# Conflicts:
#	src/views/services/serviceDirective/components/ConfigServiceDirectiveForm.vue
This commit is contained in:
yangjun 2025-08-25 15:01:52 +08:00
commit 04fcc7e7db
38 changed files with 4528 additions and 190 deletions

View File

@ -2,7 +2,7 @@
VITE_USE_MOCK = false VITE_USE_MOCK = false
# 发布路径 # 发布路径
VITE_PUBLIC_PATH = /biz103 VITE_PUBLIC_PATH = /biz101
# 是否启用gzip或brotli压缩 # 是否启用gzip或brotli压缩
# 选项值: gzip | brotli | none # 选项值: gzip | brotli | none
@ -13,10 +13,10 @@ VITE_BUILD_COMPRESS = 'gzip'
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
#后台接口父地址(必填) #后台接口父地址(必填)
VITE_GLOB_API_URL=/nursingunit103 VITE_GLOB_API_URL=/nursingunit101
#后台接口全路径地址(必填) #后台接口全路径地址(必填)
VITE_GLOB_DOMAIN_URL=https://www.focusnu.com/nursingunit103 VITE_GLOB_DOMAIN_URL=https://www.focusnu.com/nursingunit101
# 接口父路径前缀 # 接口父路径前缀
VITE_GLOB_API_URL_PREFIX= VITE_GLOB_API_URL_PREFIX=

View File

@ -0,0 +1,21 @@
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm } = useMessage();
enum Api {
list = '/eldertag/canAddElderTag/list',
exportXls = '/eldertag/canAddElderTag/exportXls',
}
/**
*
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
/**
* api
* @param params
*/
export const getExportUrl = Api.exportXls;

View File

@ -0,0 +1,31 @@
import { BasicColumn } from '/@/components/Table';
import { FormSchema } from '/@/components/Table';
import { rules } from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
import { getWeekMonthQuarterYear } from '/@/utils';
//列表数据
export const columns: BasicColumn[] = [
{
title: '所属机构',
align: 'center',
dataIndex: 'sysOrgCode_dictText',
},
{
title: '标签类型',
align: 'center',
dataIndex: 'type_dictText',
},
{
title: '标签名称',
align: 'center',
dataIndex: 'tagName',
},
{
title: '价格(元)',
align: 'center',
dataIndex: 'price',
},
];
// 高级查询数据
export const superQuerySchema = {};

View File

@ -0,0 +1,248 @@
<template>
<div>
<!--查询区域-->
<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="sysOrgCode">
<template #label><span title="所属机构">所属机构</span></template>
<j-dict-select-tag placeholder="请选择所属机构" v-model:value="queryParam.sysOrgCode" :orgCode="'ope'"
dictCode="sys_depart,depart_name,org_code" allow-clear />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="type">
<template #label><span title="标签类型">标签类型</span></template>
<j-dict-select-tag v-model:value="queryParam.type" dictCode="elder_tag_type" placeholder="请选择标签类型"
allowClear :ignoreDisabled="true" />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="tagName">
<template #label><span title="标签名称">标签名称</span></template>
<JInput v-model:value="queryParam.tagName" 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>
<!--引用表格-->
<BasicTable @register="registerTable">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
</template>
<template v-slot:bodyCell="{ column, record, index, text }">
</template>
</BasicTable>
<!-- 表单区域 -->
<CanAddElderTagModal ref="registerModal" @success="handleSuccess"></CanAddElderTagModal>
</div>
</template>
<script lang="ts" name="canadddirective-canAddElderTag" setup>
import { ref, reactive } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { columns, superQuerySchema } from './CanAddElderTag.data';
import { list, getExportUrl } from './CanAddElderTag.api';
import { downloadFile } from '/@/utils/common/renderUtils';
import CanAddElderTagModal from './components/CanAddElderTagModal.vue'
import { useUserStore } from '/@/store/modules/user';
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
import JInput from "/@/components/Form/src/jeecg/components/JInput.vue";
import { useMessage } from '/@/hooks/web/useMessage';
import { syncElderTag } from '/@/views/synchronization/eldertag/eldertag/ElderTag.api';
const props = defineProps({
elderTagMainOrgInfo: {},
existETIds: [],
})
const emit = defineEmits(['refreshExistIds']);
const { createMessage, createConfirm } = useMessage();
const formRef = ref();
const queryParam = reactive<any>({});
const toggleSearchStatus = ref<boolean>(false);
const registerModal = ref();
const userStore = useUserStore();
//table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '可新增长者标签',
api: list,
columns,
canResize: false,
useSearchForm: false,
showActionColumn: false,
actionColumn: {
width: 120,
fixed: 'right',
},
beforeFetch: async (params) => {
queryParam.existElderTagIds = props.existETIds.map(item => item.id).join(',')
return Object.assign(params, queryParam);
},
},
exportConfig: {
name: "可新增标签",
url: getExportUrl,
params: queryParam,
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = tableContext;
const labelCol = reactive({
xs: 24,
sm: 4,
xl: 6,
xxl: 5
});
const wrapperCol = reactive({
xs: 24,
sm: 20,
xl: 18,
xxl: 19
});
/**
* 详情
*/
function handleDetail(record: Recordable) {
registerModal.value.disableSubmit = true;
registerModal.value.edit(record);
}
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
// /**
// *
// */
// function handlePull(record) {
// createConfirm({
// iconType: 'warning',
// title: '',
// content: '' + record.sysOrgCode_dictText + '' + record.type_dictText + ' - ' + record.tagName + '' + props.elderTagMainOrgInfo.departName,
// okText: '',
// cancelText: '',
// onOk: () => {
// syncElderTag(
// record.sysOrgCode,
// {
// syncIds: record.tagId,
// upIds: '',
// syncOrgCodes: props.elderTagMainOrgInfo.orgCode,
// syncOption: 'all',
// }
// ).then(res => {
// createMessage.success(',!')
// emit('refreshExistIds', props.elderTagMainOrgInfo)
// }).catch(() => {
// createMessage.error('')
// })
// }
// });
// }
/**
* 操作栏
*/
function getTableAction(record) {
return [
// {
// label: '',
// onClick: handleDetail.bind(null, record),
// },
// {
// label: '',
// onClick: handlePull.bind(null, record),
// }
];
}
/**
* 下拉操作栏
*/
function getDropDownAction(record) {
return [
]
}
/**
* 查询
*/
function searchQuery() {
reload();
}
/**
* 重置
*/
function searchReset() {
formRef.value.resetFields();
selectedRowKeys.value = [];
//
reload();
}
defineExpose({
searchReset,
reload,
})
</script>
<style lang="less" scoped>
.jeecg-basic-table-form-container {
padding: 0;
margin-bottom: 14px;
.table-page-search-submitButtons {
display: block;
margin-bottom: 0px;
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: 14px;
height: 32px;
}
:deep(.ant-picker),
:deep(.ant-input-number) {
width: 100%;
}
}
</style>

View File

@ -0,0 +1,120 @@
<template>
<a-spin :spinning="confirmLoading">
<JFormContainer :disabled="disabled">
<template #detail>
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol"
name="CanAddElderTagForm">
<a-row>
<a-col :span="24">
<a-form-item label="标签类型" v-bind="validateInfos.type" id="ElderTagForm-type" name="type">
<j-dict-select-tag v-model:value="formData.type" dictCode="elder_tag_type" placeholder="请选择标签类型"
allowClear :ignoreDisabled="true" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="标签名称" v-bind="validateInfos.tagName" id="ElderTagForm-tagName" name="tagName">
<a-input v-model:value="formData.tagName" placeholder="请输入标签名称" allow-clear></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="价格(元)" v-bind="validateInfos.price" id="ElderTagForm-price" name="price">
<a-input-number v-model:value="formData.price" placeholder="请输入价格" style="width: 100%" :min="0"
:max="99.99" :precision="2" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="图标" v-bind="validateInfos.pic" id="ElderTagForm-pic" name="pic">
<JImageUpload :fileMax="1" v-model:value="formData.pic"></JImageUpload>
</a-form-item>
</a-col>
</a-row>
</a-form>
</template>
</JFormContainer>
</a-spin>
</template>
<script lang="ts" setup>
import { ref, reactive, defineExpose, nextTick, defineProps, computed, onMounted } from 'vue';
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
import { getValueType } from '/@/utils';
import { Form } from 'ant-design-vue';
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
const props = defineProps({
formDisabled: { type: Boolean, default: false },
formData: { type: Object, default: () => ({}) },
formBpm: { type: Boolean, default: true }
});
const formRef = ref();
const useForm = Form.useForm;
const emit = defineEmits(['register', 'ok']);
const formData = reactive<Record<string, any>>({
id: '',
type: '',
tagName: '',
price: undefined,
createTime: '',
sysOrgCode: '',
});
const { createMessage } = useMessage();
const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } });
const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
const confirmLoading = ref<boolean>(false);
//
const validatorRules = reactive({
});
const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: false });
//
const disabled = computed(() => {
if (props.formBpm === true) {
if (props.formData.disabled === false) {
return false;
} else {
return true;
}
}
return props.formDisabled;
});
/**
* 新增
*/
function add() {
edit({});
}
/**
* 编辑
*/
function edit(record) {
nextTick(() => {
resetFields();
const tmpData = {};
Object.keys(formData).forEach((key) => {
if (record.hasOwnProperty(key)) {
tmpData[key] = record[key]
}
})
//
Object.assign(formData, tmpData);
});
}
defineExpose({
add,
edit,
});
</script>
<style lang="less" scoped>
.antd-modal-form {
padding: 14px;
}
</style>

View File

@ -0,0 +1,81 @@
<template>
<a-drawer :title="title" width="50vw" v-model:visible="visible" :closable="true"
:footer-style="{ textAlign: 'right' }" @cancel="handleCancel">
<template #footer>
<a-button @click="handleCancel" style="margin-right: 8px;">关闭</a-button>
</template>
<CanAddElderTagForm ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></CanAddElderTagForm>
</a-drawer>
</template>
<script lang="ts" setup>
import { ref, nextTick, defineExpose } from 'vue';
import CanAddElderTagForm from './CanAddElderTagForm.vue'
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
const title = ref<string>('');
const width = ref<number>(800);
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();
const emit = defineEmits(['register', 'success']);
/**
* 新增
*/
function add() {
title.value = '新增';
visible.value = true;
nextTick(() => {
registerForm.value.add();
});
}
/**
* 编辑
* @param record
*/
function edit(record) {
title.value = disableSubmit.value ? '详情' : '编辑';
visible.value = true;
nextTick(() => {
registerForm.value.edit(record);
});
}
/**
* 确定按钮点击事件
*/
function handleOk() {
registerForm.value.submitForm();
}
/**
* form保存回调事件
*/
function submitCallback() {
handleCancel();
emit('success');
}
/**
* 取消按钮回调事件
*/
function handleCancel() {
visible.value = false;
}
defineExpose({
add,
edit,
disableSubmit,
});
</script>
<style lang="less">
/**隐藏样式-modal确定按钮 */
.jee-hidden {
display: none !important;
}
</style>
<style lang="less" scoped></style>

View File

@ -14,6 +14,7 @@ enum Api {
listByDS = '/elder/elderTag/listByDS', listByDS = '/elder/elderTag/listByDS',
idListByDS = '/elder/elderTag/idListByDS', idListByDS = '/elder/elderTag/idListByDS',
syncElderTag = '/elder/elderTag/syncElderTag', syncElderTag = '/elder/elderTag/syncElderTag',
compareList = '/elder/elderTag/compareList',
} }
/** /**
@ -94,4 +95,11 @@ export const idListByDS = (params) => defHttp.get({ url: Api.idListByDS, params
*/ */
export const syncElderTag = (dataSourceCode: string, params: any) => { export const syncElderTag = (dataSourceCode: string, params: any) => {
return defHttp.post({ url: `${Api.syncElderTag}?sourceOrgCode=${encodeURIComponent(dataSourceCode)}`, params }); return defHttp.post({ url: `${Api.syncElderTag}?sourceOrgCode=${encodeURIComponent(dataSourceCode)}`, params });
}; };
/**
*
* @param params compareOrgCode
* @returns
*/
export const compareList = (params) => defHttp.get({ url: Api.compareList, params });

View File

@ -26,11 +26,11 @@ export const columns: BasicColumn[] = [
dataIndex: 'pic', dataIndex: 'pic',
customRender: render.renderImage, customRender: render.renderImage,
}, },
{ // {
title: '排序', // title: '排序',
align: 'center', // align: 'center',
dataIndex: 'sort', // dataIndex: 'sort',
}, // },
{ {
title: '是否启用', title: '是否启用',
align: 'center', align: 'center',

View File

@ -45,6 +45,10 @@
preIcon="ant-design:plus-outlined"> 新增</a-button> preIcon="ant-design:plus-outlined"> 新增</a-button>
<a-button type="primary" class="btnPrivate" @click="handleDirectiveMainOpen" v-show="isShowETM" <a-button type="primary" class="btnPrivate" @click="handleDirectiveMainOpen" v-show="isShowETM"
preIcon="ant-design:profile-outlined">标准标签库</a-button> 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" style="margin-right: 10px;"
v-show="ownOrgCode == mainOrgCode" @click="handleLookNewDirectives">差异标签</a-button>
</template> </template>
<!--操作栏--> <!--操作栏-->
<template #action="{ record }"> <template #action="{ record }">
@ -55,6 +59,30 @@
</BasicTable> </BasicTable>
<!-- 表单区域 --> <!-- 表单区域 -->
<ElderTagModal ref="registerModal" @success="handleSuccess"></ElderTagModal> <ElderTagModal ref="registerModal" @success="handleSuccess"></ElderTagModal>
<!-- 差异标签 -->
<a-drawer v-model:visible="newElderTagVisible" title="差异标签" width="85vw" :footer-style="{ textAlign: 'right' }"
:bodyStyle="{ padding: '14px', height: '80vh', display: 'flex', flexDirection: 'column', overflow: 'auto' }"
wrapClassName="org-list-modal" @cancel="handleCancelNewElderTag">
<template #footer>
<a-button @click="handleCancelNewElderTag" type="primary">关闭</a-button>
</template>
<div style="padding:0px 8px;">
<CanAddElderTagList ref="canAddElderTagRef" :elderTagMainOrgInfo="elderTagMainOrgInfo" :existETIds="existETIds"
@refreshExistIds="refreshDMExistedIds"></CanAddElderTagList>
</div>
</a-drawer>
<!-- 差异比对 -->
<a-drawer title="差异比对" width="80vw" :open="compareListOpen" @close="onCompareListClose"
:footer-style="{ textAlign: 'right' }" :bodyStyle="{ padding: '14px' }">
<template #footer>
<a-button type="primary" @click="onCompareListClose" style="margin-right: 10px;">关闭</a-button>
</template>
<CompareElderTagList ref="compareListRef" v-if="compareListOpen" :ownOrgCode="ownOrgCode"
:ownOrgName="ownOrgName">
</CompareElderTagList>
</a-drawer>
</div> </div>
</template> </template>
@ -63,7 +91,7 @@ import { ref, reactive, onMounted } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table'; import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage'; import { useListPage } from '/@/hooks/system/useListPage';
import { columns, superQuerySchema } from './ElderTag.data'; import { columns, superQuerySchema } from './ElderTag.data';
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl } from './ElderTag.api'; import { list, idListByDS, deleteOne, batchDelete, getImportUrl, getExportUrl } from './ElderTag.api';
import { downloadFile } from '/@/utils/common/renderUtils'; import { downloadFile } from '/@/utils/common/renderUtils';
import ElderTagModal from './components/ElderTagModal.vue' import ElderTagModal from './components/ElderTagModal.vue'
import { useUserStore } from '/@/store/modules/user'; import { useUserStore } from '/@/store/modules/user';
@ -72,6 +100,8 @@ import JInput from "/@/components/Form/src/jeecg/components/JInput.vue";
import { queryByKey } from '/@/views/admin/sysconfig/SysConfig.api' import { queryByKey } from '/@/views/admin/sysconfig/SysConfig.api'
import { getOrgInfo } from '@/api/common/api' import { getOrgInfo } from '@/api/common/api'
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
import CanAddElderTagList from '/@/views/elder/canaddet/CanAddElderTagList.vue'
import CompareElderTagList from './components/CompareElderTagList.vue'
const formRef = ref(); const formRef = ref();
const queryParam = reactive<any>({}); const queryParam = reactive<any>({});
@ -80,6 +110,14 @@ const registerModal = ref();
const userStore = useUserStore(); const userStore = useUserStore();
const isShowETM = ref(false)// const isShowETM = ref(false)//
const mainOrgCode = ref()// const mainOrgCode = ref()//
const canAddElderTagRef = ref()
const newElderTagVisible = ref(false)
const existETIds = ref([])//id
const ownOrgCode = ref('') //
const ownOrgName = ref('') //
const elderTagMainOrgInfo = ref()
const compareListRef = ref()
const compareListOpen = ref(false)
//table //table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({ const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: { tableProps: {
@ -92,16 +130,16 @@ const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
width: 120, width: 120,
fixed: 'right', fixed: 'right',
}, },
defSort: { // defSort: {
column: 'sort', // column: 'sort',
order: 'asc', // order: 'asc',
}, // },
beforeFetch: async (params) => { beforeFetch: async (params) => {
return Object.assign(params, queryParam); return Object.assign(params, queryParam);
}, },
}, },
exportConfig: { exportConfig: {
name: "长者标签", name: "差异标签",
url: getExportUrl, url: getExportUrl,
params: queryParam, params: queryParam,
}, },
@ -225,12 +263,50 @@ function handleDirectiveMainOpen() {
} }
async function getElderTagMainOrgCode() { async function getElderTagMainOrgCode() {
let { orgCode } = await getOrgInfo() let { orgCode, orgName } = await getOrgInfo()
ownOrgCode.value = orgCode
ownOrgName.value = orgName
let { configValue } = await queryByKey({ key: 'elder_tag_main_org_code' }) let { configValue } = await queryByKey({ key: 'elder_tag_main_org_code' })
mainOrgCode.value = configValue mainOrgCode.value = configValue
if (orgCode != configValue) isShowETM.value = true if (orgCode != configValue) isShowETM.value = true
} }
//
async function refreshDMExistedIds(dmOrgInfo, izReset = false, izQuery = true) {
await idListByDS({ dataSourceCode: 'master' }).then(res => {
existETIds.value = res.records
if (izReset) {
canAddElderTagRef.value?.searchReset()
} else {
canAddElderTagRef.value?.reload()
}
})
}
async function handleLookNewDirectives() {
await refreshDMExistedIds(elderTagMainOrgInfo.value, true)
newElderTagVisible.value = true
}
/**
* 关闭新增指令
*/
function handleCancelNewElderTag() {
newElderTagVisible.value = false
}
/**
* 差异比对
*/
function handleCompare() {
compareListOpen.value = true
}
function onCompareListClose() {
compareListOpen.value = false
}
// //
onMounted(() => { onMounted(() => {
getElderTagMainOrgCode() getElderTagMainOrgCode()

View File

@ -0,0 +1,353 @@
<template>
<div class="compare-table-wrap">
<div style="margin-bottom: 14px;width: 100%;">
<a-button type="primary" style="float: right;" @click="showTargetOrgListModal"
:disabled="loading">目标机构</a-button>
</div>
<div class="table-card">
<!-- 表头两级 -->
<div class="thead">
<!-- 顶层 -->
<div class="thead-top">
<div class="th"></div>
<div class="th"></div>
<div class="th"></div>
<div class="th th-org" style="grid-column:4 / span 2;">源机构</div>
<div class="th th-org" style="grid-column:6 / span 2;">目标机构</div>
</div>
<!-- 次级 -->
<div class="thead-sub">
<div class="th">标签类型</div>
<div class="th">标签名称</div>
<div class="th">标签说明</div>
<div class="th th-name-sub">名称</div>
<div class="th th-exist-sub">是否存在</div>
<div class="th th-name-sub">名称</div>
<div class="th th-exist-sub">是否存在</div>
</div>
</div>
<!-- 表体 -->
<div v-if="!targetOrgInfo && !loading" class="status">未选择目标机构</div>
<div v-else class="body-div">
<div v-if="loading" class="status">加载中</div>
<div v-else-if="rows.length === 0" class="status">暂无数据</div>
<div v-else class="tbody">
<div class="tr" v-for="item in rows" :key="item.id || item.directiveName || item.instructionName"
:data-rank="rank(item)">
<div class="td td-tag" :title="item.instructionName || '-'">{{ item.instructionName || '-' }}
</div>
<div class="td td-category" :title="item.categoryName || '-'">{{ item.categoryName || '-' }}
</div>
<div class="td td-type" :title="item.typeName || '-'">{{ item.typeName || '-' }}</div>
<div class="td td-name" :title="item.directiveName || '-'">{{ item.directiveName || '-' }}</div>
<div class="td td-cycle" :title="item.cycleTypeName || '-'">{{ item.cycleTypeName || '-' }}
</div>
<!-- 源机构 -->
<div class="td td-org-name" :title="ownOrgName || '-'">{{ ownOrgName || '-' }}</div>
<div class="td td-org-exist center" :title="item.ownExist ? '源机构已存在' : '源机构不存在'">
<div class="org-badge">
<svg v-if="item.ownExist" class="icon check" viewBox="0 0 24 24" aria-hidden="true">
<path
d="M20.285 6.709l-11.39 11.39-5.18-5.18 1.414-1.414 3.766 3.766 9.976-9.976z" />
</svg>
<svg v-else class="icon cross" viewBox="0 0 24 24" aria-hidden="true">
<path
d="M18.3 5.71L12 12.01 5.7 5.71 4.29 7.12 10.59 13.42 4.29 19.72 5.7 21.13 12 14.83 18.3 21.13 19.71 19.72 13.41 13.42 19.71 7.12z" />
</svg>
</div>
</div>
<!-- 目标机构 -->
<div class="td td-org-name" :title="targetOrgInfo.comName || '-'">{{ targetOrgInfo.comName ||
'-' }}</div>
<div class="td td-org-exist center" :title="item.targetExist ? '目标机构已存在' : '目标机构不存在'">
<div class="org-badge">
<svg v-if="item.targetExist" class="icon check" viewBox="0 0 24 24" aria-hidden="true">
<path
d="M20.285 6.709l-11.39 11.39-5.18-5.18 1.414-1.414 3.766 3.766 9.976-9.976z" />
</svg>
<svg v-else class="icon cross" viewBox="0 0 24 24" aria-hidden="true">
<path
d="M18.3 5.71L12 12.01 5.7 5.71 4.29 7.12 10.59 13.42 4.29 19.72 5.7 21.13 12 14.83 18.3 21.13 19.71 19.72 13.41 13.42 19.71 7.12z" />
</svg>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<a-modal v-model:visible="targetOrgListVisible" title="请选择目标机构" width="90vw" @cancel="handleCancelTarget"
:bodyStyle="{ padding: '14px', height: '70vh', display: 'flex', flexDirection: 'column', overflow: 'auto' }">
<template #footer>
<a-button @click="handleCancelTarget" type="primary">取消</a-button>
<a-button @click="handleGetTarget" type="primary">确认</a-button>
</template>
<OrgListCom class="step-content" ref="targetOrgListComRef" @handleOrgChoose="handleTargetOrgChoose"
:showChoose="true" :showDirectiveChoose="true" :pageSize="-1" :excludeOrgCode="ownOrgCode" />
</a-modal>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { compareList } from '../ElderTag.api';
import OrgListCom from '/@/views/orgcom/OrgListCom.vue';
const props = defineProps({
ownOrgCode: '',//
ownOrgName: '',//
});
const targetOrgInfo = ref('')//
type Row = {
id?: string;
instructionName?: string;
categoryName?: string;
typeName?: string;
directiveName?: string;
cycleTypeName?: string;
ownExist?: boolean;
targetExist?: boolean;
};
const rows = ref<Row[]>([]);
const loading = ref(false);
const targetOrgListVisible = ref(false);
const targetOrgListComRef = ref();
function rank(it: Row) {
if (it.ownExist && it.targetExist) return 'both';
if (it.ownExist) return 'own-only';
return 'target-only';
}
function handleCancelTarget() {
targetOrgListVisible.value = false;
targetOrgListComRef.value?.resetSeleted?.([]);
}
function showTargetOrgListModal() {
targetOrgListComRef.value?.reload?.()
targetOrgListVisible.value = true;
}
function handleGetTarget() {
if (!targetOrgInfo.value) {
targetOrgListVisible.value = false;
return;
}
initData()
handleCancelTarget()
}
function handleTargetOrgChoose(orgInfo_: any) {
targetOrgInfo.value = orgInfo_
}
async function initData() {
loading.value = true;
rows.value = [];
try {
let res = await compareList({ compareOrgCode: targetOrgInfo.value.orgCode })
if (Array.isArray(res)) rows.value = res;
else if (res && Array.isArray(res.result)) rows.value = res.result;
else if (res && Array.isArray(res.list)) rows.value = res.list;
else if (res && Array.isArray(res.data)) rows.value = res.data;
else rows.value = res || [];
} catch (e) {
rows.value = [];
console.error('compareList error', e);
} finally {
loading.value = false;
}
}
</script>
<style lang="less" scoped>
.compare-table-wrap {
padding: 16px;
background: #f6f8fb;
font-family: "PingFang SC", "Microsoft YaHei", Arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
}
.table-card {
width: 100%;
max-width: 100%;
background: #fff;
border-radius: 8px;
overflow: hidden;
border: 1px solid #e6eef8;
box-shadow: 0 6px 18px rgba(2, 6, 23, 0.04);
}
.thead {
background: linear-gradient(180deg, #fbfdff, #ffffff);
border-bottom: 1px solid #e6eef8;
}
.thead-top,
.thead-sub,
.tr {
display: grid;
gap: 12px;
align-items: center;
justify-items: center;
}
.thead-top {
grid-template-columns: 1fr 2fr 3fr 2fr 1fr 2fr 1fr;
padding: 12px 14px 0px 14px;
font-weight: 600;
color: #374151;
}
.thead-sub {
grid-template-columns: 1fr 2fr 3fr 2fr 1fr 2fr 1fr;
padding: 0px 14px 8px 14px;
border-bottom: 1px solid #e6eef8;
color: #374151;
font-size: 13px;
font-weight: 600;
}
.th {
padding: 6px 4px;
text-align: center;
}
.tbody {
display: flex;
flex-direction: column;
}
.tr {
grid-template-columns: 1fr 2fr 3fr 2fr 1fr 2fr 1fr;
padding: 12px 14px;
background: #fff;
border-bottom: 1px solid #eef6fb;
}
.tr:last-child {
border-bottom: none;
}
.td {
padding: 6px 4px;
font-size: 14px;
color: #111827;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: center;
width: 100%;
}
.td-org-name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.td-org-exist {
display: flex;
align-items: center;
justify-content: center;
}
.org-badge {
width: 36px;
height: 36px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
background: #fbfdff;
}
.icon {
width: 20px;
height: 20px;
fill: currentColor;
}
.icon.check {
color: #10b981;
}
.icon.cross {
color: #ef4444;
}
.status {
padding: 14px;
background: #fff;
border-radius: 8px;
color: #6b7280;
text-align: center;
box-shadow: 0 6px 14px rgba(2, 6, 23, 0.03);
margin-top: 8px;
width: 100%;
}
.body-div {
height: 65vh;
overflow-y: scroll;
// scrollbar-width: none;
// -ms-overflow-style: none;
}
// .body-div::-webkit-scrollbar {
// width: 0;
// height: 0;
// background: transparent;
// }
@media (max-width: 1000px) {
.thead-top,
.thead-sub,
.tr {
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 80px 80px 80px;
}
.td-name,
.th.th-name {
display: none;
}
}
@media (max-width: 700px) {
.thead {
display: none;
}
.tr {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
padding: 12px;
}
.td {
white-space: normal;
text-align: center;
}
.center {
justify-content: center;
gap: 8px;
}
}
</style>

View File

@ -20,11 +20,11 @@ export const columns: BasicColumn[] = [
align: 'center', align: 'center',
dataIndex: 'price', dataIndex: 'price',
}, },
{ // {
title: '排序', // title: '排序',
align: 'center', // align: 'center',
dataIndex: 'sort', // dataIndex: 'sort',
}, // },
{ {
title: '是否启用', title: '是否启用',
align: 'center', align: 'center',

View File

@ -30,11 +30,11 @@
<JImageUpload v-else :fileMax="1" v-model:value="formData.pic"></JImageUpload> <JImageUpload v-else :fileMax="1" v-model:value="formData.pic"></JImageUpload>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="24"> <!-- <a-col :span="24">
<a-form-item label="排序" v-bind="validateInfos.sort" id="ElderTagForm-sort" name="sort"> <a-form-item label="排序" v-bind="validateInfos.sort" id="ElderTagForm-sort" name="sort">
<a-input-number v-model:value="formData.sort" placeholder="请输入排序" style="width: 100%" /> <a-input-number v-model:value="formData.sort" placeholder="请输入排序" style="width: 100%" />
</a-form-item> </a-form-item>
</a-col> </a-col> -->
<a-col :span="24"> <a-col :span="24">
<a-form-item label="是否启用" v-bind="validateInfos.izEnabled" id="ElderTagForm-izEnabled" name="izEnabled"> <a-form-item label="是否启用" v-bind="validateInfos.izEnabled" id="ElderTagForm-izEnabled" name="izEnabled">
<j-dict-select-tag type='radio' v-model:value="formData.izEnabled" dictCode="iz_enabled" <j-dict-select-tag type='radio' v-model:value="formData.izEnabled" dictCode="iz_enabled"

View File

@ -93,7 +93,7 @@ const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
pageSizeOptions: ['15', '50', '70', '100'], pageSizeOptions: ['15', '50', '70', '100'],
}, },
actionColumn: { actionColumn: {
width: 200, width: 90,
fixed: 'right', fixed: 'right',
}, },
defSort: { defSort: {

View File

@ -0,0 +1,96 @@
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from "/@/hooks/web/useMessage";
const { createConfirm } = useMessage();
enum Api {
list = '/admin/orgapplyinfo/orgApplyInfo/list',
save='/admin/orgapplyinfo/orgApplyInfo/add',
edit='/admin/orgapplyinfo/orgApplyInfo/edit',
editCg='/admin/orgapplyinfo/orgApplyInfo/editCg',
submitContract='/admin/orgapplyinfo/orgApplyInfo/submitContract',
deleteOne = '/admin/orgapplyinfo/orgApplyInfo/delete',
deleteBatch = '/admin/orgapplyinfo/orgApplyInfo/deleteBatch',
importExcel = '/admin/orgapplyinfo/orgApplyInfo/importExcel',
exportXls = '/admin/orgapplyinfo/orgApplyInfo/exportXls',
getOrgInfo = '/admin/orgapplyinfo/orgApplyInfo/getOrgInfo',
}
/**
* api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* api
*/
export const getImportUrl = Api.importExcel;
/**
*
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
/**
* sys_depart信息
* @param params orgCode部门编码
* @returns
*/
export const getOrgInfo = (params) => defHttp.get({ url: Api.getOrgInfo, params });
/**
*
* @param params
* @param handleSuccess
*/
export const deleteOne = (params,handleSuccess) => {
return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
/**
*
* @param params
* @param handleSuccess
*/
export const batchDelete = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
});
}
/**
*
* @param params
* @param isUpdate
*/
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params }, { isTransformResponse: false });
}
export const editCg = (params, isUpdate) => {
return defHttp.post({ url: Api.editCg, params }, { isTransformResponse: false });
}
/**
*
* @param params
* @param isUpdate
*/
export const submitContract = (params) => {
return defHttp.post({ url: Api.submitContract, params });
}

View File

@ -0,0 +1,153 @@
<template>
<a-card :class="{
'selected-card': isSelected,
'directive-selected-card': isDirectiveSelected,
'org-card': clickable
}" style="width: 100%; border-radius: 8px;" :style="{ cursor: clickable ? 'pointer' : 'default' }"
:bodyStyle="{ padding: '24px' }" @click="handleClick">
<div>
<a-row style="font-weight: normal; margin-bottom: 12px;">
<a-col :span="existTagFunc() ? 16 : 21">
<div>
<span class="ellipsis-one-lines1" :title="orgInfo.departName" style="font-size: 17px; font-weight: bold;">{{
orgInfo.departName
}}</span>
</div>
</a-col>
<a-col :span="existTagFunc() ? 8 : 3" style="text-align: right;">
<div style="display: flex; align-items: center; justify-content: flex-end; gap: 8px;">
<span v-if="isDirectiveMain"
style="color: #909399; font-size: 12px; font-weight: bold; white-space: nowrap;">
标准指令库
</span>
<span v-if="isElderTagMain"
style="color: #909399; font-size: 12px; font-weight: bold; white-space: nowrap;">
标准标签库
</span>
<div class="zxClass" :class="{ 'zxbkClass': existTagFunc() }" style="min-width: 35px;">{{ orgInfo.orgCode
}}
</div>
</div>
</a-col>
</a-row>
<div style="position: relative;">
<div>
<div><span style="color: #909399;">机构负责人</span>{{ orgInfo.orgLeader }}</div>
<div><span style="color: #909399;">负责人电话</span>{{ orgInfo.orgLeaderPhone }}</div>
</div>
<div class="org-address" :style="{ backgroundImage: `url(${bg})` }">
<span class="ellipsis-one-lines2" :title="orgInfo.comRegisterAddress">{{ orgInfo.comRegisterAddress }}</span>
</div>
<div
style="font-size: 12px; display: flex; justify-content: space-between; align-items: center; margin-top: 12px;">
<span style="color: #909399;">加盟时间{{ orgInfo.franchiseTime?.substring(0, 10) }}</span>
<a-button style="font-size: 12px;" v-show="showDetail" type="link" size="small"
@click.stop="handleDetail">了解更多</a-button>
</div>
</div>
</div>
</a-card>
</template>
<script setup lang="ts">
import { defineProps, defineEmits } from 'vue'
import bg from './orgaddressbk.png'
const props = defineProps({
orgInfo: { type: Object, required: true },
layout: { type: String, default: 'full' },
isSelected: { type: Boolean, default: false },
isDirectiveSelected: { type: Boolean, default: false },
isDirectiveMain: { type: Boolean, default: false },//
isElderTagMain: { type: Boolean, default: false },//
showDetail: { type: Boolean, default: false },
clickable: { type: Boolean, default: false }
})
const emit = defineEmits(['click', 'detail'])
const existTagFunc = () => {
return props.isDirectiveMain || props.isElderTagMain
}
const handleClick = () => {
emit('click', props.orgInfo)
}
const handleDetail = () => {
emit('detail', props.orgInfo)
}
</script>
<style lang="less" scoped>
.zxClass {
font-size: 12px;
background-color: white;
border: 1px solid #e4e4e4;
border-radius: 8px;
height: 25px;
color: #7c7c7c;
line-height: 25px;
padding: 0 8px;
flex-shrink: 0;
}
.zxbkClass {
background-color: #F5F7FF;
}
.selected-card {
border: 2px solid #1890ff;
box-shadow: 0 0 8px rgba(24, 144, 255, 0.3);
}
.directive-selected-card {
border: 2px solid #1890FF;
box-shadow: 0 0 8px rgba(37, 149, 255, 0.3);
}
.org-card {
&:hover {
border-color: #55a9f8;
box-shadow: 0 2px 8px rgba(37, 149, 255, 0.3);
}
}
:deep .ant-divider {
margin: 0 0 8px 0;
}
.org-address {
width: 100%;
height: 65px;
background-color: #f8fbff;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
padding: 13px;
padding-right: 100px;
color: #696c7f;
display: flex;
align-items: center;
margin-top: 10px;
border-radius: 10px;
font-size: 12.5px;
}
.ellipsis-one-lines1 {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
text-overflow: ellipsis;
}
.ellipsis-one-lines2 {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1.8;
}
</style>

View File

@ -0,0 +1,146 @@
<template>
<div>
<a-row>
<a-col v-for="(item, index) in orgTableList.records" :key="item.id" :xs="24" :sm="24"
:md="props.layout == 'full' ? 12 : 8" :lg="props.layout == 'full' ? 12 : 8" :xl="props.layout == 'full' ? 8 : 8"
:xxl="props.layout == 'full' ? 6 : 8" :xxxl="props.layout == 'full' ? 4 : 8"
:style="{ 'padding-right': ((index + 1) % 4 != 0) ? '14px' : '0px', 'padding-bottom': '14px' }">
<OrgCard :orgInfo="item" :layout="props.layout"
:is-selected="selectedOrgs.some(org => org.orgCode === item.orgCode)"
:is-directive-selected="directiveMainSelectedOrg?.orgCode === item.orgCode"
:is-elder-tag-main="etmOrg?.orgCode === item.orgCode" :show-detail="props.showDetail"
:clickable="props.showChoose || props.showDirectiveChoose" @click="handleCardClick" @detail="handleDetail" />
</a-col>
<a-col v-if="orgTableList.length == 0">
<div style="margin: 30px auto;">
<a-empty />
</div>
</a-col>
</a-row>
<div
style="float:right;bottom: 20px;z-index: 999;padding: 8px 16px;border-radius: 4px;display: flex;align-items: center;"
v-show="props.layout == 'full' && pageSize != -1">
<span style="margin-right: 10px;"> {{ orgTableList.total }} 条数据</span>
<Pagination showLessItems v-model:current="pageParams.pageNo" :pageSize="pageParams.pageSize" size="small"
show-quick-jumper :total="orgTableList.total" @change="reload" />
</div>
</div>
</template>
<script setup lang="ts" name="synchronization-directive2">
import { ref, reactive, onMounted } from 'vue'
import { Pagination } from 'ant-design-vue'
import { getOrgInfo } from './OrgApplyInfo.api'
import OrgCard from './OrgCardCom.vue'
const props = defineProps({
showChoose: { type: Boolean, default: false },
pageSize: { type: Number, default: 8 },
showDetail: { type: Boolean, default: false },
title: { type: String, default: '' },
allowMultipleSelection: { type: Boolean, default: false },
layout: { type: String, default: 'full' },
excludeOrgCode: { type: String, default: '' },
showDirectiveMain: { type: Boolean, default: false },
showDirectiveChoose: { type: Boolean, default: false },
showDMTip: { type: Boolean, default: false },
})
const emit = defineEmits(['handleOrgDetail', 'handleOrgChoose'])
const orgTableList = ref<any>({ records: [], total: 0 })
const queryParam = reactive<any>({})
const pageParams = ref({ pageNo: 1, pageSize: props.pageSize })
const directiveMainSelectedOrg = ref<any>(null)
const etmOrg = ref<any>('')
const selectedOrgs = ref<any[]>([])
function handleCardClick(item: any) {
if (props.showDirectiveChoose) {
directiveMainSelectedOrg.value = item
emit('handleOrgChoose', item)
}
if (props.showChoose) {
if (props.allowMultipleSelection) {
if (selectedOrgs.value.some(selected => selected.orgCode === item.orgCode)) {
selectedOrgs.value = selectedOrgs.value.filter(selected => selected.orgCode !== item.orgCode)
} else {
selectedOrgs.value.push(item)
}
} else {
selectedOrgs.value = [item]
}
}
}
function commitOrgsInfo() {
emit('handleOrgChoose', selectedOrgs.value)
}
function handleDetail(item: any) {
emit('handleOrgDetail', item)
}
function reload() {
directiveMainSelectedOrg.value = {}
queryParam.pageSize = pageParams.value.pageSize
queryParam.pageNo = pageParams.value.pageNo
queryParam.title = props.title
if (props.layout == 'half') {
queryParam.pageSize = -1
}
getOrgInfo(queryParam).then(res => {
res.records = res.records.filter(o => o.orgCode != props.excludeOrgCode)
orgTableList.value = res
if (props.showDirectiveChoose || props.showDMTip) {
const defaultSelected = res.records.find(item => item.izElderTagMain === '0')
if (defaultSelected) {
etmOrg.value = defaultSelected
emit('handleOrgChoose', defaultSelected)
}
}
})
}
function searchReset() {
queryParam.title = null
if (props.layout == 'half') {
queryParam.pageSize = -1
}
getOrgInfo(queryParam).then(res => {
res.records = res.records.filter(o => o.orgCode != props.excludeOrgCode)
orgTableList.value = res
})
}
function checkAllOrEmpty(isCheckAll = true) {
if (isCheckAll) {
orgTableList.value.records.forEach(item => {
if (!selectedOrgs.value.some(selected => selected.orgCode === item.orgCode)) {
selectedOrgs.value.push(item);
}
});
} else {
selectedOrgs.value = [];
}
emit('handleOrgChoose', selectedOrgs.value);
}
function resetSeleted(orgs: any[]) {
selectedOrgs.value = [...orgs]
}
onMounted(() => {
reload()
})
defineExpose({
reload,
searchReset,
selectedOrgs,
checkAllOrEmpty,
commitOrgsInfo,
resetSeleted
})
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -0,0 +1,72 @@
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from "/@/hooks/web/useMessage";
const { createConfirm } = useMessage();
enum Api {
list = '/canadddirective/canAddDirective/list',
save='/canadddirective/canAddDirective/add',
edit='/canadddirective/canAddDirective/edit',
deleteOne = '/canadddirective/canAddDirective/delete',
deleteBatch = '/canadddirective/canAddDirective/deleteBatch',
importExcel = '/canadddirective/canAddDirective/importExcel',
exportXls = '/canadddirective/canAddDirective/exportXls',
}
/**
* api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* api
*/
export const getImportUrl = Api.importExcel;
/**
*
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
/**
*
* @param params
* @param handleSuccess
*/
export const deleteOne = (params,handleSuccess) => {
return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
/**
*
* @param params
* @param handleSuccess
*/
export const batchDelete = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
});
}
/**
*
* @param params
* @param isUpdate
*/
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params }, { isTransformResponse: false });
}

View File

@ -0,0 +1,83 @@
import { BasicColumn } from '/@/components/Table';
import { FormSchema } from '/@/components/Table';
import { rules } from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
import { getWeekMonthQuarterYear } from '/@/utils';
//列表数据
export const columns: BasicColumn[] = [
{
title: '所属机构',
align: 'center',
dataIndex: 'orgCode_dictText',
width:200,
},
{
title: '分类标签',
align: 'center',
dataIndex: 'instructionTag',
width: 170,
},
{
title: '服务类别',
align: 'center',
dataIndex: 'category',
width: 170,
},
{
title: '服务类型',
align: 'center',
dataIndex: 'type',
width: 170,
},
{
title: '服务指令',
align: 'center',
dataIndex: 'directiveName',
},
{
title: '周期类型',
align: 'center',
dataIndex: 'cycleType',
width: 120,
},
{
title: '收费价格(元)',
align: 'center',
dataIndex: 'tollPrice',
width: 100,
},
{
title: '提成价格(元)',
align: 'center',
dataIndex: 'comPrice',
},
{
title: '服务时长(分钟)',
align: 'center',
dataIndex: 'serviceDuration',
width: 135,
},
{
title: '服务指令描述',
align: 'center',
dataIndex: 'serviceContent',
width: 200,
},
{
title: '创建日期',
align: 'center',
dataIndex: 'createTime',
width: 160,
},
];
// 高级查询数据
export const superQuerySchema = {
instructionTag: { title: '分类标签', order: 0, view: 'text', type: 'string' },
category: { title: '服务类别', order: 1, view: 'text', type: 'string' },
type: { title: '服务类型', order: 2, view: 'text', type: 'string' },
directiveName: { title: '服务指令', order: 3, view: 'text', type: 'string' },
cycleType: { title: '周期类型', order: 4, view: 'text', type: 'string' },
createTime: { title: '创建日期', order: 5, view: 'datetime', type: 'string' },
orgCode: { title: '所属部门', order: 6, view: 'list', type: 'string', dictTable: 'sys_depart', dictCode: 'org_code', dictText: 'depart_name' },
};

View File

@ -0,0 +1,228 @@
<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" style="padding-top: 20px;">
<a-row :gutter="24">
<a-col :lg="6">
<a-form-item name="orgCode">
<template #label><span title="所属机构">所属机构</span></template>
<j-dict-select-tag placeholder="请选择所属机构" v-model:value="queryParam.orgCode" :orgCode="'ope'"
dictCode="sys_depart,depart_name,org_code" allow-clear />
</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>
<!--引用表格-->
<BasicTable @register="registerTable">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
<template v-slot:bodyCell="{ column, record, index, text }">
</template>
</BasicTable>
<!-- 表单区域 -->
<CanAddDirectiveModal ref="registerModal" @success="handleSuccess"></CanAddDirectiveModal>
</div>
</template>
<script lang="ts" name="canadddirective-canAddDirective" setup>
import { ref, reactive, onMounted } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { columns, superQuerySchema } from './CanAddDirective.data';
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl } from './CanAddDirective.api';
import CanAddDirectiveModal from './components/CanAddDirectiveDetailModal.vue'
import { useUserStore } from '/@/store/modules/user';
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
import { useMessage } from '/@/hooks/web/useMessage';
const props = defineProps({
directiveMainOrgInfo: {},
existDirectiveIds: [],
})
const emit = defineEmits(['refreshExistIds']);
const { createMessage, createConfirm } = useMessage();
const formRef = ref();
const queryParam = reactive<any>({});
const toggleSearchStatus = ref<boolean>(false);
const registerModal = ref();
const userStore = useUserStore();
//table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '可新增指令',
api: list,
columns,
canResize: false,
useSearchForm: false,
showActionColumn: false,
actionColumn: {
width: 120,
fixed: 'right',
},
pagination: {
current: 1,
pageSize: 15,
pageSizeOptions: ['15', '50', '70', '100'],
},
beforeFetch: async (params) => {
queryParam.existDirectiveIds = props.existDirectiveIds.map(item => item.id).join(',')
return Object.assign(params, queryParam);
},
},
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: 5,
xxl: 5
});
const wrapperCol = reactive({
xs: 24,
sm: 19,
});
/**
* 详情
*/
function handleDetail(record: Recordable) {
console.log("🚀 ~ handleDetail ~ record:", record)
registerModal.value.disableSubmit = true;
registerModal.value.edit(record);
}
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 镜像
*/
function handlePull(record) {
createConfirm({
iconType: 'warning',
title: '镜像确认',
content: '请确认是否将' + record.orgCode_dictText + '新增的服务指令“' + record.directiveName + '”镜像给当前标准服务指令库:' + props.directiveMainOrgInfo.departName,
okText: '确认',
cancelText: '取消',
onOk: () => {
// syncDirective(
// record.orgCode,
// {
// syncIds: record.directiveId,
// upIds: '',
// syncOrgCodes: props.directiveMainOrgInfo.orgCode,
// syncOption: 'all',
// }
// ).then(res => {
// createMessage.success(',!')
// emit('refreshExistIds', props.directiveMainOrgInfo)
// }).catch(() => {
// createMessage.error('')
// })
}
});
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
// {
// label: '',
// onClick: handleDetail.bind(null, record),
// },
// {
// label: '',
// onClick: handlePull.bind(null, record),
// }
];
}
/**
* 查询
*/
function searchQuery() {
emit('refreshExistIds', props.directiveMainOrgInfo, false)
}
/**
* 重置
*/
function searchReset() {
formRef.value.resetFields();
selectedRowKeys.value = [];
//
emit('refreshExistIds', props.directiveMainOrgInfo, false)
}
defineExpose({
searchReset,
reload,
})
</script>
<style lang="less" scoped>
.jeecg-basic-table-form-container {
padding: 0;
margin-bottom: 18px;
.table-page-search-submitButtons {
display: block;
margin-bottom: 0px;
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: 18px;
height: 32px;
}
:deep(.ant-picker),
:deep(.ant-input-number) {
width: 100%;
}
}
</style>

View File

@ -0,0 +1,315 @@
<template>
<a-spin :spinning="confirmLoading">
<JFormContainer>
<template #detail>
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol"
name="ConfigService2DirectiveForm">
<a-row v-show="isAudit">
<a-col :span="12">
<a-config-provider :disabled="false">
<a-form-item label="服务指令审核" v-bind="validateInfos.statusVal" id="ConfigServiceDirectiveForm-statusVal"
name="statusVal">
<a-select v-model:value="formData.statusVal" placeholder="请选择审核状态" style="width: 200px"
:disabled="false">
<a-select-option value="auditPass">审核通过</a-select-option>
<a-select-option value="auditFaild">审核不通过</a-select-option>
</a-select>
</a-form-item>
</a-config-provider>
</a-col>
</a-row>
</a-form>
</template>
</JFormContainer>
<JFormContainer :disabled="disabled" style="margin-top: -30px;">
<template #detail>
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol"
name="ConfigService2DirectiveForm">
<a-row v-show="!isEditMedia">
<a-col :span="12">
<a-form-item label="分类标签" v-bind="validateInfos.instructionTagId"
id="ConfigServiceDirectiveForm-instructionTagId" name="instructionTagId">
{{formData.instructionTag}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="服务类别" v-bind="validateInfos.categoryId" id="ConfigServiceDirectiveForm-categoryId"
name="categoryId">
{{formData.category}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="服务类型" v-bind="validateInfos.typeId" id="ConfigServiceDirectiveForm-typeId"
name="typeId">
{{formData.type}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="服务指令名称" v-bind="validateInfos.directiveName"
id="ConfigServiceDirectiveForm-directiveName" name="directiveName">
{{formData.directiveName}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="收费价格(元)" v-bind="validateInfos.tollPrice" id="ConfigServiceDirectiveForm-tollPrice"
name="tollPrice">
{{formData.tollPrice}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="提成价格(元)" v-bind="validateInfos.comPrice" id="ConfigServiceDirectiveForm-comPrice"
name="comPrice">
{{formData.comPrice}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="医保报销" v-bind="validateInfos.izReimbursement"
id="ConfigServiceDirectiveForm-izReimbursement" name="izReimbursement">
{{formData.izReimbursement=='1'?'报销':'不报销'}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="机构优惠" v-bind="validateInfos.izPreferential"
id="ConfigServiceDirectiveForm-izPreferential" name="izPreferential">
{{formData.izPreferential=='1'?'参与':'不参与'}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="周期类型" v-bind="validateInfos.cycleType" id="ConfigServiceDirectiveForm-cycleType"
name="cycleType">
<span v-if="formData.cycleType=='1'">日常护理</span>
<span v-if="formData.cycleType=='2'">周期护理</span>
<span v-if="formData.cycleType=='3'">即时护理</span>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="服务时长(分钟)" v-bind="validateInfos.serviceDuration"
id="ConfigServiceDirectiveForm-serviceDuration" name="serviceDuration">
{{formData.serviceDuration}}
</a-form-item>
</a-col>
</a-row>
<a-col :span="12">
<a-form-item label="服务指令描述" v-bind="validateInfos.serviceContent"
id="ConfigServiceDirectiveForm-serviceContent" name="serviceContent">
{{formData.serviceContent}}
</a-form-item>
</a-col>
</a-form>
</template>
</JFormContainer>
</a-spin>
</template>
<script lang="ts" setup>
import { ref, reactive, defineExpose, nextTick, defineProps, computed, onMounted, watch } from 'vue';
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
import { JCheckbox } from '/@/components/Form';
import JUpload from '/@/components/Form/src/jeecg/components/JUpload/JUpload.vue';
import JImageUpload from '/@/components/Form/src/jeecg/components/JImageUpload.vue';
import { getValueType } from '/@/utils';
import { Form } from 'ant-design-vue';
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
const props = defineProps({
formDisabled: { type: Boolean, default: false },
formData: { type: Object, default: () => ({}) },
formBpm: { type: Boolean, default: true },
});
const bodyTagDictCode = ref(`nu_config_body_tag,tag_name,id,1=2`)
const emotionTagDictCode = ref(`nu_config_emotion_tag,tag_name,id,1=2`)
const formRef = ref();
const useForm = Form.useForm;
const emit = defineEmits(['register', 'ok']);
const formData = reactive<Record<string, any>>({
id: '',
categoryId: '',
typeId: '',
instructionTagId: '',
directiveName: '',
tollPrice: 0,
comPrice: 0,
izReimbursement: '0',
izPreferential: '0',
chargingFrequency: '',
cycleType: '',
sort: 99,
serviceContent: '',
serviceDuration: '5',
izEnabled: '0',
createBy: '',
createTime: '',
updateBy: '',
updateTime: '',
mp3File: '',
mp4File: '',
previewFile: '',
immediateFile: '',
status: '',
statusVal: undefined,
sysOrgCode: undefined,
instructionTag:'',
category:'',
type:'',
});
const { createMessage } = useMessage();
const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 8 } });
const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
const confirmLoading = ref<boolean>(false);
const isEditMedia = ref(false)
const isAudit = ref(false)
//
const validatorRules = reactive({
});
const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: false });
//
const disabled = computed(() => {
if (props.formBpm === true) {
if (props.formData.disabled === false) {
return false;
} else {
return true;
}
}
return props.formDisabled;
});
const categoryDictCode = ref('')
const typeDictCode = ref('')
//
const canUploadPreviewImage = computed(() => {
return formData.instructionTagId &&
formData.categoryId &&
formData.typeId &&
formData.directiveName &&
formData.cycleType;
});
//
const instructionComDictCode = ref([])
function upInstructionDictCode(v_) {
instructionComDictCode.value = v_
}
//
const categoryComDictCode = ref([])
function upCategoryDictCode(v_) {
categoryComDictCode.value = v_
}
//
const typeComDictCode = ref([])
function upTypeDictCode(v_) {
typeComDictCode.value = v_
}
//
const cycleTypeComDictCode = ref([])
function upCycleTypeDictCode(v_) {
cycleTypeComDictCode.value = v_
}
watch([instructionComDictCode, categoryComDictCode, typeComDictCode, cycleTypeComDictCode], () => {
// directiveBizPath
}, { deep: true });
const directiveBizPath = computed(() => {
if (!canUploadPreviewImage.value) return '';
//
const instructionTagName_ = instructionComDictCode.value.filter(d => d.value == formData.instructionTagId)?.[0]?.label;
const categoryName_ = categoryComDictCode.value.filter(d => d.value == formData.categoryId)?.[0]?.label;
const typeName_ = typeComDictCode.value.filter(d => d.value == formData.typeId)?.[0]?.label;
const cycleTypeName_ = cycleTypeComDictCode.value.filter(d => d.value == formData.cycleType)?.[0]?.label;
//
return 'directive/' + `${instructionTagName_}/${categoryName_}/${typeName_}/${formData.directiveName}/${cycleTypeName_}`;
});
watch(
() => formData.instructionTagId,
(newInstructionTagId) => {
if (!newInstructionTagId) {
formData.categoryId = ''
formData.typeId = ''
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 iz_enabled = 0 and iz_enabled = 0 and instruction_id = '${newInstructionTagId}' order by sort asc`;
}
}
);
watch(
() => formData.categoryId,
(newCategoryId) => {
if (!newCategoryId) {
formData.typeId = ''
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 iz_enabled = 0 and category_id = '${newCategoryId}' order by sort asc`;
}
}
);
/**
* 新增
*/
function add() {
edit({});
}
/**
* 编辑
* isEditMedia_是否为编辑指令资源 隐藏业务字段
* isAudit_是否为服务指令那个审核 隐藏业务字段
*/
function edit(record, isEditMedia_ = false, isAudit_ = false) {
console.log("🌊 ~ edit ~ record:", record)
if (!!record.bodyTags) {
// "id = 'id1' or id = 'id2'"
const bodyTagConditions = record.bodyTags.split(',')
.map(id => `id = '${id}'`)
.join(' or ');
bodyTagDictCode.value = `nu_config_body_tag,tag_name,id,del_flag = 0 and iz_enabled = 0 ` +
(bodyTagConditions ? ` and (${bodyTagConditions})` : '') +
` order by sort asc`;
}
if (!!record.emotionTags) {
// "id = 'id1' or id = 'id2'"
const emotionTagConditions = record.emotionTags.split(',')
.map(id => `id = '${id}'`)
.join(' or ');
emotionTagDictCode.value = `nu_config_emotion_tag,tag_name,id,del_flag = 0 and iz_enabled = 0 ` +
(emotionTagConditions ? ` and (${emotionTagConditions})` : '') +
` order by sort asc`;
}
isEditMedia.value = isEditMedia_
isAudit.value = isAudit_
formData.bodyTags = ''
formData.emotionTags = ''
nextTick(() => {
resetFields();
const tmpData = {};
Object.keys(formData).forEach((key) => {
if (record.hasOwnProperty(key)) {
tmpData[key] = record[key]
}
})
//
Object.assign(formData, tmpData);
});
}
defineExpose({
add,
edit,
});
</script>
<style lang="less" scoped>
.antd-modal-form {
padding: 14px;
}
</style>

View File

@ -0,0 +1,148 @@
<template>
<a-drawer :title="title" width="70vw" v-model:visible="visible" :footer-style="{ textAlign: 'right' }" @cancel="handleCancel"
cancelText="关闭" :maskClosable="true">
<template #footer>
<a-button @click="handleCancel">关闭</a-button>
</template>
<CanAddDirectiveForm ref="registerForm" v-if="visible" @ok="submitCallback" :formDisabled="disableSubmit"
:formBpm="false"></CanAddDirectiveForm>
</a-drawer>
</template>
<script lang="ts" setup>
import { ref, nextTick, defineExpose, defineProps } from 'vue';
import CanAddDirectiveForm from './CanAddDirectiveDetail.vue'
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
import { queryById } from '/@/views/services/serviceDirective/ConfigServiceDirective.api';
const props = defineProps({
});
const title = ref<string>('');
const visible = ref<boolean>(false);
const auditVisible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();
const auditListRef = ref();
const emit = defineEmits(['register', 'success']);
const opeType = ref('')// add edit editMedia- look audit auditMedia-
/**
* 编辑
* @param record
*/
function edit(record) {
title.value = '详情';
visible.value = true;
queryById({ dataSourceCode: record.orgCode, id: record.directiveId }).then(res => {
res.instructionTag = record.instructionTag;
res.category = record.category;
res.type = record.type;
registerForm.value.edit(res);
})
}
/**
* 审核列表 - 审核
* @param record
*/
function audit(record) {
title.value = '审核';
visible.value = true;
nextTick(() => {
registerForm.value.edit(record, false, true);
});
}
/**
* 打开审核列表
*/
function openAuditList() {
auditVisible.value = true;
auditListRef.value?.open();
}
/**
* 编辑指令资源
* @param record
*/
function editMedia(record) {
title.value = '编辑指令资源';
visible.value = true;
nextTick(() => {
registerForm.value.edit(record, true);
});
}
/**
* 确定按钮点击事件
*/
function handleOk() {
if (opeType.value == 'audit') {
registerForm.value.submitAudit();
} else {
registerForm.value.submitForm();
}
}
/**
* 暂存
*/
function handleSave() {
registerForm.value.submitForm();
}
/**
* 给审核对应的业务平台同步资源
*/
function handleMediaAsync() {
registerForm.value.syncMediaForBizFunc();
}
/**
* 给所有业务平台同步资源
*/
function handleMediaSyncAllPlat() {
registerForm.value.syncMediaForAllBizFunc();
}
/**
* form保存回调事件
*/
function submitCallback() {
handleCancel();
emit('success');
}
/**
* 取消按钮回调事件
*/
function handleCancel() {
visible.value = false;
}
/**
* 审核列表-关闭按钮回调事件
*/
function handleAuditCancel() {
auditVisible.value = false;
emit('success')
}
defineExpose({
edit,
editMedia,
disableSubmit,
audit,
openAuditList,
opeType,
});
</script>
<style lang="less">
/**隐藏样式-modal确定按钮 */
.jee-hidden {
display: none !important;
}
</style>
<style lang="less" scoped></style>

View File

@ -0,0 +1,445 @@
<template>
<a-spin :spinning="confirmLoading">
<JFormContainer>
<template #detail>
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol"
name="ConfigService2DirectiveForm">
<a-row v-show="isAudit">
<a-col :span="12">
<a-config-provider :disabled="false">
<a-form-item label="服务指令审核" v-bind="validateInfos.statusVal" id="ConfigServiceDirectiveForm-statusVal"
name="statusVal">
<a-select v-model:value="formData.statusVal" placeholder="请选择审核状态" style="width: 200px"
:disabled="false">
<a-select-option value="auditPass">审核通过</a-select-option>
<a-select-option value="auditFaild">审核不通过</a-select-option>
</a-select>
</a-form-item>
</a-config-provider>
</a-col>
</a-row>
</a-form>
</template>
</JFormContainer>
<JFormContainer :disabled="disabled" style="margin-top: -30px;">
<template #detail>
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol"
name="ConfigService2DirectiveForm">
<a-row v-show="!isEditMedia">
<a-col :span="12">
<a-form-item label="分类标签" v-bind="validateInfos.instructionTagId"
id="ConfigServiceDirectiveForm-instructionTagId" name="instructionTagId">
<j-dict-select-tag v-model:value="formData.instructionTagId" :orgCode="formData?.sysOrgCode"
:dictCode="`nu_config_service_instruction_tag,instruction_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc`"
placeholder="请选择分类标签" allowClear @upDictCode="upInstructionDictCode" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="服务类别" v-bind="validateInfos.categoryId" id="ConfigServiceDirectiveForm-categoryId"
name="categoryId">
<j-dict-select-tag type="list" v-model:value="formData.categoryId" :orgCode="formData?.sysOrgCode"
:disabled="!formData.instructionTagId" :dictCode="categoryDictCode" placeholder="请选择服务类别" allow-clear
@upDictCode="upCategoryDictCode" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="服务类型" v-bind="validateInfos.typeId" id="ConfigServiceDirectiveForm-typeId"
name="typeId">
<j-dict-select-tag type="list" v-model:value="formData.typeId" :dictCode="typeDictCode"
:orgCode="formData?.sysOrgCode" :disabled="!formData.categoryId" placeholder="请选择服务类型" allowClear
@upDictCode="upTypeDictCode" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="服务指令名称" v-bind="validateInfos.directiveName"
id="ConfigServiceDirectiveForm-directiveName" name="directiveName">
<a-input v-model:value="formData.directiveName" placeholder="请输入服务指令名称" allow-clear></a-input>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="收费价格(元)" v-bind="validateInfos.tollPrice" id="ConfigServiceDirectiveForm-tollPrice"
name="tollPrice">
<a-input-number v-model:value="formData.tollPrice" placeholder="请输入收费价格" style="width: 100%"
precision="2" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="提成价格(元)" v-bind="validateInfos.comPrice" id="ConfigServiceDirectiveForm-comPrice"
name="comPrice">
<a-input-number v-model:value="formData.comPrice" placeholder="请输入提成价格" style="width: 100%"
precision="2" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="医保报销" v-bind="validateInfos.izReimbursement"
id="ConfigServiceDirectiveForm-izReimbursement" name="izReimbursement">
<j-dict-select-tag type='radio' v-model:value="formData.izReimbursement" dictCode="med_ins_reimb"
allowClear />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="机构优惠" v-bind="validateInfos.izPreferential"
id="ConfigServiceDirectiveForm-izPreferential" name="izPreferential">
<j-dict-select-tag type='radio' v-model:value="formData.izPreferential"
dictCode="institutional_discount" allowClear />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="周期类型" v-bind="validateInfos.cycleType" id="ConfigServiceDirectiveForm-cycleType"
name="cycleType">
<j-dict-select-tag type="list" v-model:value="formData.cycleType" dictCode="period_type"
:orgCode="formData?.sysOrgCode" placeholder="请选择周期类型" allowClear @upDictCode="upCycleTypeDictCode" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="服务时长(分钟)" v-bind="validateInfos.serviceDuration"
id="ConfigServiceDirectiveForm-serviceDuration" name="serviceDuration">
<a-input-number v-model:value="formData.serviceDuration" :min="5" :max="55" :step="5"
placeholder="请输入服务时长(分钟)" allow-clear />
</a-form-item>
</a-col>
</a-row>
<!-- <a-row v-show="!isEditMedia">
<a-col :span="24">
<a-form-item label="体型标签" id="ConfigServiceDirectiveForm-typeId" :labelCol="labelCol2"
:wrapperCol="wrapperCol2" name="typeId">
<span v-if="!formData.bodyTags">-</span>
<JCheckbox v-else v-model:value="formData.bodyTags" :orgCode="formData?.sysOrgCode"
:dictCode="bodyTagDictCode" />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="情绪标签" :labelCol="labelCol2" :wrapperCol="wrapperCol2" name="emoTags">
<span v-if="!formData.emotionTags">-</span>
<JCheckbox v-else v-model:value="formData.emotionTags" :orgCode="formData?.sysOrgCode"
:dictCode="emotionTagDictCode" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="是否启用" v-bind="validateInfos.izEnabled" id="ConfigServiceDirectiveForm-izEnabled"
name="izEnabled">
<j-dict-select-tag type='radio' v-model:value="formData.izEnabled" dictCode="iz_enabled"
placeholder="请选择是否启用"  allowClear />
</a-form-item>
</a-col>
</a-row> -->
<!-- <a-row> -->
<!-- <a-col :span="12">
<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"
:disabled="!canUploadPreviewImage" :bizPath="directiveBizPath">
</JImageUpload>
</a-form-item>
</a-col> -->
<a-col :span="12">
<a-form-item label="服务指令描述" v-bind="validateInfos.serviceContent"
id="ConfigServiceDirectiveForm-serviceContent" name="serviceContent">
<a-textarea v-model:value="formData.serviceContent" :rows="2" placeholder="请输入服务指令描述" :autosize="true" />
</a-form-item>
</a-col>
<!-- </a-row> -->
<!-- <a-row v-show="!disabled">
<a-col :span="12">
<a-form-item label="指令音频文件" v-bind="validateInfos.mp3File" id="ConfigServiceDirectiveForm-mp3File">
<j-upload v-model:value="formData.mp3File" accept=".mp3" :maxCount="1"
:disabled="!canUploadPreviewImage" :bizPath="directiveBizPath"></j-upload>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="指令视频文件" v-bind="validateInfos.mp4File" id="ConfigServiceDirectiveForm-mp4File">
<j-upload v-model:value="formData.mp4File" accept=".mp4" :maxCount="1"
:disabled="!canUploadPreviewImage" :bizPath="directiveBizPath"></j-upload>
</a-form-item>
</a-col>
</a-row> -->
</a-form>
</template>
</JFormContainer>
<!-- <JFormContainer style="margin-top: -40px;">
<template #detail>
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol"
name="ConfigServiceDirectiveForm">
<a-row>
<a-col :span="12" v-if="!!formData.mp3File">
<a-form-item label="指令音频预览" id="ConfigServiceDirectiveForm-mp3File">
<audio controls disabled="false">
<source :src="getFileAccessHttpUrl(formData.mp3File)">
</audio>
</a-form-item>
</a-col>
<a-col :span="12" v-if="disabled && !formData.mp3File">
<a-form-item label="指令音频预览">
<span>暂无文件</span>
</a-form-item>
</a-col>
<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)">
</video>
</a-form-item>
</a-col>
<a-col :span="12" v-if="disabled && !formData.mp3File">
<a-form-item label="指令视频预览">
<span>暂无文件</span>
</a-form-item>
</a-col>
<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"
:disabled="!canUploadPreviewImage || disabled" :bizPath="directiveBizPath">
</JImageUpload>
</a-form-item>
</a-col>
</a-row>
</a-form>
</template>
</JFormContainer> -->
</a-spin>
</template>
<script lang="ts" setup>
import { ref, reactive, defineExpose, nextTick, defineProps, computed, onMounted, watch } from 'vue';
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
import { JCheckbox } from '/@/components/Form';
import JUpload from '/@/components/Form/src/jeecg/components/JUpload/JUpload.vue';
import JImageUpload from '/@/components/Form/src/jeecg/components/JImageUpload.vue';
import { getValueType } from '/@/utils';
import { Form } from 'ant-design-vue';
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
const props = defineProps({
formDisabled: { type: Boolean, default: false },
formData: { type: Object, default: () => ({}) },
formBpm: { type: Boolean, default: true },
});
const bodyTagDictCode = ref(`nu_config_body_tag,tag_name,id,1=2`)
const emotionTagDictCode = ref(`nu_config_emotion_tag,tag_name,id,1=2`)
const formRef = ref();
const useForm = Form.useForm;
const emit = defineEmits(['register', 'ok']);
const formData = reactive<Record<string, any>>({
id: '',
categoryId: '',
typeId: '',
instructionTagId: '',
directiveName: '',
tollPrice: 0,
comPrice: 0,
izReimbursement: '0',
izPreferential: '0',
chargingFrequency: '',
cycleType: '',
sort: 99,
serviceContent: '',
serviceDuration: '5',
izEnabled: '0',
createBy: '',
createTime: '',
updateBy: '',
updateTime: '',
mp3File: '',
mp4File: '',
previewFile: '',
immediateFile: '',
status: '',
statusVal: undefined,
sysOrgCode: undefined,
});
const { createMessage } = useMessage();
const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 6 } });
const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
const labelCol2 = ref<any>({ xs: { span: 24 }, sm: { span: 3 } });
const wrapperCol2 = ref<any>({ xs: { span: 24 }, sm: { span: 20 } });
const confirmLoading = ref<boolean>(false);
const isEditMedia = ref(false)
const isAudit = ref(false)
//
const validatorRules = reactive({
categoryId: [{ required: true, message: '请选择服务类别!' },],
typeId: [{ required: true, message: '请选择服务类型!' },],
instructionTagId: [{ required: true, message: '请选择分类标签!' },],
directiveName: [{ required: true, message: '请输入服务指令名称!' },],
tollPrice: [{ required: true, message: '请输入收费价格!' }, { pattern: /^(([0-9]*)|([0]\.\d{0,4}|[1-9][0-9]*\.\d{0,4}))$/, message: '请输入正确的金额!' },],
comPrice: [{ required: false }, { pattern: /^(([0-9]*)|([0]\.\d{0,4}|[1-9][0-9]*\.\d{0,4}))$/, message: '请输入正确的金额!' },],
izReimbursement: [{ required: true, message: '请选择是否参与医保报销!' },],
izPreferential: [{ required: true, message: '请选择是否参与机构优惠!' },],
// chargingFrequency: [{ required: true, message: '!' },],
cycleType: [{ required: true, message: '请选择周期类型!' },],
// sort: [{ required: true, message: '!' }, { pattern: /^\d+$/, message: '!' },],
serviceDuration: [
{ required: true, message: '请输入服务时长(分钟)!' },
{ pattern: /^\d+$/, message: '请输入正整数!' },
{
validator: (_, value) => {
if (value % 5 !== 0) {
return Promise.reject('请输入5的倍数!');
}
return Promise.resolve();
},
},
{
validator: (_, value) => {
if (value < 5 || value > 55) {
return Promise.reject('请输入5到55之间的值!');
}
return Promise.resolve();
},
},
],
izEnabled: [{ required: true, message: '请选择是否启用!' },],
});
const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: false });
//
const disabled = computed(() => {
if (props.formBpm === true) {
if (props.formData.disabled === false) {
return false;
} else {
return true;
}
}
return props.formDisabled;
});
const categoryDictCode = ref('')
const typeDictCode = ref('')
//
const canUploadPreviewImage = computed(() => {
return formData.instructionTagId &&
formData.categoryId &&
formData.typeId &&
formData.directiveName &&
formData.cycleType;
});
//
const instructionComDictCode = ref([])
function upInstructionDictCode(v_) {
instructionComDictCode.value = v_
}
//
const categoryComDictCode = ref([])
function upCategoryDictCode(v_) {
categoryComDictCode.value = v_
}
//
const typeComDictCode = ref([])
function upTypeDictCode(v_) {
typeComDictCode.value = v_
}
//
const cycleTypeComDictCode = ref([])
function upCycleTypeDictCode(v_) {
cycleTypeComDictCode.value = v_
}
watch([instructionComDictCode, categoryComDictCode, typeComDictCode, cycleTypeComDictCode], () => {
// directiveBizPath
}, { deep: true });
const directiveBizPath = computed(() => {
if (!canUploadPreviewImage.value) return '';
//
const instructionTagName_ = instructionComDictCode.value.filter(d => d.value == formData.instructionTagId)?.[0]?.label;
const categoryName_ = categoryComDictCode.value.filter(d => d.value == formData.categoryId)?.[0]?.label;
const typeName_ = typeComDictCode.value.filter(d => d.value == formData.typeId)?.[0]?.label;
const cycleTypeName_ = cycleTypeComDictCode.value.filter(d => d.value == formData.cycleType)?.[0]?.label;
//
return 'directive/' + `${instructionTagName_}/${categoryName_}/${typeName_}/${formData.directiveName}/${cycleTypeName_}`;
});
watch(
() => formData.instructionTagId,
(newInstructionTagId) => {
if (!newInstructionTagId) {
formData.categoryId = ''
formData.typeId = ''
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 iz_enabled = 0 and iz_enabled = 0 and instruction_id = '${newInstructionTagId}' order by sort asc`;
}
}
);
watch(
() => formData.categoryId,
(newCategoryId) => {
if (!newCategoryId) {
formData.typeId = ''
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 iz_enabled = 0 and category_id = '${newCategoryId}' order by sort asc`;
}
}
);
/**
* 新增
*/
function add() {
edit({});
}
/**
* 编辑
* isEditMedia_是否为编辑指令资源 隐藏业务字段
* isAudit_是否为服务指令那个审核 隐藏业务字段
*/
function edit(record, isEditMedia_ = false, isAudit_ = false) {
console.log("🌊 ~ edit ~ record:", record)
if (!!record.bodyTags) {
// "id = 'id1' or id = 'id2'"
const bodyTagConditions = record.bodyTags.split(',')
.map(id => `id = '${id}'`)
.join(' or ');
bodyTagDictCode.value = `nu_config_body_tag,tag_name,id,del_flag = 0 and iz_enabled = 0 ` +
(bodyTagConditions ? ` and (${bodyTagConditions})` : '') +
` order by sort asc`;
}
if (!!record.emotionTags) {
// "id = 'id1' or id = 'id2'"
const emotionTagConditions = record.emotionTags.split(',')
.map(id => `id = '${id}'`)
.join(' or ');
emotionTagDictCode.value = `nu_config_emotion_tag,tag_name,id,del_flag = 0 and iz_enabled = 0 ` +
(emotionTagConditions ? ` and (${emotionTagConditions})` : '') +
` order by sort asc`;
}
isEditMedia.value = isEditMedia_
isAudit.value = isAudit_
formData.bodyTags = ''
formData.emotionTags = ''
nextTick(() => {
resetFields();
const tmpData = {};
Object.keys(formData).forEach((key) => {
if (record.hasOwnProperty(key)) {
tmpData[key] = record[key]
}
})
//
Object.assign(formData, tmpData);
});
}
defineExpose({
add,
edit,
});
</script>
<style lang="less" scoped>
.antd-modal-form {
padding: 14px;
}
</style>

View File

@ -0,0 +1,145 @@
<template>
<a-drawer :title="title" width="70vw" v-model:visible="visible" :footer-style="{ textAlign: 'right' }" @cancel="handleCancel"
cancelText="关闭" :maskClosable="true">
<template #footer>
<a-button @click="handleCancel">关闭</a-button>
</template>
<CanAddDirectiveForm ref="registerForm" v-if="visible" @ok="submitCallback" :formDisabled="disableSubmit"
:formBpm="false"></CanAddDirectiveForm>
</a-drawer>
</template>
<script lang="ts" setup>
import { ref, nextTick, defineExpose, defineProps } from 'vue';
import CanAddDirectiveForm from './CanAddDirectiveForm.vue'
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
import { queryById } from '/@/views/synchronization/directive/serviceDirective/ConfigServiceDirective.api';
const props = defineProps({
});
const title = ref<string>('');
const visible = ref<boolean>(false);
const auditVisible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();
const auditListRef = ref();
const emit = defineEmits(['register', 'success']);
const opeType = ref('')// add edit editMedia- look audit auditMedia-
/**
* 编辑
* @param record
*/
function edit(record) {
title.value = '详情';
visible.value = true;
queryById({ dataSourceCode: record.orgCode, id: record.directiveId }).then(res => {
registerForm.value.edit(res);
})
}
/**
* 审核列表 - 审核
* @param record
*/
function audit(record) {
title.value = '审核';
visible.value = true;
nextTick(() => {
registerForm.value.edit(record, false, true);
});
}
/**
* 打开审核列表
*/
function openAuditList() {
auditVisible.value = true;
auditListRef.value?.open();
}
/**
* 编辑指令资源
* @param record
*/
function editMedia(record) {
title.value = '编辑指令资源';
visible.value = true;
nextTick(() => {
registerForm.value.edit(record, true);
});
}
/**
* 确定按钮点击事件
*/
function handleOk() {
if (opeType.value == 'audit') {
registerForm.value.submitAudit();
} else {
registerForm.value.submitForm();
}
}
/**
* 暂存
*/
function handleSave() {
registerForm.value.submitForm();
}
/**
* 给审核对应的业务平台同步资源
*/
function handleMediaAsync() {
registerForm.value.syncMediaForBizFunc();
}
/**
* 给所有业务平台同步资源
*/
function handleMediaSyncAllPlat() {
registerForm.value.syncMediaForAllBizFunc();
}
/**
* form保存回调事件
*/
function submitCallback() {
handleCancel();
emit('success');
}
/**
* 取消按钮回调事件
*/
function handleCancel() {
visible.value = false;
}
/**
* 审核列表-关闭按钮回调事件
*/
function handleAuditCancel() {
auditVisible.value = false;
emit('success')
}
defineExpose({
edit,
editMedia,
disableSubmit,
audit,
openAuditList,
opeType,
});
</script>
<style lang="less">
/**隐藏样式-modal确定按钮 */
.jee-hidden {
display: none !important;
}
</style>
<style lang="less" scoped></style>

View File

@ -0,0 +1,72 @@
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from "/@/hooks/web/useMessage";
const { createConfirm } = useMessage();
enum Api {
list = '/services/directiveMedia/list',
save='/services/directiveMedia/add',
edit='/services/directiveMedia/edit',
deleteOne = '/services/directiveMedia/delete',
deleteBatch = '/services/directiveMedia/deleteBatch',
importExcel = '/services/directiveMedia/importExcel',
exportXls = '/services/directiveMedia/exportXls',
}
/**
* api
* @param params
*/
export const getExportUrl = Api.exportXls;
/**
* api
*/
export const getImportUrl = Api.importExcel;
/**
*
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
/**
*
* @param params
* @param handleSuccess
*/
export const deleteOne = (params,handleSuccess) => {
return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
/**
*
* @param params
* @param handleSuccess
*/
export const batchDelete = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
handleSuccess();
});
}
});
}
/**
*
* @param params
* @param isUpdate
*/
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params }, { isTransformResponse: false });
}

View File

@ -0,0 +1,63 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
import { getWeekMonthQuarterYear } from '/@/utils';
//列表数据
export const columns: BasicColumn[] = [
{
title: '服务指令名称',
align: "center",
dataIndex: 'directiveName'
},
{
title: '分类标签',
align: "center",
dataIndex: 'instructionTagId_dictText'
},
{
title: '服务类别',
align: "center",
dataIndex: 'categoryId_dictText'
},
{
title: '服务类型',
align: "center",
dataIndex: 'typeId_dictText'
},
{
title: '周期类型',
align: "center",
dataIndex: 'cycleType_dictText'
},
{
title: '服务指令图片大图',
align: "center",
dataIndex: 'previewFile',
customRender: render.renderImage,
},
{
title: '服务指令图片小图',
align: "center",
dataIndex: 'previewFileSmall',
customRender: render.renderImage,
},
{
title: '即时指令图标',
align: "center",
dataIndex: 'immediateFile',
customRender: render.renderImage,
},
];
// 高级查询数据
export const superQuerySchema = {
directiveName: {title: '服务指令名称',order: 0,view: 'text', type: 'string',},
instructionTagId: {title: '分类标签id',order: 1,view: 'list', type: 'string',dictCode: '',},
categoryId: {title: '服务类别id',order: 2,view: 'list', type: 'string',dictCode: '',},
typeId: {title: '服务类型id',order: 3,view: 'list', type: 'string',dictCode: '',},
cycleType: {title: '周期类型',order: 4,view: 'list', type: 'string',dictCode: '',},
previewFile: {title: '服务指令图片大图',order: 5,view: 'image', type: 'string',},
previewFileSmall: {title: '服务指令图片小图',order: 6,view: 'image', type: 'string',},
immediateFile: {title: '即时指令图标',order: 7,view: 'image', type: 'string',},
};

View File

@ -0,0 +1,308 @@
<template>
<div>
<!--查询区域-->
<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="请输入服务指令名称" />
</a-form-item>
</a-col>
<a-col :lg="6">
<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 and iz_enabled = 0 order by sort asc`"
placeholder="请选择分类标签" allow-clear />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="categoryId">
<template #label><span title="服务类别">服务类别</span></template>
<j-dict-select-tag v-model:value="queryParam.categoryId" :dictCode="categoryDictCode"
placeholder="请选择服务类别" allow-clear />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="typeId">
<template #label><span title="服务类型">服务类型</span></template>
<j-dict-select-tag v-model:value="queryParam.typeId" :dictCode="typeDictCode" placeholder="请选择服务类型"
allow-clear />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="cycleType">
<template #label><span title="周期类型">周期类型</span></template>
<j-dict-select-tag v-model:value="queryParam.cycleType" dictCode="period_type" placeholder="请选择周期类型"
allow-clear />
</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 style="padding: 14px;background-color: #fff;">
<BasicTable @register="registerTable" :rowSelection="rowSelection">
<!--插槽:table标题-->
<template #tableTitle>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
<template v-slot:bodyCell="{ column, record, index, text }">
</template>
</BasicTable>
</div>
<!-- 表单区域 -->
<DirectiveMediaModal ref="registerModal" @success="handleSuccess"></DirectiveMediaModal>
</div>
</template>
<script lang="ts" name="directivemedia-directiveMedia" setup>
import { ref, reactive, watch } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { columns, superQuerySchema } from './DirectiveMedia.data';
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl } from './DirectiveMedia.api';
import { idListByDS } from '/@/views/services/serviceDirective/ConfigServiceDirective.api';
import { downloadFile } from '/@/utils/common/renderUtils';
import DirectiveMediaModal from './components/DirectiveMediaModal.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';
const emit = defineEmits(['success']);
const props = defineProps({
ownOrgCode: '',//
});
const formRef = ref();
const queryParam = reactive<any>({});
const toggleSearchStatus = ref<boolean>(false);
const registerModal = ref();
const userStore = useUserStore();
const categoryDictCode = ref('')
const typeDictCode = ref('')
const existingExcludeIds = ref('')
//table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '服务指令资源管理',
api: list,
columns,
canResize: false,
useSearchForm: false,
immediate: false,
actionColumn: {
width: 100,
fixed: 'right',
},
scroll: { 'y': '55vh' },
beforeFetch: async (params) => {
queryParam.excludeIds = existingExcludeIds.value
return Object.assign(params, queryParam);
},
},
exportConfig: {
name: "服务指令资源管理",
url: getExportUrl,
params: queryParam,
},
importConfig: {
url: getImportUrl,
success: handleSuccess
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRows, selectedRowKeys }] = tableContext;
const labelCol = reactive({
xs: 24,
sm: 4,
xl: 6,
xxl: 5
});
const wrapperCol = reactive({
xs: 24,
sm: 20,
});
//
const superQueryConfig = reactive(superQuerySchema);
/**
* 高级查询事件
*/
function handleSuperQuery(params) {
Object.keys(params).map((k) => {
queryParam[k] = params[k];
});
searchQuery();
}
/**
* 新增事件
*/
function handleAdd() {
registerModal.value.disableSubmit = false;
registerModal.value.add();
}
/**
* 编辑事件
*/
function handleEdit(record: Recordable) {
registerModal.value.disableSubmit = false;
registerModal.value.edit(record);
}
/**
* 详情
*/
function handleDetail(record: Recordable) {
registerModal.value.disableSubmit = true;
registerModal.value.edit(record);
}
/**
* 删除事件
*/
async function handleDelete(record) {
await deleteOne({ id: record.id }, handleSuccess);
}
/**
* 批量删除事件
*/
async function batchHandleDelete() {
await batchDelete({ ids: selectedRowKeys.value }, handleSuccess);
}
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
},
];
}
/**
* 查询
*/
function searchQuery() {
init()
}
/**
* 重置
*/
function searchReset() {
formRef.value.resetFields();
selectedRowKeys.value = [];
//
reload();
}
watch(
() => queryParam.instructionTagId,
(newInstructionTagId) => {
// if (needWatch.value) {
queryParam.categoryId = ''
queryParam.typeId = ''
// queryParam.cycleType = ''
// }
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 iz_enabled = 0 and instruction_id = '${newInstructionTagId}' order by sort asc`;
}
}
);
watch(
() => queryParam.categoryId,
(newCategoryId) => {
// if (needWatch.value) {
queryParam.typeId = ''
// queryParam.cycleType = ''
// }
if (!newCategoryId) {
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 iz_enabled = 0 and category_id = '${newCategoryId}' order by sort asc`;
}
}
);
watch(
() => queryParam.typeId,
(newTypeId) => {
// if (needWatch.value) {
// queryParam.cycleType = ''
// }
}
);
async function init() {
let res = await idListByDS({ dataSourceCode: 'master' })
existingExcludeIds.value = res.records.map(item => item.id)?.join(',')
reload()
}
defineExpose({
selectedRows,
init
});
</script>
<style lang="less" scoped>
.jeecg-basic-table-form-container {
padding: 0;
margin-bottom: 14px;
.table-page-search-submitButtons {
display: block;
margin-bottom: 14px;
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: 14px;
height: 32px;
}
:deep(.ant-picker),
:deep(.ant-input-number) {
width: 100%;
}
}
</style>

View File

@ -0,0 +1,336 @@
<template>
<a-spin :spinning="confirmLoading">
<JFormContainer :disabled="disabled">
<template #detail>
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol"
name="DirectiveMediaForm">
<a-row>
<a-col :span="24">
<a-form-item label="分类标签" v-bind="validateInfos.instructionTagId" id="DirectiveMediaForm-instructionTagId"
name="instructionTagId">
<j-dict-select-tag v-model:value="formData.instructionTagId" :disabled="!!formData.id"
:dictCode="`nu_config_service_instruction_tag,instruction_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc`"
@upDictCode="upInstructionDictCode" placeholder="请选择分类标签" :orgCode="sjjdbm" allow-clear />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="服务类别" v-bind="validateInfos.categoryId" id="DirectiveMediaForm-categoryId"
name="categoryId">
<j-dict-select-tag v-model:value="formData.categoryId" :disabled="!!formData.id"
@upDictCode="upCategoryDictCode" :dictCode="categoryDictCode" placeholder="请选择服务类别" :orgCode="sjjdbm"
allow-clear />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="服务类型" v-bind="validateInfos.typeId" id="DirectiveMediaForm-typeId" name="typeId">
<j-dict-select-tag v-model:value="formData.typeId" :disabled="!!formData.id" :dictCode="typeDictCode"
@upDictCode="upTypeDictCode" placeholder="请选择服务类型" :orgCode="sjjdbm" allow-clear />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="服务指令名称" v-bind="validateInfos.directiveName" id="DirectiveMediaForm-directiveName"
name="directiveName">
<a-input v-model:value="formData.directiveName" :disabled="!!formData.id" placeholder="请输入服务指令名称"
:maxlength="20" :showCount="true" allow-clear></a-input>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="周期类型" v-bind="validateInfos.cycleType" id="DirectiveMediaForm-cycleType"
name="cycleType">
<j-dict-select-tag v-model:value="formData.cycleType" :disabled="!!formData.id" dictCode="period_type"
@upDictCode="upCycleTypeDictCode" placeholder="请选择周期类型" :orgCode="sjjdbm" allow-clear />
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="服务指令图片大图" v-bind="validateInfos.previewFile" id="DirectiveMediaForm-previewFile"
name="previewFile">
<j-image-upload :fileMax="1" v-model:value="formData.previewFile"></j-image-upload>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="服务指令图片小图" v-bind="validateInfos.previewFileSmall"
id="DirectiveMediaForm-previewFileSmall" name="previewFileSmall">
<j-image-upload :fileMax="1" v-model:value="formData.previewFileSmall"></j-image-upload>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="即时指令图标" v-bind="validateInfos.immediateFile" id="DirectiveMediaForm-immediateFile"
name="immediateFile">
<j-image-upload :fileMax="1" v-model:value="formData.immediateFile"></j-image-upload>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="指令音频文件" v-bind="validateInfos.mp3File" id="ConfigServiceDirectiveForm-mp3File">
<j-upload v-model:value="formData.mp3File" accept=".mp3" :maxCount="1"
:beforeUpload="checkMp3"></j-upload>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="指令视频文件" v-bind="validateInfos.mp4File" id="ConfigServiceDirectiveForm-mp4File">
<j-upload v-model:value="formData.mp4File" accept=".mp4" :maxCount="1"
:beforeUpload="checkMp4"></j-upload>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="服务指令描述" v-bind="validateInfos.serviceContent"
id="ConfigServiceDirectiveForm-serviceContent" name="serviceContent">
<a-textarea v-model:value="formData.serviceContent" placeholder="请输入服务指令描述" :autosize="{ minRows: 3 }"
:maxlength="200" :showCount="true" />
</a-form-item>
</a-col>
</a-row>
</a-form>
</template>
</JFormContainer>
</a-spin>
</template>
<script lang="ts" setup>
import { ref, reactive, defineExpose, nextTick, defineProps, computed, onMounted, watch } from 'vue';
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
import JImageUpload from '/@/components/Form/src/jeecg/components/JImageUpload.vue';
import { getValueType } from '/@/utils';
import { saveOrUpdate } from '../DirectiveMedia.api';
import { Form } from 'ant-design-vue';
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
import JUpload from '/@/components/Form/src/jeecg/components/JUpload/JUpload.vue';
const sjjdbm = import.meta.env.VITE_SYTJGBM
const categoryDictCode = ref('')
const typeDictCode = ref('')
const props = defineProps({
formDisabled: { type: Boolean, default: false },
formData: { type: Object, default: () => ({}) },
formBpm: { type: Boolean, default: true }
});
const formRef = ref();
const useForm = Form.useForm;
const emit = defineEmits(['register', 'ok']);
const formData = reactive<Record<string, any>>({
id: '',
directiveId: '',
directiveName: '',
instructionTagId: '',
categoryId: '',
typeId: '',
cycleType: '',
previewFile: '',
previewFileSmall: '',
immediateFile: '',
mp3File: '',
mp4File: '',
serviceContent: '',
});
const needWatch = ref(false)
const { createMessage } = useMessage();
const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } });
const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
const confirmLoading = ref<boolean>(false);
//
const validatorRules = reactive({
directiveName: [{ required: true, message: '请输入服务指令名称!' },],
instructionTagId: [{ required: true, message: '请输入分类标签id!' },],
categoryId: [{ required: true, message: '请输入服务类别id!' },],
typeId: [{ required: true, message: '请输入服务类型id!' },],
cycleType: [{ required: true, message: '请输入周期类型!' },],
});
const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: false });
//
const instructionComDictCode = ref([])
function upInstructionDictCode(v_) {
instructionComDictCode.value = v_
}
//
const categoryComDictCode = ref([])
function upCategoryDictCode(v_) {
categoryComDictCode.value = v_
}
//
const typeComDictCode = ref([])
function upTypeDictCode(v_) {
typeComDictCode.value = v_
}
//
const cycleTypeComDictCode = ref([])
function upCycleTypeDictCode(v_) {
cycleTypeComDictCode.value = v_
}
watch([instructionComDictCode, categoryComDictCode, typeComDictCode, cycleTypeComDictCode], () => {
// formComputedData
}, { deep: true });
const formComputedData = computed(() => {
//
const instructionName = instructionComDictCode.value.find(d => d.value == formData.instructionTagId)?.label || '';
const categoryName = categoryComDictCode.value.find(d => d.value == formData.categoryId)?.label || '';
const typeName = typeComDictCode.value.find(d => d.value == formData.typeId)?.label || '';
const cycleTypeName = cycleTypeComDictCode.value.find(d => d.value == formData.cycleType)?.label || '';
return {
mediaFileSavePath: `directive/${instructionName}/${categoryName}/${typeName}/${cycleTypeName}/${formData.directiveName}`,
instructionName,
categoryName,
typeName,
cycleTypeName,
};
});
//
const disabled = computed(() => {
if (props.formBpm === true) {
if (props.formData.disabled === false) {
return false;
} else {
return true;
}
}
return props.formDisabled;
});
watch(
() => formData.instructionTagId,
(newInstructionTagId) => {
if (needWatch.value) {
formData.categoryId = ''
formData.typeId = ''
// formData.cycleType = ''
}
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 iz_enabled = 0 and instruction_id = '${newInstructionTagId}' order by sort asc`;
}
}
);
watch(
() => formData.categoryId,
(newCategoryId) => {
if (needWatch.value) {
formData.typeId = ''
// formData.cycleType = ''
}
if (!newCategoryId) {
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 iz_enabled = 0 and category_id = '${newCategoryId}' order by sort asc`;
}
}
);
watch(
() => formData.typeId,
(newTypeId) => {
if (needWatch.value) {
// formData.cycleType = ''
}
}
);
const checkMp3 = (file) => {
const isPDF = file.type === 'application/mp3' || file.name.endsWith('.mp3');
if (!isPDF) {
createMessage.error('只能上传 mp3 文件!');
return false; //
}
return true;
};
const checkMp4 = (file) => {
const isPDF = file.type === 'application/mp4' || file.name.endsWith('.mp4');
if (!isPDF) {
createMessage.error('只能上传 mp4 文件!');
return false; //
}
return true;
};
/**
* 新增
*/
function add() {
edit({});
}
/**
* 编辑
*/
function edit(record) {
needWatch.value = false
setTimeout(() => {
needWatch.value = true
}, 1000)
nextTick(() => {
resetFields();
const tmpData = {};
Object.keys(formData).forEach((key) => {
if (record.hasOwnProperty(key)) {
tmpData[key] = record[key]
}
})
//
Object.assign(formData, tmpData);
});
}
/**
* 提交数据
*/
async function submitForm() {
try {
//
await validate();
} catch ({ errorFields }) {
if (errorFields) {
const firstField = errorFields[0];
if (firstField) {
formRef.value.scrollToField(firstField.name, { behavior: 'smooth', block: 'center' });
}
}
return Promise.reject(errorFields);
}
confirmLoading.value = true;
const isUpdate = ref<boolean>(false);
//
let model = formData;
if (model.id) {
isUpdate.value = true;
}
//
for (let data in model) {
//
if (model[data] instanceof Array) {
let valueType = getValueType(formRef.value.getProps, data);
//
if (valueType === 'string') {
model[data] = model[data].join(',');
}
}
}
model.mediaFileSavePath = formComputedData.value.mediaFileSavePath
await saveOrUpdate(model, isUpdate.value)
.then((res) => {
if (res.success) {
createMessage.success(res.message);
emit('ok');
} else {
createMessage.warning(res.message);
}
})
.finally(() => {
confirmLoading.value = false;
});
}
defineExpose({
add,
edit,
submitForm,
});
</script>
<style lang="less" scoped>
.antd-modal-form {
padding: 14px;
}
</style>

View File

@ -0,0 +1,83 @@
<template>
<a-drawer :title="title" width="50vw" :visible="visible" @ok="handleOk" @cancel="handleCancel" cancelText="关闭"
:closable="true" :footer-style="{ textAlign: 'right' }" @close="handleCancel"
:bodyStyle="{ padding: '0px', background: 'linear-gradient(135deg, #f1f7ff 0%, #f1f7ff 100%)' }">
<DirectiveMediaForm ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false">
</DirectiveMediaForm>
<template #footer>
<a-button @click="handleCancel" style="margin-right: 8px;">关闭</a-button>
</template>
</a-drawer>
</template>
<script lang="ts" setup>
import { ref, nextTick, defineExpose } from 'vue';
import DirectiveMediaForm from './DirectiveMediaForm.vue'
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
const title = ref<string>('');
const width = ref<number>(800);
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();
const emit = defineEmits(['register', 'success']);
/**
* 新增
*/
function add() {
title.value = '新增';
visible.value = true;
nextTick(() => {
registerForm.value.add();
});
}
/**
* 编辑
* @param record
*/
function edit(record) {
title.value = disableSubmit.value ? '详情' : '编辑';
visible.value = true;
nextTick(() => {
registerForm.value.edit(record);
});
}
/**
* 确定按钮点击事件
*/
function handleOk() {
registerForm.value.submitForm();
}
/**
* form保存回调事件
*/
function submitCallback() {
handleCancel();
emit('success');
}
/**
* 取消按钮回调事件
*/
function handleCancel() {
visible.value = false;
}
defineExpose({
add,
edit,
disableSubmit,
});
</script>
<style lang="less">
/**隐藏样式-modal确定按钮 */
.jee-hidden {
display: none !important;
}
</style>
<style lang="less" scoped></style>

View File

@ -6,6 +6,7 @@ const { createConfirm } = useMessage();
enum Api { enum Api {
list = '/services/serviceDirective/list', list = '/services/serviceDirective/list',
save = '/services/serviceDirective/add', save = '/services/serviceDirective/add',
batchAdd = '/services/serviceDirective/batchAdd',
edit = '/services/serviceDirective/edit', edit = '/services/serviceDirective/edit',
deleteOne = '/services/serviceDirective/delete', deleteOne = '/services/serviceDirective/delete',
deleteBatch = '/services/serviceDirective/deleteBatch', deleteBatch = '/services/serviceDirective/deleteBatch',
@ -21,6 +22,7 @@ enum Api {
idListByDS = '/services/serviceDirective/idListByDS', idListByDS = '/services/serviceDirective/idListByDS',
syncDirective = '/services/serviceDirective/syncDirective', syncDirective = '/services/serviceDirective/syncDirective',
useOrStopCascade = '/services/serviceDirective/useOrStopCascade', useOrStopCascade = '/services/serviceDirective/useOrStopCascade',
compareList = '/services/serviceDirective/compareList',
} }
/** /**
@ -94,6 +96,13 @@ export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save; let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params }, { isTransformResponse: false }); return defHttp.post({ url: url, params }, { isTransformResponse: false });
}; };
/**
*
* @param params
*/
export const batchAdd = (params) => {
return defHttp.post({ url: Api.batchAdd, params }, { isTransformResponse: false });
};
/** /**
* *
@ -141,4 +150,11 @@ export const syncDirective = (dataSourceCode: string, params: any) => {
*/ */
export const useOrStopCascade = (params) => { export const useOrStopCascade = (params) => {
return defHttp.post({ url: Api.useOrStopCascade, params }); return defHttp.post({ url: Api.useOrStopCascade, params });
}; };
/**
*
* @param params compareOrgCode
* @returns
*/
export const compareList = (params) => defHttp.get({ url: Api.compareList, params });

View File

@ -78,18 +78,18 @@ export const columns: BasicColumn[] = [
dataIndex: 'comPrice', dataIndex: 'comPrice',
width: 95, width: 95,
}, },
{ // {
title: '医保报销', // title: '医保报销',
align: 'center', // align: 'center',
dataIndex: 'izReimbursement_dictText', // dataIndex: 'izReimbursement_dictText',
width: 100, // width: 100,
}, // },
{ // {
title: '机构优惠', // title: '机构优惠',
align: 'center', // align: 'center',
dataIndex: 'izPreferential_dictText', // dataIndex: 'izPreferential_dictText',
width: 100, // width: 100,
}, // },
{ {
title: '周期类型', title: '周期类型',
align: 'center', align: 'center',
@ -114,11 +114,17 @@ export const columns: BasicColumn[] = [
width: 100, width: 100,
}, },
{ {
title: '服务指令图片', title: '服务指令图片大图',
align: 'center', align: 'center',
dataIndex: 'previewFile', dataIndex: 'previewFile',
customRender: render.renderImage, customRender: render.renderImage,
}, },
{
title: '服务指令图片小图',
align: 'center',
dataIndex: 'previewFileSmall',
customRender: render.renderImage,
},
{ {
title: '服务指令描述', title: '服务指令描述',
align: 'center', align: 'center',

View File

@ -0,0 +1,320 @@
<template>
<div>
<!--引用表格-->
<BasicTable @register="registerTable">
<!--插槽:table标题-->
<template #tableTitle>
</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 === '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>
<!-- 表单区域 -->
<ConfigServiceDirectiveModal ref="registerModal" @success="handleSuccess" :izAbnormal="true">
</ConfigServiceDirectiveModal>
</div>
<!-- 音频播放 -->
<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>
</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 './ConfigServiceDirectiveModal.vue'
import { useUserStore } from '/@/store/modules/user';
import { cloneDeep } from "lodash-es";
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
import { Empty } from 'ant-design-vue';
import { queryByKey } from '/@/views/admin/sysconfig/SysConfig.api'
import { getOrgInfo } from '@/api/common/api'
import { useMessage } from '/@/hooks/web/useMessage';
const { createMessage, createConfirm } = useMessage();
const queryParam = reactive<any>({
instructionTagId: '',
categoryId: '',
typeId: '',
izEnabled: '0',
});
watch(
() => queryParam.instructionTagId,
() => {
queryParam.categoryId = ''
queryParam.typeId = ''
}
)
//
watch(
() => queryParam.categoryId,
() => {
queryParam.typeId = ''
}
)
const registerModal = ref();
const treeData = 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.izAbnormal = true
params.column = 'createTime'
params.order = 'desc'
return params;
},
},
exportConfig: {
name: "服务指令",
url: getExportUrl,
params: queryParam,
},
importConfig: {
url: getImportUrl,
success: handleSuccess
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = tableContext;
const filterIzEnabled = ref('enabled')///
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
reloadTree()
}
/**
* 编辑事件
*/
function handleEdit(record: Recordable) {
registerModal.value.disableSubmit = false;
registerModal.value.opeType = 'edit';
record.izEnabled = ''
record.tollPrice = ''
registerModal.value.edit(record);
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record)
},
];
}
/**
* 下拉操作栏
*/
function getDropDownAction(record) {
return [
]
}
const showAudioModal = ref(false); //
const audioUrl = ref(''); // URL
const audioPlayer = ref(null);
//
const openAudioModal = (url) => {
audioUrl.value = getFileAccessHttpUrl(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 = getFileAccessHttpUrl(url);
showVideoModal.value = true;
};
//
const closeVideoModal = () => {
if (videoPlayer.value) {
videoPlayer.value.pause(); //
videoPlayer.value.currentTime = 0; //
}
showVideoModal.value = false;
videoUrl.value = '';
};
//
const isPlaying = ref(false);
function reloadTree() {
tree({ filterIzEnabled: filterIzEnabled.value }).then(res => {
treeData.value = res;
})
}
//
onMounted(() => {
if (audioPlayer.value) {
audioPlayer.value.addEventListener('ended', () => {
isPlaying.value = false;
});
}
});
defineExpose({
reload
});
</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;
}
}
</style>

View File

@ -0,0 +1,357 @@
<template>
<div class="compare-table-wrap">
<div style="margin-bottom: 14px;width: 100%;">
<a-button type="primary" style="float: right;" @click="showTargetOrgListModal"
:disabled="loading">目标机构</a-button>
</div>
<div class="table-card">
<!-- 表头两级 -->
<div class="thead">
<!-- 顶层 -->
<div class="thead-top">
<div class="th"></div>
<div class="th"></div>
<div class="th"></div>
<div class="th"></div>
<div class="th"></div>
<div class="th th-org" style="grid-column:6 / span 2;">源机构</div>
<div class="th th-org" style="grid-column:8 / span 2;">目标机构</div>
</div>
<!-- 次级 -->
<div class="thead-sub">
<div class="th">分类标签</div>
<div class="th">服务类别</div>
<div class="th">服务类型</div>
<div class="th">服务指令</div>
<div class="th">周期类型</div>
<div class="th th-name-sub">名称</div>
<div class="th th-exist-sub">是否存在</div>
<div class="th th-name-sub">名称</div>
<div class="th th-exist-sub">是否存在</div>
</div>
</div>
<!-- 表体 -->
<div v-if="!targetOrgInfo && !loading" class="status">未选择目标机构</div>
<div v-else class="body-div">
<div v-if="loading" class="status">加载中</div>
<div v-else-if="rows.length === 0" class="status">暂无数据</div>
<div v-else class="tbody">
<div class="tr" v-for="item in rows" :key="item.id || item.directiveName || item.instructionName"
:data-rank="rank(item)">
<div class="td td-tag" :title="item.instructionName || '-'">{{ item.instructionName || '-' }}
</div>
<div class="td td-category" :title="item.categoryName || '-'">{{ item.categoryName || '-' }}
</div>
<div class="td td-type" :title="item.typeName || '-'">{{ item.typeName || '-' }}</div>
<div class="td td-name" :title="item.directiveName || '-'">{{ item.directiveName || '-' }}</div>
<div class="td td-cycle" :title="item.cycleTypeName || '-'">{{ item.cycleTypeName || '-' }}
</div>
<!-- 源机构 -->
<div class="td td-org-name" :title="ownOrgName || '-'">{{ ownOrgName || '-' }}</div>
<div class="td td-org-exist center" :title="item.ownExist ? '源机构已存在' : '源机构不存在'">
<div class="org-badge">
<svg v-if="item.ownExist" class="icon check" viewBox="0 0 24 24" aria-hidden="true">
<path
d="M20.285 6.709l-11.39 11.39-5.18-5.18 1.414-1.414 3.766 3.766 9.976-9.976z" />
</svg>
<svg v-else class="icon cross" viewBox="0 0 24 24" aria-hidden="true">
<path
d="M18.3 5.71L12 12.01 5.7 5.71 4.29 7.12 10.59 13.42 4.29 19.72 5.7 21.13 12 14.83 18.3 21.13 19.71 19.72 13.41 13.42 19.71 7.12z" />
</svg>
</div>
</div>
<!-- 目标机构 -->
<div class="td td-org-name" :title="targetOrgInfo.comName || '-'">{{ targetOrgInfo.comName ||
'-' }}</div>
<div class="td td-org-exist center" :title="item.targetExist ? '目标机构已存在' : '目标机构不存在'">
<div class="org-badge">
<svg v-if="item.targetExist" class="icon check" viewBox="0 0 24 24" aria-hidden="true">
<path
d="M20.285 6.709l-11.39 11.39-5.18-5.18 1.414-1.414 3.766 3.766 9.976-9.976z" />
</svg>
<svg v-else class="icon cross" viewBox="0 0 24 24" aria-hidden="true">
<path
d="M18.3 5.71L12 12.01 5.7 5.71 4.29 7.12 10.59 13.42 4.29 19.72 5.7 21.13 12 14.83 18.3 21.13 19.71 19.72 13.41 13.42 19.71 7.12z" />
</svg>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<a-modal v-model:visible="targetOrgListVisible" title="请选择目标机构" width="90vw" @cancel="handleCancelTarget"
:bodyStyle="{ padding: '14px', height: '70vh', display: 'flex', flexDirection: 'column', overflow: 'auto' }">
<template #footer>
<a-button @click="handleCancelTarget" type="primary">取消</a-button>
<a-button @click="handleGetTarget" type="primary">确认</a-button>
</template>
<OrgListCom class="step-content" ref="targetOrgListComRef" @handleOrgChoose="handleTargetOrgChoose"
:showChoose="true" :showDirectiveChoose="true" :pageSize="-1" :excludeOrgCode="ownOrgCode" />
</a-modal>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { compareList } from '../ConfigServiceDirective.api';
import OrgListCom from '/@/views/orgcom/OrgListCom.vue';
const props = defineProps({
ownOrgCode: '',//
ownOrgName: '',//
});
const targetOrgInfo = ref('')//
type Row = {
id?: string;
instructionName?: string;
categoryName?: string;
typeName?: string;
directiveName?: string;
cycleTypeName?: string;
ownExist?: boolean;
targetExist?: boolean;
};
const rows = ref<Row[]>([]);
const loading = ref(false);
const targetOrgListVisible = ref(false);
const targetOrgListComRef = ref();
function rank(it: Row) {
if (it.ownExist && it.targetExist) return 'both';
if (it.ownExist) return 'own-only';
return 'target-only';
}
function handleCancelTarget() {
targetOrgListVisible.value = false;
targetOrgListComRef.value?.resetSeleted?.([]);
}
function showTargetOrgListModal() {
targetOrgListComRef.value?.reload?.()
targetOrgListVisible.value = true;
}
function handleGetTarget() {
if (!targetOrgInfo.value) {
targetOrgListVisible.value = false;
return;
}
initData()
handleCancelTarget()
}
function handleTargetOrgChoose(orgInfo_: any) {
targetOrgInfo.value = orgInfo_
}
async function initData() {
loading.value = true;
rows.value = [];
try {
let res = await compareList({ compareOrgCode: targetOrgInfo.value.orgCode })
if (Array.isArray(res)) rows.value = res;
else if (res && Array.isArray(res.result)) rows.value = res.result;
else if (res && Array.isArray(res.list)) rows.value = res.list;
else if (res && Array.isArray(res.data)) rows.value = res.data;
else rows.value = res || [];
} catch (e) {
rows.value = [];
console.error('compareList error', e);
} finally {
loading.value = false;
}
}
</script>
<style lang="less" scoped>
.compare-table-wrap {
padding: 16px;
background: #f6f8fb;
font-family: "PingFang SC", "Microsoft YaHei", Arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
}
.table-card {
width: 100%;
max-width: 100%;
background: #fff;
border-radius: 8px;
overflow: hidden;
border: 1px solid #e6eef8;
box-shadow: 0 6px 18px rgba(2, 6, 23, 0.04);
}
.thead {
background: linear-gradient(180deg, #fbfdff, #ffffff);
border-bottom: 1px solid #e6eef8;
}
.thead-top,
.thead-sub,
.tr {
display: grid;
gap: 12px;
align-items: center;
justify-items: center;
}
.thead-top {
grid-template-columns: 1fr 1fr 1fr 2fr 1fr 2fr 1fr 2fr 1fr;
padding: 12px 14px 0px 14px;
font-weight: 600;
color: #374151;
}
.thead-sub {
grid-template-columns: 1fr 1fr 1fr 2fr 1fr 2fr 1fr 2fr 1fr;
padding: 0px 14px 8px 14px;
border-bottom: 1px solid #e6eef8;
color: #374151;
font-size: 13px;
font-weight: 600;
}
.th {
padding: 6px 4px;
text-align: center;
}
.tbody {
display: flex;
flex-direction: column;
}
.tr {
grid-template-columns: 1fr 1fr 1fr 2fr 1fr 2fr 1fr 2fr 1fr;
padding: 12px 14px;
background: #fff;
border-bottom: 1px solid #eef6fb;
}
.tr:last-child {
border-bottom: none;
}
.td {
padding: 6px 4px;
font-size: 14px;
color: #111827;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: center;
width: 100%;
}
.td-org-name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.td-org-exist {
display: flex;
align-items: center;
justify-content: center;
}
.org-badge {
width: 36px;
height: 36px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
background: #fbfdff;
}
.icon {
width: 20px;
height: 20px;
fill: currentColor;
}
.icon.check {
color: #10b981;
}
.icon.cross {
color: #ef4444;
}
.status {
padding: 14px;
background: #fff;
border-radius: 8px;
color: #6b7280;
text-align: center;
box-shadow: 0 6px 14px rgba(2, 6, 23, 0.03);
margin-top: 8px;
width: 100%;
}
.body-div {
height: 65vh;
overflow-y: scroll;
// scrollbar-width: none;
// -ms-overflow-style: none;
}
// .body-div::-webkit-scrollbar {
// width: 0;
// height: 0;
// background: transparent;
// }
@media (max-width: 1000px) {
.thead-top,
.thead-sub,
.tr {
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 80px 80px 80px;
}
.td-name,
.th.th-name {
display: none;
}
}
@media (max-width: 700px) {
.thead {
display: none;
}
.tr {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
padding: 12px;
}
.td {
white-space: normal;
text-align: center;
}
.center {
justify-content: center;
gap: 8px;
}
}
</style>

View File

@ -77,18 +77,18 @@ export const columns: BasicColumn[] = [
align: 'center', align: 'center',
dataIndex: 'comPrice', dataIndex: 'comPrice',
}, },
{ // {
title: '医保报销', // title: '医保报销',
align: 'center', // align: 'center',
dataIndex: 'izReimbursement_dictText', // dataIndex: 'izReimbursement_dictText',
width: 100, // width: 100,
}, // },
{ // {
title: '机构优惠', // title: '机构优惠',
align: 'center', // align: 'center',
dataIndex: 'izPreferential_dictText', // dataIndex: 'izPreferential_dictText',
width: 100, // width: 100,
}, // },
{ {
title: '周期类型', title: '周期类型',
align: 'center', align: 'center',

View File

@ -1,12 +1,46 @@
<template> <template>
<a-spin :spinning="confirmLoading"> <a-spin :spinning="confirmLoading">
<div
style="padding-top: 14px;padding-left: 14px;padding-right: 14px; background-color: #fff;border-radius: 10px;box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);margin-bottom: 14px;">
<JFormContainer :disabled="disabled">
<template #detail>
<a-form ref="formRef" :labelCol="labelCol" :wrapperCol="wrapperCol" :colon="false"
name="ConfigService2DirectiveForm" style="padding: 0px 0px;">
<a-row v-show="!isEditMedia">
<a-col :span="8">
<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 and iz_enabled = 0 order by sort asc`"
placeholder="请选择分类标签" allowClear @upDictCode="upInstructionDictCode" disabled />
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="服务类别" v-bind="validateInfos.categoryId" id="ConfigServiceDirectiveForm-categoryId"
name="categoryId">
<j-dict-select-tag type="list" v-model:value="formData.categoryId" disabled :orgCode="mainOrgCode"
:dictCode="categoryDictCode" placeholder="请选择服务类别" allow-clear @upDictCode="upCategoryDictCode" />
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="服务类型" v-bind="validateInfos.typeId" id="ConfigServiceDirectiveForm-typeId"
name="typeId">
<j-dict-select-tag type="list" v-model:value="formData.typeId" :dictCode="typeDictCode"
:orgCode="mainOrgCode" disabled placeholder="请选择服务类型" allowClear @upDictCode="upTypeDictCode" />
</a-form-item>
</a-col>
</a-row>
</a-form>
</template>
</JFormContainer>
</div>
<div style="padding: 14px;background-color: #fff;border-radius: 10px;box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);"> <div style="padding: 14px;background-color: #fff;border-radius: 10px;box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);">
<JFormContainer :disabled="disabled"> <JFormContainer :disabled="disabled">
<template #detail> <template #detail>
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol" :colon="false" <a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol" :colon="false"
name="ConfigService2DirectiveForm" style="padding: 20px 0px;"> name="ConfigService2DirectiveForm" style="padding: 20px 0px;">
<a-row v-show="!isEditMedia"> <a-row v-show="!isEditMedia">
<a-col :span="12" v-show="false"> <!-- <a-col :span="12" v-show="false">
<a-form-item label="分类标签" v-bind="validateInfos.instructionTagId" <a-form-item label="分类标签" v-bind="validateInfos.instructionTagId"
id="ConfigServiceDirectiveForm-instructionTagId" name="instructionTagId"> id="ConfigServiceDirectiveForm-instructionTagId" name="instructionTagId">
<j-dict-select-tag v-model:value="formData.instructionTagId" :orgCode="mainOrgCode" <j-dict-select-tag v-model:value="formData.instructionTagId" :orgCode="mainOrgCode"
@ -29,7 +63,7 @@
:orgCode="mainOrgCode" :disabled="!!formData.id" placeholder="请选择服务类型" allowClear :orgCode="mainOrgCode" :disabled="!!formData.id" placeholder="请选择服务类型" allowClear
@upDictCode="upTypeDictCode" /> @upDictCode="upTypeDictCode" />
</a-form-item> </a-form-item>
</a-col> </a-col> -->
<a-col :span="12"> <a-col :span="12">
<a-form-item label="服务指令名称" v-bind="validateInfos.directiveName" <a-form-item label="服务指令名称" v-bind="validateInfos.directiveName"
id="ConfigServiceDirectiveForm-directiveName" name="directiveName"> id="ConfigServiceDirectiveForm-directiveName" name="directiveName">
@ -110,7 +144,7 @@
<div class="upload-area"> <div class="upload-area">
<p class="upload-text">点击或者拖拽上传</p> <p class="upload-text">点击或者拖拽上传</p>
<div class="upload-icon"> <div class="upload-icon">
<img src="./mp3type.png" alt="MP3 icon" style="width: 40px; height: 40px;" /> <img src="./pictype.png" alt="MP3 icon" style="width: 40px; height: 40px;" />
</div> </div>
<p class="upload-hint"> <p class="upload-hint">
<span>文件大小不超过10MB</span> <span>文件大小不超过10MB</span>
@ -134,7 +168,7 @@
<div class="upload-area"> <div class="upload-area">
<p class="upload-text">点击或者拖拽上传</p> <p class="upload-text">点击或者拖拽上传</p>
<div class="upload-icon"> <div class="upload-icon">
<img src="./mp4type.png" alt="MP3 icon" style="width: 40px; height: 40px;" /> <img src="./mp3type.png" alt="MP3 icon" style="width: 40px; height: 40px;" />
</div> </div>
<p class="upload-hint"> <p class="upload-hint">
<span>文件大小不超过10MB</span> <span>文件大小不超过10MB</span>
@ -153,6 +187,30 @@
</a-upload-dragger> </a-upload-dragger>
</a-col> </a-col>
<a-col :span="24" v-show="directiveMediaBtnValue == 3"> <a-col :span="24" v-show="directiveMediaBtnValue == 3">
<a-upload-dragger name="file" v-model:fileList="fileList" :multiple="false" :show-upload-list="false"
:before-upload="beforeUpload" style="background-color: #F6FAFF;">
<div class="upload-area">
<p class="upload-text">点击或者拖拽上传</p>
<div class="upload-icon">
<img src="./mp4type.png" alt="MP3 icon" style="width: 40px; height: 40px;" />
</div>
<p class="upload-hint">
<span>文件大小不超过10MB</span>
<span class="divider">|</span>
<a-tooltip placement="top">
<template #title>
这里是格式说明的具体内容
</template>
<span>
<QuestionCircleOutlined style="margin-right: 0px;" />
格式说明
</span>
</a-tooltip>
</p>
</div>
</a-upload-dragger>
</a-col>
<a-col :span="24" v-show="directiveMediaBtnValue == 4">
<a-upload-dragger name="file" v-model:fileList="fileList" :multiple="false" :show-upload-list="false" <a-upload-dragger name="file" v-model:fileList="fileList" :multiple="false" :show-upload-list="false"
:before-upload="beforeUpload" style="background-color: #F6FAFF;"> :before-upload="beforeUpload" style="background-color: #F6FAFF;">
<div class="upload-area"> <div class="upload-area">
@ -337,8 +395,8 @@ const validatorRules = reactive({
directiveName: [{ required: true, message: '请输入服务指令名称!' },], directiveName: [{ required: true, message: '请输入服务指令名称!' },],
tollPrice: [{ required: true, message: '请输入收费价格!' }, { pattern: /^(([0-9]*)|([0]\.\d{0,4}|[1-9][0-9]*\.\d{0,4}))$/, message: '请输入正确的金额!' },], tollPrice: [{ required: true, message: '请输入收费价格!' }, { pattern: /^(([0-9]*)|([0]\.\d{0,4}|[1-9][0-9]*\.\d{0,4}))$/, message: '请输入正确的金额!' },],
comPrice: [{ required: false }, { pattern: /^(([0-9]*)|([0]\.\d{0,4}|[1-9][0-9]*\.\d{0,4}))$/, message: '请输入正确的金额!' },], comPrice: [{ required: false }, { pattern: /^(([0-9]*)|([0]\.\d{0,4}|[1-9][0-9]*\.\d{0,4}))$/, message: '请输入正确的金额!' },],
izReimbursement: [{ required: true, message: '请选择是否参与医保报销!' },], // izReimbursement: [{ required: true, message: '!' },],
izPreferential: [{ required: true, message: '请选择是否参与机构优惠!' },], // izPreferential: [{ required: true, message: '!' },],
// chargingFrequency: [{ required: true, message: '!' },], // chargingFrequency: [{ required: true, message: '!' },],
cycleType: [{ required: true, message: '请选择周期类型!' },], cycleType: [{ required: true, message: '请选择周期类型!' },],
// sort: [{ required: true, message: '!' }, { pattern: /^\d+$/, message: '!' },], // sort: [{ required: true, message: '!' }, { pattern: /^\d+$/, message: '!' },],
@ -461,7 +519,7 @@ watch(
if (needWatch.value) { if (needWatch.value) {
formData.categoryId = '' formData.categoryId = ''
formData.typeId = '' formData.typeId = ''
formData.cycleType = '' // formData.cycleType = ''
} }
if (!newInstructionTagId) { if (!newInstructionTagId) {
categoryDictCode.value = 'nu_config_service_category,category_name,id,1=2'; categoryDictCode.value = 'nu_config_service_category,category_name,id,1=2';
@ -475,7 +533,7 @@ watch(
(newCategoryId) => { (newCategoryId) => {
if (needWatch.value) { if (needWatch.value) {
formData.typeId = '' formData.typeId = ''
formData.cycleType = '' // formData.cycleType = ''
} }
if (!newCategoryId) { if (!newCategoryId) {
typeDictCode.value = 'nu_config_service_type,type_name,id,1=2'; typeDictCode.value = 'nu_config_service_type,type_name,id,1=2';
@ -488,7 +546,7 @@ watch(
() => formData.typeId, () => formData.typeId,
(newTypeId) => { (newTypeId) => {
if (needWatch.value) { if (needWatch.value) {
formData.cycleType = '' // formData.cycleType = ''
} }
} }
); );

View File

@ -1,6 +1,6 @@
<template> <template>
<a-spin :spinning="confirmLoading"> <a-spin :spinning="confirmLoading">
<div style="padding: 14px;background-color: #fff;border-radius: 10px;box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);"> <div style="padding: 14px; background-color: #fff;border-radius: 10px;box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);">
<JFormContainer :disabled="disabled"> <JFormContainer :disabled="disabled">
<template #detail> <template #detail>
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol" :colon="false" <a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol" :colon="false"
@ -73,127 +73,82 @@
</a-form-item> </a-form-item>
</a-col> </a-col>
</a-row> </a-row>
<a-row style="padding: 20px;"> <a-row style="margin-top: 20px;">
<a-col :span="6"> <a-col :span="12" v-show="showMedia">
<DirectiveRadioCom :directiveMediaBtnValue="directiveMediaBtnValue" @change="mediaBtnChanged"> <a-form-item label="服务指令图片" v-bind="validateInfos.previewFile">
</DirectiveRadioCom> <span v-if="disabled && !formData.previewFile">暂无文件</span>
<JImageUpload v-else-if="opeType == 'dmlook'" :fileMax="1"
:value="mediaApiAddress + formData.previewFile">
</JImageUpload>
<JImageUpload v-else :fileMax="1" v-model:value="formData.previewFile"></JImageUpload>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="服务指令描述" v-bind="validateInfos.serviceContent"
id="ConfigServiceDirectiveForm-serviceContent" name="serviceContent">
<a-textarea v-model:value="formData.serviceContent" :autosize="true" placeholder="请输入服务指令描述"
:maxlength="200" :showCount="true" />
</a-form-item>
</a-col> </a-col>
</a-row> </a-row>
<a-row style="padding: 0px 20px;"> <a-row v-show="!disabled && showMedia">
<a-col :span="24" v-show="directiveMediaBtnValue == 0"> <a-col :span="12">
<a-upload-dragger name="file" v-model:fileList="fileList" :multiple="false" :show-upload-list="false" <a-form-item label="指令音频文件" v-bind="validateInfos.mp3File" id="ConfigServiceDirectiveForm-mp3File">
:before-upload="beforeUpload" style="background-color: #F6FAFF;"> <j-upload v-model:value="formData.mp3File" accept=".mp3" :maxCount="1"
<div class="upload-area"> :beforeUpload="checkMp3"></j-upload>
<p class="upload-text">点击或者拖拽上传</p> </a-form-item>
<div class="upload-icon">
<img src="./pictype.png" alt="MP3 icon" style="width: 40px; height: 40px;" />
</div>
<p class="upload-hint">
<span>文件大小不超过10MB</span>
<span class="divider">|</span>
<a-tooltip placement="top">
<template #title>
这里是格式说明的具体内容
</template>
<span>
<QuestionCircleOutlined style="margin-right: 0px;" />
格式说明
</span>
</a-tooltip>
</p>
</div>
</a-upload-dragger>
</a-col> </a-col>
<a-col :span="24" v-show="directiveMediaBtnValue == 1"> <a-col :span="12">
<a-upload-dragger name="file" v-model:fileList="fileList" :multiple="false" :show-upload-list="false" <a-form-item label="指令视频文件" v-bind="validateInfos.mp4File" id="ConfigServiceDirectiveForm-mp4File">
:before-upload="beforeUpload" style="background-color: #F6FAFF;"> <j-upload v-model:value="formData.mp4File" accept=".mp4" :maxCount="1"
<div class="upload-area"> :beforeUpload="checkMp4"></j-upload>
<p class="upload-text">点击或者拖拽上传</p> </a-form-item>
<div class="upload-icon">
<img src="./mp3type.png" alt="MP3 icon" style="width: 40px; height: 40px;" />
</div>
<p class="upload-hint">
<span>文件大小不超过10MB</span>
<span class="divider">|</span>
<a-tooltip placement="top">
<template #title>
这里是格式说明的具体内容
</template>
<span>
<QuestionCircleOutlined style="margin-right: 0px;" />
格式说明
</span>
</a-tooltip>
</p>
</div>
</a-upload-dragger>
</a-col>
<a-col :span="24" v-show="directiveMediaBtnValue == 2">
<a-upload-dragger name="file" v-model:fileList="fileList" :multiple="false" :show-upload-list="false"
:before-upload="beforeUpload" style="background-color: #F6FAFF;">
<div class="upload-area">
<p class="upload-text">点击或者拖拽上传</p>
<div class="upload-icon">
<img src="./mp4type.png" alt="MP3 icon" style="width: 40px; height: 40px;" />
</div>
<p class="upload-hint">
<span>文件大小不超过10MB</span>
<span class="divider">|</span>
<a-tooltip placement="top">
<template #title>
这里是格式说明的具体内容
</template>
<span>
<QuestionCircleOutlined style="margin-right: 0px;" />
格式说明
</span>
</a-tooltip>
</p>
</div>
</a-upload-dragger>
</a-col>
<a-col :span="24" v-show="directiveMediaBtnValue == 3">
<a-upload-dragger name="file" v-model:fileList="fileList" :multiple="false" :show-upload-list="false"
:before-upload="beforeUpload" style="background-color: #F6FAFF;">
<div class="upload-area">
<p class="upload-text">点击或者拖拽上传</p>
<div class="upload-icon">
<img src="./pictype.png" alt="MP3 icon" style="width: 40px; height: 40px;" />
</div>
<p class="upload-hint">
<span>文件大小不超过10MB</span>
<span class="divider">|</span>
<a-tooltip placement="top">
<template #title>
这里是格式说明的具体内容
</template>
<span>
<QuestionCircleOutlined style="margin-right: 0px;" />
格式说明
</span>
</a-tooltip>
</p>
</div>
</a-upload-dragger>
</a-col> </a-col>
</a-row> </a-row>
<a-row style="padding: 20px;"> </a-form>
<a-col :span="2"> </template>
<div class="description-container"> </JFormContainer>
<a-button @click="toggleDescription">服务指令描述</a-button> <JFormContainer style="margin-top: -40px;" v-show="showMedia">
<div v-show="showDescription" class="description-box"> <template #detail>
<div class="box-header"> <a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol" :colon="false"
<span class="title">服务指令描述</span> name="ConfigServiceDirectiveForm">
<span class="collapse-icon" @click="toggleDescription"> <a-row>
<DownOutlined style="margin-right: 3px;" />收起 <a-col :span="12" v-if="!!formData.mp3File">
</span> <a-form-item label="指令音频预览" id="ConfigServiceDirectiveForm-mp3File">
</div> <audio controls disabled="false">
<div> <source
<a-textarea v-model:value="formData.serviceContent" placeholder="请输入服务指令描述" :maxlength="200" :src="opeType == 'dmlook' ? mediaApiAddress + formData.mp3File : getFileAccessHttpUrl(formData.mp3File)">
:rows="3" :autosize="{ minRows: 3 }" :showCount="true" /> </audio>
</div> </a-form-item>
</div> </a-col>
</div> <a-col :span="12" v-if="disabled && !formData.mp3File">
<a-form-item label="指令音频预览">
<span>暂无文件</span>
</a-form-item>
</a-col>
<a-col :span="12" v-if="!!formData.mp4File" :push="!!formData.mp3File ? 0 : 12">
<a-form-item label="指令视频预览" id="ConfigServiceDirectiveForm-mp4File">
<video controls>
<source
:src="opeType == 'dmlook' ? mediaApiAddress + formData.mp4File : getFileAccessHttpUrl(formData.mp4File)">
</video>
</a-form-item>
</a-col>
<a-col :span="12" v-if="disabled && !formData.mp3File">
<a-form-item label="指令视频预览">
<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-if="opeType == 'dmlook'" :fileMax="1"
:value="mediaApiAddress + formData.immediateFile">
</JImageUpload>
<JImageUpload v-else :fileMax="1" v-model:value="formData.immediateFile"></JImageUpload>
</a-form-item>
</a-col> </a-col>
</a-row> </a-row>
</a-form> </a-form>
@ -337,8 +292,8 @@ const validatorRules = reactive({
directiveName: [{ required: true, message: '请输入服务指令名称!' },], directiveName: [{ required: true, message: '请输入服务指令名称!' },],
tollPrice: [{ required: true, message: '请输入收费价格!' }, { pattern: /^(([0-9]*)|([0]\.\d{0,4}|[1-9][0-9]*\.\d{0,4}))$/, message: '请输入正确的金额!' },], tollPrice: [{ required: true, message: '请输入收费价格!' }, { pattern: /^(([0-9]*)|([0]\.\d{0,4}|[1-9][0-9]*\.\d{0,4}))$/, message: '请输入正确的金额!' },],
comPrice: [{ required: false }, { pattern: /^(([0-9]*)|([0]\.\d{0,4}|[1-9][0-9]*\.\d{0,4}))$/, message: '请输入正确的金额!' },], comPrice: [{ required: false }, { pattern: /^(([0-9]*)|([0]\.\d{0,4}|[1-9][0-9]*\.\d{0,4}))$/, message: '请输入正确的金额!' },],
izReimbursement: [{ required: true, message: '请选择是否参与医保报销!' },], // izReimbursement: [{ required: true, message: '!' },],
izPreferential: [{ required: true, message: '请选择是否参与机构优惠!' },], // izPreferential: [{ required: true, message: '!' },],
// chargingFrequency: [{ required: true, message: '!' },], // chargingFrequency: [{ required: true, message: '!' },],
cycleType: [{ required: true, message: '请选择周期类型!' },], cycleType: [{ required: true, message: '请选择周期类型!' },],
// sort: [{ required: true, message: '!' }, { pattern: /^\d+$/, message: '!' },], // sort: [{ required: true, message: '!' }, { pattern: /^\d+$/, message: '!' },],
@ -461,7 +416,7 @@ watch(
if (needWatch.value) { if (needWatch.value) {
formData.categoryId = '' formData.categoryId = ''
formData.typeId = '' formData.typeId = ''
formData.cycleType = '' // formData.cycleType = ''
} }
if (!newInstructionTagId) { if (!newInstructionTagId) {
categoryDictCode.value = 'nu_config_service_category,category_name,id,1=2'; categoryDictCode.value = 'nu_config_service_category,category_name,id,1=2';
@ -475,7 +430,7 @@ watch(
(newCategoryId) => { (newCategoryId) => {
if (needWatch.value) { if (needWatch.value) {
formData.typeId = '' formData.typeId = ''
formData.cycleType = '' // formData.cycleType = ''
} }
if (!newCategoryId) { if (!newCategoryId) {
typeDictCode.value = 'nu_config_service_type,type_name,id,1=2'; typeDictCode.value = 'nu_config_service_type,type_name,id,1=2';
@ -488,7 +443,7 @@ watch(
() => formData.typeId, () => formData.typeId,
(newTypeId) => { (newTypeId) => {
if (needWatch.value) { if (needWatch.value) {
formData.cycleType = '' // formData.cycleType = ''
} }
} }
); );

View File

@ -1,12 +1,7 @@
<template> <template>
<div class="tab-container" :class="{ compact }"> <div class="tab-container" :class="{ compact }">
<div <div v-for="(tab, index) in tabs" :key="index" class="tab-item" :class="{ active: activeTab === index }"
v-for="(tab, index) in tabs" @click="handleTabClick(index)">
:key="index"
class="tab-item"
:class="{ active: activeTab === index }"
@click="handleTabClick(index)"
>
<span class="tab-text">{{ tab }}</span> <span class="tab-text">{{ tab }}</span>
<div v-if="index < tabs.length - 1" class="tab-divider"></div> <div v-if="index < tabs.length - 1" class="tab-divider"></div>
</div> </div>
@ -29,7 +24,7 @@ const props = defineProps({
const emit = defineEmits(['update:directiveMediaBtnValue', 'change']) const emit = defineEmits(['update:directiveMediaBtnValue', 'change'])
const tabs = ['服务指令图片', '指令音频文件', '指令视频文件', '即时指令图标'] const tabs = ['服务指令图片(大)', '服务指令图片(小)', '指令音频文件', '指令视频文件', '即时指令图标']
const activeTab = ref(props.directiveMediaBtnValue) const activeTab = ref(props.directiveMediaBtnValue)
watch(() => props.directiveMediaBtnValue, (newVal) => { watch(() => props.directiveMediaBtnValue, (newVal) => {

View File

@ -149,7 +149,7 @@ const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
pageSizeOptions: ['15', '50', '70', '100'], pageSizeOptions: ['15', '50', '70', '100'],
}, },
actionColumn: { actionColumn: {
width: 200, width: 90,
fixed: 'right', fixed: 'right',
}, },
beforeFetch: async (params) => { beforeFetch: async (params) => {