This commit is contained in:
1378012178@qq.com 2025-08-12 08:52:53 +08:00
commit cf26287dcf
136 changed files with 11410 additions and 815 deletions

View File

@ -25,157 +25,7 @@
})();
</script>
<div id="app">
<style>
html[data-theme='dark'] .app-loading {
background-color: #2c344a;
}
html[data-theme='dark'] .app-loading .app-loading-title {
color: rgba(255, 255, 255, 0.85);
}
.app-loading {
display: flex;
width: 100%;
height: 100%;
justify-content: center;
align-items: center;
flex-direction: column;
background-color: #f4f7f9;
}
.app-loading .app-loading-wrap {
position: absolute;
top: 50%;
left: 50%;
display: flex;
-webkit-transform: translate3d(-50%, -50%, 0);
transform: translate3d(-50%, -50%, 0);
justify-content: center;
align-items: center;
flex-direction: column;
}
.app-loading .dots {
display: flex;
padding: 98px;
justify-content: center;
align-items: center;
}
.app-loading .app-loading-title {
display: flex;
margin-top: 10px;
margin-bottom: 20px;
font-size: 30px;
color: rgba(0, 0, 0, 0.85);
justify-content: center;
align-items: center;
}
.app-loading .app-loading-logo {
display: block;
width: 90px;
margin: 0 auto;
margin-bottom: 20px;
}
.dot {
position: relative;
display: inline-block;
width: 48px;
height: 48px;
margin-top: 30px;
font-size: 32px;
transform: rotate(45deg);
box-sizing: border-box;
animation: antRotate 1.2s infinite linear;
}
.dot i {
position: absolute;
display: block;
width: 20px;
height: 20px;
background-color: #0065cc;
border-radius: 100%;
opacity: 0.3;
transform: scale(0.75);
animation: antSpinMove 1s infinite linear alternate;
transform-origin: 50% 50%;
}
.dot i:nth-child(1) {
top: 0;
left: 0;
}
.dot i:nth-child(2) {
top: 0;
right: 0;
-webkit-animation-delay: 0.4s;
animation-delay: 0.4s;
}
.dot i:nth-child(3) {
right: 0;
bottom: 0;
-webkit-animation-delay: 0.8s;
animation-delay: 0.8s;
}
.dot i:nth-child(4) {
bottom: 0;
left: 0;
-webkit-animation-delay: 1.2s;
animation-delay: 1.2s;
}
@keyframes antRotate {
to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg);
}
}
@-webkit-keyframes antRotate {
to {
-webkit-transform: rotate(405deg);
transform: rotate(405deg);
}
}
@keyframes antSpinMove {
to {
opacity: 1;
}
}
@-webkit-keyframes antSpinMove {
to {
opacity: 1;
}
}
</style>
<div class="app-loading">
<div class="app-loading-wrap">
<img src="<%= basePublicPath %>/resource/img/logo.png" class="app-loading-logo" alt="Logo" />
<div class="app-loading-title"><%= title %></div>
<div class="app-loading-dots">
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span>
</div>
</div>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
<script src="/static/tums-player/tums-player.umd.min.js"></script>
<!-- 百度统计 -->
<script>
var _hmt = _hmt || [];
(function () {
var hm = document.createElement('script');
hm.src = 'https://hm.baidu.com/hm.js?0febd9e3cacb3f627ddac64d52caac39';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
<!-- 腾讯地图 -->
<script src="https://map.qq.com/api/gljs?v=1.exp&key=2E6BZ-ZC3E3-BMX3D-OWFUI-FLY2F-MLFFJ"></script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 KiB

View File

@ -20,7 +20,7 @@ enum Api {
}
/**
*
*
* @param params
*/
export const getNuList = (params) => {

View File

@ -23,6 +23,7 @@ enum Api {
GetPermCode = '/sys/permission/getPermCode',
//新加的获取图形验证码的接口
getInputCode = '/sys/randomImage',
randomCode = '/sys/randomInputCode',
//获取短信验证码的接口
getCaptcha = '/sys/sms',
//注册接口
@ -114,6 +115,10 @@ export function getCodeInfo(currdatetime) {
let url = Api.getInputCode + `/${currdatetime}`;
return defHttp.get({ url: url });
}
export function randomCode(currdatetime) {
let url = Api.randomCode + `/${currdatetime}`;
return defHttp.get({ url: url });
}
/**
* @description:
*/

View File

@ -3,7 +3,7 @@
* @Description: logo component
-->
<template>
<div class="anticon" :class="getAppLogoClass" @click="goHome" style="background: #e3f6fc;text-align: center;">
<div class="anticon" :class="getAppLogoClass" @click="goHome" style="background: #ceeef7;text-align: center;">
<img src="../../../assets/images/logo.png" />
<div class="ml-2 truncate md:opacity-100" :class="getTitleClass" v-show="showTitle">
{{ shortTitle }}

View File

@ -89,7 +89,6 @@
opt.getContainer = `.${prefixVar}-layout-content` as any;
}
}
console.log('getProps:opt',opt);
return opt as DrawerProps;
});

View File

@ -94,7 +94,7 @@
return Object.assign(
{
text: t('common.resetText'),
preIcon: 'ic:baseline-restart-alt',
preIcon: 'ant-design:reload-outlined',
},
props.resetButtonOptions
);

View File

@ -25,9 +25,31 @@
</a-button>
</div>
</a-upload>
<a-modal :open="previewVisible" :footer="null" @cancel="handleCancel()">
<img alt="example" style="width: 100%" :src="previewImage" />
</a-modal>
<!-- <img alt="example" style="width: 100%" :src="previewImage" /> -->
<!-- <a-modal :open="previewVisible" width="70%" class="imgView" :footer="null" @cancel="handleCancel()">
<div class="img-container">
<img
alt="example"
class="preview-img"
:src="previewImage"
/>
</div>
</a-modal> -->
<a-modal
:open="previewVisible"
:width="modalWidth"
:bodyStyle="{ padding: 0, display: 'flex', justifyContent: 'center', alignItems: 'center' }"
:footer="null"
@cancel="handleCancel"
>
<img
ref="previewImgRef"
class="preview-img"
:src="previewImage"
@load="handleImageLoad"
/>
</a-modal>
</div>
</template>
<script lang="ts">
@ -106,6 +128,7 @@
//
const previewVisible = ref<boolean>(false);
//
const multiple = computed(() => {
return props['fileMax'] > 1 || props['fileMax'] === 0;
@ -227,14 +250,26 @@
//
console.log(file);
}
const previewImgRef = ref<HTMLImageElement | null>(null);
const modalWidth = ref('auto');
/**
* 预览图片
*/
function handlePreview(file) {
previewImage.value = file.url || file.thumbUrl;
async function handlePreview(file) {
if (!file.url && !file.preview) {
file.preview = (await getBase64(file.originFileObj)) as string;
}
previewImage.value = file.url || file.preview;
previewVisible.value = true;
}
function getBase64(file: File) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
}
function getAvatarView() {
if (uploadFileList.length > 0) {
@ -247,6 +282,20 @@
previewVisible.value = false;
}
//
const handleImageLoad = () => {
if (!previewImgRef.value) return;
const img = previewImgRef.value;
const maxWidth = window.innerWidth * 0.9; // 90%
const maxHeight = window.innerHeight * 0.8; // 80%
//
const ratio = Math.min(maxWidth / img.naturalWidth, maxHeight / img.naturalHeight, 1);
modalWidth.value = `${img.naturalWidth * ratio}px`;
};
return {
state,
attrs,
@ -262,6 +311,9 @@
handlePreview,
handleCancel,
handleChange,
handleImageLoad,
previewImgRef,
modalWidth,
};
},
});
@ -276,4 +328,27 @@
margin-top: 8px;
color: #666;
}
/* 确保 Modal 内容区域填满 */
.imgView .ant-modal-body {
height: 80vh; /* 限制模态框高度,避免超出屏幕 */
display: flex;
align-items: center;
justify-content: center;
}
/* 图片容器 */
.img-container {
max-width: 100%;
max-height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
/* 图片自适应 */
.preview-img {
max-width: 100%;
max-height: 100%;
object-fit: contain; /* 保持比例,不拉伸 */
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div ref="containerRef" :class="`${prefixCls}-container`">
<a-upload
<a-upload
:headers="headers"
:multiple="multiple"
:action="uploadUrl"
@ -22,6 +22,12 @@
<span>{{ text }}</span>
</a-button>
</a-upload>
<template v-if="bindProps.fileType=='pdf' && maxCount=='1' && bindProps.value">
<a style="border:1px solid #d9d9d9;width:60px;text-align:center;border-radius:4px;padding:2px 5px;" @click="handleView({url:getFileAccessHttpUrl(bindProps.value)})">
<Icon icon="ant-design:search-outlined" style="color: rgb(140, 134, 134)" />
<span class="ant-upload-text" style="color: rgb(140, 134, 134)" >预览</span>
</a>
</template>
</div>
</template>
@ -38,6 +44,10 @@
import { UploadTypeEnum } from './upload.data';
import { getFileAccessHttpUrl, getHeaders } from '/@/utils/common/compUtils';
import UploadItemActions from './components/UploadItemActions.vue';
import { useGlobSetting } from '/@/hooks/setting';
import {encryptByBase64} from "@/utils/cipher";
const glob = useGlobSetting();
const { createMessage, createConfirm } = useMessage();
const { prefixCls } = useDesign('j-upload');
@ -357,6 +367,7 @@
//
function onFilePreview(file) {
console.log("🚀 ~ onFilePreview ~ file:", file)
if (isImageMode.value) {
createImgPreview({ imageList: [file.url], maskClosable: true });
} else {
@ -364,6 +375,18 @@
}
}
/**
* 预览
*/
function handleView(record) {
if (record && record.url) {
console.log('glob.onlineUrl', glob.viewUrl);
let url = encodeURIComponent(encryptByBase64(record.url));
let previewUrl = `${glob.viewUrl}?url=` + url;
window.open(previewUrl, '_blank');
}
}
function emitValue(value) {
emit('change', value);
emit('update:value', value);

View File

@ -65,7 +65,7 @@
//
modalTitle: {
type: String,
default: '护理单元选择',
default: '区域选择',
},
},
emits: ['register', 'getSelectResult'],
@ -112,7 +112,7 @@
//update-end-author:liusq date:2023-10-30 for: [issues/5514]
schemas: [
{
label: '护理单元名称',
label: '区域名称',
field: 'nuName',
component: 'JInput',
colProps: { span: 10 },
@ -122,13 +122,13 @@
//
const columns = [
{
title: '护理单元ID',
title: '区域ID',
dataIndex: 'nuId',
width: 180,
align: 'left',
},
{
title: '护理单元名称',
title: '区域名称',
dataIndex: 'nuName',
// width: 180,
},
@ -144,7 +144,7 @@
rowKey: 'nuId',
columns: [
{
title: '护理单元名称',
title: '区域名称',
dataIndex: 'nuName',
width: 40,
},

View File

@ -71,7 +71,7 @@
//
const pageSize = ref<number>(140);
//
const pageSizeOptions = ref<any>(['10', '20', '50', '100', '140']);
const pageSizeOptions = ref<any>(['15', '50', '80', '100']);
//
const searchIconValue = ref<string>('');
const { clipboardRef, isSuccessRef } = useCopyToClipboard(props.value);

View File

@ -27,6 +27,11 @@
}
}
.ant-drawer-body {
// background: url(../resource/img/modalback.png);
background: linear-gradient(135deg, #f6faff 0%, #f1f7ff 100%);
}
.ant-modal {
width: 520px;
padding-bottom: 0;
@ -47,6 +52,11 @@
.ant-modal-body {
padding: 0;
// background: url(../resource/img/modalback.png);
// background-repeat: no-repeat;
// background-size: cover;
background: linear-gradient(135deg, #f6faff 0%, #f1f7ff 100%);
> .scrollbar > .scrollbar__bar.is-horizontal {
display: none;

View File

@ -197,15 +197,9 @@
color: white !important;
background-color: #1890ff !important;
border-radius: 8px;
margin: 0px 20px 0 20px;
// margin: 0px 20px 0 20px;
}
.jeecg-menu-vertical .jeecg-menu-item:hover, .jeecg-menu-vertical .jeecg-menu-submenu-title:hover {
color: #fff !important;
border-radius: 8px;
background: #c9cacc;
margin: 10px 20px 0 20px;
}
.jeecg-menu-light.jeecg-menu-vertical .jeecg-menu-item-active.jeecg-menu-submenu {
color: #606266 !important;
background: #f0f0f0;
@ -220,4 +214,12 @@
margin-top: 10px;
padding: 8px;
}
.jeecg-menu-vertical .jeecg-menu-item:hover, .jeecg-menu-vertical .jeecg-menu-submenu-title:hover {
color: #fff !important;
border-radius: 8px;
background: #c9cacc;
// margin: 10px 20px 0 20px;
transform: scale(1.02);
}
</style>

View File

@ -107,7 +107,6 @@
//update-begin-author:taoyan date:2022-6-1 for: VUEN-1144 online
function storePathTitle(path) {
console.log('storePathTitle', path);
let title = '';
if (instance!.attrs) {
let item: any = instance!.attrs.item;

View File

@ -163,7 +163,7 @@ import { useMessage } from "/@/hooks/web/useMessage";
import AsyncListComponent from '@/components/dataAsync/AsyncMainList.vue'
const props = defineProps({
syncType: '',//'nuBaseInfo'
syncType: '',//'nuBaseInfo'
showSyncBtn: true,
});
const emit = defineEmits(['orgChanged', 'handleAsync']);

View File

@ -273,7 +273,7 @@
...unref(getProps),
...unref(getHeaderProps),
scroll: unref(getScrollRef),
loading: unref(getLoading),
loading: false,
tableLayout: 'fixed',
rowSelection: unref(getRowSelectionRef),
rowKey: unref(getRowKey),

View File

@ -131,5 +131,5 @@ export function registerGlobComp(app: App) {
.use(Cascader)
.use(Rate)
.use(Progress);
console.log("---初始化--- 全局注册Antd、仪表盘、流程设计器、online、流程等组件--------------")
// console.log("---初始化--- 全局注册Antd、仪表盘、流程设计器、online、流程等组件--------------")
}

View File

@ -135,10 +135,10 @@ img, video {
html[data-theme='light'] {
.jeecg-form-detail-effect {
*:not(.ant-select-selection-placeholder){
color: #606266!important;
// color: #606266!important;
}
.ant-row label {
color: #797c81 !important;
// color: #797c81 !important;
}
.ant-select-selector,
.ant-btn,

View File

@ -28,10 +28,10 @@ export function connectWebSocket(url: string) {
protocols: [token],
// update-begin--author:liaozhiyang---date:20240726---for[issues/6662] 演示系统socket总断换一个写法
onConnected: function (ws) {
console.log('[WebSocket] 连接成功', ws);
// console.log('[WebSocket] 连接成功', ws);
},
onDisconnected: function (ws, event) {
console.log('[WebSocket] 连接断开:', ws, event);
// console.log('[WebSocket] 连接断开:', ws, event);
},
onError: function (ws, event) {
console.log('[WebSocket] 连接发生错误: ', ws, event);
@ -78,11 +78,11 @@ export function connectWebSocket(url: string) {
}
function onOpen() {
console.log('[WebSocket] 连接成功');
// console.log('[WebSocket] 连接成功');
}
function onClose(e) {
console.log('[WebSocket] 连接断开:', e);
// console.log('[WebSocket] 连接断开:', e);
}
function onError(e) {

View File

@ -1,5 +1,5 @@
<template>
<Header :class="getHeaderClass" style="background-image: url('../resource/img/bj.png');">
<Header :class="getHeaderClass" class="headClass">
<!-- left start -->
<div :class="`${prefixCls}-left`" >
<!-- logo -->
@ -11,7 +11,7 @@
/>
<LayoutBreadcrumb v-if="getShowContent && getShowBread" :theme="getHeaderTheme" />
<!-- 欢迎语 -->
<span v-if="getShowContent && getShowBreadTitle && !getIsMobile" style="background: #e3f6fc !important;" :class="[prefixCls, `${prefixCls}--${getHeaderTheme}`,'headerIntroductionClass']"> {{t('layout.header.welcomeIn')}} {{ title }} </span>
<span v-if="getShowContent && getShowBreadTitle && !getIsMobile" style="background: #ceeef7 !important;" :class="[prefixCls, `${prefixCls}--${getHeaderTheme}`,'headerIntroductionClass']"> {{t('layout.header.welcomeIn')}} {{ title }} </span>
</div>
<!-- left end -->
@ -261,4 +261,11 @@
border-bottom: 0px;
border-left: 0px;
}
.headClass{
background-image: url('../resource/img/bj.png') !important;
background-repeat: no-repeat;
background-size: 100% auto;
background-color: #e5f5f9 !important;
}
</style>

View File

@ -4,7 +4,7 @@
<LayoutHeader fixed v-if="getShowFullHeaderRef" />
<Layout :class="[layoutClass]">
<LayoutSideBar v-if="getShowSidebar || getIsMobile" />
<Layout :class="`${prefixCls}-main`" style="background-image: url('../resource/img/bj.png');">
<Layout :class="`${prefixCls}-main`" >
<LayoutMultipleHeader />
<LayoutContent />
<LayoutFooter />

View File

@ -68,7 +68,7 @@ async function bootstrap(props?: MainAppProps) {
registerGlobComp(app);
//CAS单点登录
await useSso().ssoLogin();
// await useSso().ssoLogin();
// 配置路由
setupRouter(app);
@ -83,10 +83,10 @@ async function bootstrap(props?: MainAppProps) {
setupErrorHandle(app);
// 注册第三方组件
await registerThirdComp(app);
// await registerThirdComp(app);
// 当路由准备好时再执行挂载( https://next.router.vuejs.org/api/#isready)
await router.isReady();
// await router.isReady();
// 挂载应用
app.mount(getMountContainer(props), true);

View File

@ -212,7 +212,7 @@ export const usePermissionStore = defineStore({
// 后台菜单构建
case PermissionModeEnum.BACK:
const { createMessage, createWarningModal } = useMessage();
console.log(" --- 构建后台路由菜单 --- ")
// console.log(" --- 构建后台路由菜单 --- ")
// 菜单加载提示
// createMessage.loading({
// content: t('sys.app.menuLoading'),

View File

@ -117,7 +117,7 @@ const pagination = reactive({
total: 0,
showSizeChanger: true,
showQuickJumper: true,
pageSizeOptions: ['10', '20', '30', '50'],
pageSizeOptions: ['15', '50', '80', '100'],
showTotal: total => `${total}`
});

View File

@ -1,7 +1,12 @@
<template>
<j-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<a-drawer :title="title" :width="width" v-model:visible="visible" :closable="true"
:footer-style="{ textAlign: 'right' }" @close="handleCancel">
<NuIssueInfoForm ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></NuIssueInfoForm>
</j-modal>
<template #footer>
<a-button type="primary" style="margin-right: 8px" @click="handleCancel">关闭</a-button>
<a-button type="primary" @click="handleOk" v-if="!disableSubmit">确认</a-button>
</template>
</a-drawer>
</template>
<script lang="ts" setup>
@ -10,7 +15,7 @@
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
const title = ref<string>('');
const width = ref<number>(800);
const width = ref<string>('70%');
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();

View File

@ -53,6 +53,7 @@ const formData = reactive<Record<string, any>>({
id: '',
issueType: '',
content: '',
createTime: '',
});
const { createMessage } = useMessage();
const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } });

View File

@ -1,7 +1,12 @@
<template>
<j-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<a-drawer :title="title" :width="width" v-model:visible="visible" :closable="true"
:footer-style="{ textAlign: 'right' }" @close="handleCancel">
<NuIssueInfoForm ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></NuIssueInfoForm>
</j-modal>
<template #footer>
<a-button type="primary" style="margin-right: 8px" @click="handleCancel">关闭</a-button>
<a-button type="primary" @click="handleOk" v-if="!disableSubmit">确认</a-button>
</template>
</a-drawer>
</template>
<script lang="ts" setup>
@ -10,7 +15,7 @@
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
const title = ref<string>('');
const width = ref<number>(800);
const width = ref<string>('70%');
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();

View File

@ -38,27 +38,10 @@
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
<!-- <a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button> -->
<a-dropdown v-if="selectedRowKeys.length > 0">
<template #overlay>
<a-menu>
<a-menu-item key="1" @click="batchHandleDelete">
<Icon icon="ant-design:delete-outlined"></Icon>
删除
</a-menu-item>
</a-menu>
</template>
<a-button>批量操作
<Icon icon="mdi:chevron-down"></Icon>
</a-button>
</a-dropdown>
<!-- 高级查询 -->
<!-- <super-query :config="superQueryConfig" @search="handleSuperQuery" /> -->
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
<TableAction :actions="getTableAction(record)" />
</template>
<template v-slot:bodyCell="{ column, record, index, text }">
<template v-if="column.dataIndex === 'versionUrl'">
@ -99,7 +82,7 @@ const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
canResize: false,
useSearchForm: false,
actionColumn: {
width: 120,
width: 140,
fixed: 'right',
},
beforeFetch: async (params) => {
@ -195,14 +178,6 @@ function getTableAction(record) {
label: '编辑',
onClick: handleEdit.bind(null, record)
},
];
}
/**
* 下拉操作栏
*/
function getDropDownAction(record) {
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
@ -214,6 +189,14 @@ function getDropDownAction(record) {
placement: 'topLeft',
}
}
];
}
/**
* 下拉操作栏
*/
function getDropDownAction(record) {
return [
]
}

View File

@ -1,7 +1,12 @@
<template>
<j-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<a-drawer :title="title" :width="width" v-model:visible="visible" :closable="true"
:footer-style="{ textAlign: 'right' }" @close="handleCancel">
<AppVersionConfigForm ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></AppVersionConfigForm>
</j-modal>
<template #footer>
<a-button type="primary" style="margin-right: 8px" @click="handleCancel">关闭</a-button>
<a-button type="primary" @click="handleOk" v-if="!disableSubmit">确认</a-button>
</template>
</a-drawer>
</template>
<script lang="ts" setup>
@ -10,7 +15,7 @@
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
const title = ref<string>('');
const width = ref<number>(800);
const width = ref<string>('70%');
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();

View File

@ -1,6 +1,6 @@
<template>
<a-spin :spinning="confirmLoading">
<JFormContainer :disabled="disabled">
<JFormContainer >
<template #detail>
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol"
name="NuOrgInfoForm">
@ -8,11 +8,8 @@
<a-col :span="24">
<SectionDivider :title="'机构信息'" />
</a-col>
<a-col :span="12">
<a-form-item label="机构名称" v-bind="validateInfos.departName" id="WorkOrderForm-departName" name="departName">
{{formData.departName}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="机构编码" v-bind="validateInfos.orgCode" id="WorkOrderForm-orgCode" name="orgCode">
{{formData.orgCode}}
@ -25,104 +22,41 @@
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="机构负责人电话" v-bind="validateInfos.orgLeaderPhone" id="OrgApplyInfoForm-orgLeaderPhone"
<a-form-item label="机构位置">
{{cityViewValue}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="负责人电话" v-bind="validateInfos.orgLeaderPhone" id="OrgApplyInfoForm-orgLeaderPhone"
name="orgLeaderPhone">
{{formData.orgLeaderPhone}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="机构房屋性质" v-bind="validateInfos.orgPropertyType" id="OrgApplyInfoForm-orgPropertyType"
<a-form-item label="机构名称" v-bind="validateInfos.departName" id="WorkOrderForm-departName" name="departName">
{{formData.departName}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="房屋性质" v-bind="validateInfos.orgPropertyType" id="OrgApplyInfoForm-orgPropertyType"
name="orgPropertyType">
{{formData.orgPropertyType}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="机构建筑面积" v-bind="validateInfos.orgBuildingArea" id="OrgApplyInfoForm-orgBuildingArea"
name="orgBuildingArea">
{{formData.orgBuildingArea}}
</a-form-item>
</a-col>
<!-- <a-col :span="12">
<a-form-item label="机构所在地">
{{cityViewValue}}
</a-form-item>
</a-col> -->
<a-col :span="12">
<a-form-item label="机构地址" v-bind="validateInfos.orgAddress" id="OrgApplyInfoForm-orgAddress"
name="orgAddress">
{{formData.orgAddress}}
</a-form-item>
</a-col>
</a-row>
<a-row>
<a-col :span="24">
<SectionDivider :title="'申请人身份证'" />
</a-col>
</a-row>
<a-row>
<a-col :span="12">
<a-form-item label="身份证正面" v-bind="validateInfos.cardZmPath" id="OrgApplyInfoForm-cardZmPath"
name="cardZmPath">
<JImageUpload :fileMax="1" v-model:value="formData.cardZmPath" :disabled="true"></JImageUpload>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="身份证反面" v-bind="validateInfos.cardFmPath" id="OrgApplyInfoForm-cardFmPath"
name="cardFmPath">
<JImageUpload :fileMax="1" v-model:value="formData.cardFmPath" :disabled="true"></JImageUpload>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="姓名" v-bind="validateInfos.name" id="OrgApplyInfoForm-name" name="name">
{{formData.name}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="性别" v-bind="validateInfos.sex" id="OrgApplyInfoForm-sex" name="sex">
{{formData.sex}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="身份证号" v-bind="validateInfos.idCard" id="OrgApplyInfoForm-idCard" name="idCard">
{{formData.idCard}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="出生日期" v-bind="validateInfos.birthDate" id="OrgApplyInfoForm-birthDate"
name="birthDate">
{{formData.birthDate?formData.birthDate.substring(0,10):""}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="有效开始日期" v-bind="validateInfos.startTime" id="OrgApplyInfoForm-startTime"
name="startTime">
{{formData.startTime?formData.startTime.substring(0,10):""}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="有效结束日期" v-bind="validateInfos.endTime" id="OrgApplyInfoForm-endTime" name="endTime">
{{formData.endTime?formData.endTime.substring(0,10):""}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="民族" v-bind="validateInfos.national" id="OrgApplyInfoForm-national" name="national">
{{formData.national}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="住址" v-bind="validateInfos.idCardAddress" id="OrgApplyInfoForm-idCardAddress"
name="idCardAddress">
{{formData.idCardAddress}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="签发机关" v-bind="validateInfos.issuingAuthority" id="OrgApplyInfoForm-issuingAuthority"
name="issuingAuthority">
{{formData.issuingAuthority}}
<a-form-item label="建筑面积" v-bind="validateInfos.orgBuildingArea" id="OrgApplyInfoForm-orgBuildingArea"
name="orgBuildingArea">
{{formData.orgBuildingArea}}
</a-form-item>
</a-col>
</a-row>
<a-row>
<a-col :span="24">
<SectionDivider :title="'营业执照'" />
@ -136,28 +70,28 @@
</a-row>
<a-row>
<a-col :span="12">
<a-form-item label="企业名称" v-bind="validateInfos.comName" id="OrgApplyInfoForm-comName" name="comName">
{{formData.comName}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="企业注册地址" v-bind="validateInfos.comRegisterAddress"
id="OrgApplyInfoForm-comRegisterAddress" name="comRegisterAddress">
{{formData.comRegisterAddress}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="企业信用代码" v-bind="validateInfos.comCreditCode" id="OrgApplyInfoForm-comCreditCode"
<a-form-item label="信用代码" v-bind="validateInfos.comCreditCode" id="OrgApplyInfoForm-comCreditCode"
name="comCreditCode">
{{formData.comCreditCode}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="企业名称" v-bind="validateInfos.comName" id="OrgApplyInfoForm-comName" name="comName">
{{formData.comName}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="企业法人" v-bind="validateInfos.comLegalPerson" id="OrgApplyInfoForm-comLegalPerson"
name="comLegalPerson">
{{formData.comLegalPerson}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="注册地址" v-bind="validateInfos.comRegisterAddress"
id="OrgApplyInfoForm-comRegisterAddress" name="comRegisterAddress">
{{formData.comRegisterAddress}}
</a-form-item>
</a-col>
<!-- <a-col :span="24">
<SectionDivider :title="'加盟审核'" />
@ -168,6 +102,107 @@
</a-form-item>
</a-col> -->
</a-row>
<a-row>
<a-col :span="24">
<SectionDivider :title="'申请人身份证'" />
</a-col>
</a-row>
<a-row>
<a-col :span="12">
<a-row>
<a-col :span="24">
<a-form-item label="身份证正面" v-bind="validateInfos.cardZmPath" id="OrgApplyInfoForm-cardZmPath"
name="cardZmPath">
<JImageUpload :fileMax="1" v-model:value="formData.cardZmPath" :disabled="true"></JImageUpload>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="姓名" v-bind="validateInfos.name" id="OrgApplyInfoForm-name" name="name">
{{formData.name}}
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="性别" v-bind="validateInfos.sex" id="OrgApplyInfoForm-sex" name="sex">
{{formData.sex}}
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="出生日期" v-bind="validateInfos.birthDate" id="OrgApplyInfoForm-birthDate"
name="birthDate">
{{formData.birthDate?formData.birthDate.substring(0,10):""}}
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="身份证号" v-bind="validateInfos.idCard" id="OrgApplyInfoForm-idCard" name="idCard">
{{formData.idCard}}
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="住址" v-bind="validateInfos.idCardAddress" id="OrgApplyInfoForm-idCardAddress"
name="idCardAddress">
{{formData.idCardAddress}}
</a-form-item>
</a-col>
</a-row>
</a-col>
<a-col :span="12">
<a-row>
<a-col :span="24">
<a-form-item label="身份证反面" v-bind="validateInfos.cardFmPath" id="OrgApplyInfoForm-cardFmPath"
name="cardFmPath">
<JImageUpload :fileMax="1" v-model:value="formData.cardFmPath" :disabled="true"></JImageUpload>
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="有效开始日期" v-bind="validateInfos.startTime" id="OrgApplyInfoForm-startTime"
name="startTime">
{{formData.startTime?formData.startTime.substring(0,10):""}}
</a-form-item>
</a-col>
<a-col :span="24">
<a-form-item label="有效结束日期" v-bind="validateInfos.endTime" id="OrgApplyInfoForm-endTime" name="endTime">
{{formData.endTime?formData.endTime.substring(0,10):""}}
</a-form-item>
</a-col>
<!-- <a-col :span="24">
<a-form-item label="民族" v-bind="validateInfos.national" id="OrgApplyInfoForm-national" name="national">
{{formData.national}}
</a-form-item>
</a-col> -->
<a-col :span="24">
<a-form-item label="签发机关" v-bind="validateInfos.issuingAuthority" id="OrgApplyInfoForm-issuingAuthority"
name="issuingAuthority">
{{formData.issuingAuthority}}
</a-form-item>
</a-col>
</a-row>
</a-col>
</a-row>
<a-row>
<a-col :span="24">
<SectionDivider :title="'审核信息'" />
</a-col>
<a-col :span="12">
<a-form-item label="审核人">
{{formData.auditBy}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="审核时间">
{{formData.auditTime}}
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="审核状态">
{{formData.auditStatus}}
</a-form-item>
</a-col>
</a-row>
<a-row>
<a-col :span="24">
<SectionDivider :title="'加盟合同'" />
@ -176,7 +211,8 @@
<a-row>
<a-col :span="12">
<a-form-item label="加盟合同" v-bind="validateInfos.contract" id="OrgApplyInfoForm-contract">
<JUpload v-model:value="formData.contract" :maxCount="1"></JUpload>
<!-- <JUpload v-model:value="formData.contract" :maxCount="1"></JUpload> -->
<JUpload v-model:value="formData.contract" :maxCount="1" :buttonVisible="false" disabled="true" fileType="pdf"></JUpload>
</a-form-item>
</a-col>
<!-- <a-col :span="12">
@ -270,8 +306,9 @@ const formData = reactive<Record<string, any>>({
franchiseTime: null,
contract: null,
});
const cityViewValue = ref('')
const { createMessage } = useMessage();
const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } });
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);
//
@ -311,6 +348,7 @@ function edit(record) {
tmpData[key] = record[key]
}
})
//
Object.assign(formData, tmpData);
});
@ -319,6 +357,10 @@ function edit(record) {
function open(orgCode) {
getOrgInfo({ orgCode }).then(res => {
Object.assign(formData, res);
cityViewValue.value = res.orgProvince
+ (!!res.orgCity ? res.orgCity : '')
+ (!!res.orgDistrict ? res.orgDistrict : '')
})
}
@ -383,4 +425,7 @@ defineExpose({
.antd-modal-form {
padding: 14px;
}
.ant-form-item-label{
color: white;
}
</style>

View File

@ -11,6 +11,12 @@ export const columns: BasicColumn[] = [
dataIndex: 'orgName',
width:260
},
{
title: '机构编码',
align: "center",
dataIndex: 'orgCode',
width:120
},
{
title: '平台类型',
align: "center",
@ -21,12 +27,12 @@ export const columns: BasicColumn[] = [
align: "center",
dataIndex: 'workType_dictText'
},
{
title: '标题',
align: "center",
dataIndex: 'title',
width:260
},
// {
// title: '标题',
// align: "center",
// dataIndex: 'title',
// width:260
// },
{
title: '工单状态',
align: "center",
@ -48,7 +54,7 @@ export const columns: BasicColumn[] = [
dataIndex: 'handleBy'
},
{
title: '回复时间',
title: '反馈时间',
align: "center",
dataIndex: 'replyTime'
},
@ -65,6 +71,6 @@ export const superQuerySchema = {
status: {title: '状态 0待接收 1处理中 3已解决 4工单异常 5外部原因',order: 6,view: 'text', type: 'string',},
createBy: {title: '创建人',order: 7,view: 'text', type: 'string',},
createTime: {title: '创建时间',order: 8,view: 'datetime', type: 'string',},
replyTime: {title: '回复时间',order: 9,view: 'datetime', type: 'string',},
replyTime: {title: '反馈时间',order: 9,view: 'datetime', type: 'string',},
handleBy: {title: '处理人',order: 10,view: 'text', type: 'string',},
};

View File

@ -248,3 +248,4 @@ function searchReset() {
}
}
</style>

View File

@ -30,7 +30,7 @@
{{formData.workType_dictText}}
</a-form-item>
</a-col>
<a-col :span="12">
<!-- <a-col :span="12">
<a-form-item label="标题" v-bind="validateInfos.title" id="WorkOrderForm-title" name="title">
{{formData.title}}
</a-form-item>
@ -39,7 +39,7 @@
<a-form-item label="描述" v-bind="validateInfos.content" id="WorkOrderForm-content" name="content">
{{formData.content}}
</a-form-item>
</a-col>
</a-col> -->
<a-col :span="12">
<a-form-item label="提交人" v-bind="validateInfos.createBy" id="WorkOrderForm-createBy" name="createBy">
{{formData.createBy}}
@ -57,7 +57,7 @@
<a-row>
<a-col :span="12">
<a-form-item label="反馈内容" v-bind="validateInfos.replyContent" id="WorkOrderForm-replyContent" name="replyContent">
<a-textarea v-model:value="formData.replyContent" rows="4" placeholder="请输入反馈内容" />
<a-textarea v-model:value="formData.replyContent" rows="4" placeholder="请输入反馈内容" :maxlength="100" showCount/>
</a-form-item>
</a-col>
<a-col :span="12">

View File

@ -7,7 +7,7 @@
<div style="margin: 20px;">
<SectionDivider :title="'工单信息'" />
</div>
<a-row style="border: 1px solid #e8e8e8;padding: 20px;margin:40px;border-radius: 4px;">
<a-row style="padding: 20px;margin:40px;">
<a-col :span="12">
<a-form-item label="机构名称" v-bind="validateInfos.orgName" id="WorkOrderForm-orgName" name="orgName">
{{formData.orgName}}
@ -30,7 +30,7 @@
{{formData.workType_dictText}}
</a-form-item>
</a-col>
<a-col :span="12">
<!-- <a-col :span="12">
<a-form-item label="标题" v-bind="validateInfos.title" id="WorkOrderForm-title" name="title">
{{formData.title}}
</a-form-item>
@ -39,7 +39,7 @@
<a-form-item label="描述" v-bind="validateInfos.content" id="WorkOrderForm-content" name="content">
{{formData.content}}
</a-form-item>
</a-col>
</a-col> -->
<a-col :span="12">
<a-form-item label="提交人" v-bind="validateInfos.createBy" id="WorkOrderForm-createBy" name="createBy">
{{formData.createBy}}
@ -57,7 +57,7 @@
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="回复时间" v-bind="validateInfos.replyTime" id="WorkOrderForm-replyTime" name="replyTime">
<a-form-item label="反馈时间" v-bind="validateInfos.replyTime" id="WorkOrderForm-replyTime" name="replyTime">
{{formData.replyTime?formData.replyTime:'暂未处理'}}
</a-form-item>
</a-col>
@ -67,12 +67,12 @@
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="回复附件" v-bind="validateInfos.replyFile" id="WorkOrderForm-replyFile" name="replyFile">
<a-form-item label="反馈附件" v-bind="validateInfos.replyFile" id="WorkOrderForm-replyFile" name="replyFile">
<JUpload v-model:value="formData.replyFile" :maxCount="1"></JUpload>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="回复内容" v-bind="validateInfos.replyContent" id="WorkOrderForm-replyContent" name="replyContent">
<a-form-item label="反馈内容" v-bind="validateInfos.replyContent" id="WorkOrderForm-replyContent" name="replyContent">
{{formData.replyContent}}
</a-form-item>
</a-col>

View File

@ -1,21 +1,45 @@
<template>
<j-modal :title="title" :width="'70vw'" :visible="visible" @ok="handleOk"
<!-- <j-modal :title="title" :width="'70vw'" :visible="visible" @ok="handleOk"
:okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
</j-modal> -->
<a-drawer :title="title" :width="'70vw'" v-model:visible="visible" :closable="true"
:footer-style="{ textAlign: 'right' }" @close="handleCancel">
<WorkOrderForm ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false">
</WorkOrderForm>
</j-modal>
<j-modal title="机构详情" :width="'70vw'" :visible="orgDetailVisible" @cancel="handleOrgDetailCancel">
<template #footer>
<a-button type="primary" style="margin-right: 8px" @click="handleCancel">关闭</a-button>
<a-button type="primary" @click="handleOk" v-if="!disableSubmit">确认</a-button>
</template>
</a-drawer>
<!-- <j-modal title="机构详情" :width="'70vw'" :visible="orgDetailVisible" @cancel="handleOrgDetailCancel">
<template #footer>
<a-button @click="handleOrgDetailCancel">关闭</a-button>
</template>
</j-modal> -->
<a-drawer :title="`机构详情`" :width="'70vw'" v-model:visible="orgDetailVisible" :closable="true"
:footer-style="{ textAlign: 'right' }" @close="handleOrgDetailCancel">
<OrgInfoForm ref="orgDetailRef" :formDisabled="true" :formBpm="false" />
</j-modal>
<j-modal title="反馈" :width="'70vw'" :visible="orgFankuiVisible" @ok="handleFankuiOk" @cancel="handleOrgFankuiCancel" cancelText="关闭">
<!-- <template #footer>
<a-button @click="handleOrgFankuiCancel">关闭</a-button>
</template> -->
<template #footer>
<a-button type="primary" style="margin-right: 8px" @click="handleOrgDetailCancel">关闭</a-button>
</template>
</a-drawer>
<a-drawer :title="`反馈`" :width="'70vw'" v-model:visible="orgFankuiVisible" :closable="true"
:footer-style="{ textAlign: 'right' }" @close="handleOrgFankuiCancel">
<WorkOrderFankui ref="orgFankuiRef" :formDisabled="false" @ok="handleOrgFankuiFankuiCancel" :formBpm="false" />
</j-modal>
<template #footer>
<a-button type="primary" style="margin-right: 8px" @click="handleOrgFankuiCancel">关闭</a-button>
<a-button type="primary" @click="handleOk" v-if="!handleFankuiOk">确认</a-button>
</template>
</a-drawer>
</template>
<script lang="ts" setup>

View File

@ -0,0 +1,131 @@
<template>
<div class="p-2">
<!--引用表格-->
<BasicTable @register="registerTable">
<!--插槽:table标题-->
<template #tableTitle>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)"/>
</template>
</BasicTable>
</div>
</template>
<script lang="ts" name="tplink-camera-asyncMain" setup>
import { ref, reactive } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { columns, formSchema } from './configlog.data';
import { list } from './configlog.api';
import JSelectDept from '/@/components/Form/src/jeecg/components/JSelectDept.vue';
const props = defineProps({
serverType: '',
});
const queryParam = reactive<any>({});
//table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '配置同步日志表',
api: list,
columns: columns,
formConfig: {
schemas: formSchema
},
canResize: false,
useSearchForm: true,
showTableSetting: false,
showActionColumn: false,
beforeFetch: async (params) => {
queryParam.serverType = props.serverType
return Object.assign(params, queryParam);
},
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = tableContext;
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 查询
*/
function searchQuery() {
reload();
}
/**
* 操作栏
*/
function getTableAction(record) {
return [];
}
defineExpose({
searchQuery
});
</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%;
}
}
:deep(.ant-table-title) {
display: none !important;
}
:deep(.darkened-table) {
.ant-table-thead>tr>th {
background-color: #dadadaee;
}
.ant-table-tbody>tr>td {
background-color: #f3f3f3f5;
}
}
:deep(.z-table-class) {
.ant-table-thead>tr>th {
background-color: #e6f0fd;
}
.ant-table-tbody>tr>td {
background-color: #FBFBFB;
}
}
</style>

View File

@ -0,0 +1,12 @@
import { defHttp } from '/@/utils/http/axios';
enum Api {
list = '/iot/syncConfigLog/list',
}
/**
*
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });

View File

@ -0,0 +1,77 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
//列表数据
export const columns: BasicColumn[] = [
{
title: '机构编码',
align: "center",
dataIndex: 'orgCode',
width: 80
},
{
title: '机构名称',
align: "center",
dataIndex: 'orgName',
width: 220
},
{
title: '操作',
align: "center",
dataIndex: 'syncType',
width: 80
},
{
title: '同步状态',
align: "center",
dataIndex: 'status',
width: 80
},
{
title: '服务类型',
align: "center",
dataIndex: 'serverType',
width: 80
},
{
title: '创建时间',
align: "center",
dataIndex: 'createTime',
width: 160
},
{
title: '更新时间',
align: "center",
dataIndex: 'updateTime',
width: 160
},
{
title: '备注',
align: "center",
dataIndex: 'content'
},
];
export const formSchema: FormSchema[] = [
{
label: '机构编码',
field: 'orgCode',
component: 'Input',
componentProps: {
placeholder: '请输入机构编码',
},
},
{
label: '同步状态',
field: 'status',
component: 'JDictSelectTag',
componentProps: {
placeholder: '请选择状态',
options: [
{ label: '同步成功', value: '同步成功' },
{ label: '同步中', value: '同步中' },
{ label: '同步失败', value: '同步失败' },
],
},
},
];

View File

@ -0,0 +1,363 @@
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 baseSxtColumns: BasicColumn[] = [
{
title: '设备序号',
align: "center",
dataIndex: 'deviceIndex',
width: 120,
},
{
title: '设备名称',
align: "center",
dataIndex: 'deviceName'
},
{
title: '设备状态',
align: "center",
dataIndex: 'deviceStatus_dictText',
width: 120,
},
{
title: '设备型号',
align: "center",
dataIndex: 'deviceModel',
width: 220,
},
{
title: 'NUID',
align: "center",
dataIndex: 'nuId',
width: 120,
},
{
title: '操作',
align: "center",
dataIndex: 'action',
width: 120,
},
];
export const checkSxtColumns: BasicColumn[] = [
{
title: '设备序号',
align: "center",
dataIndex: 'deviceIndex',
width: 120,
},
{
title: '设备名称',
align: "center",
dataIndex: 'deviceName'
},
{
title: '设备状态',
align: "center",
dataIndex: 'deviceStatus_dictText',
width: 120,
},
{
title: '设备型号',
align: "center",
dataIndex: 'deviceModel',
width: 220,
},
{
title: '操作',
align: "center",
dataIndex: 'action',
width: 120,
},
];
//列表数据
export const baseDbColumns: BasicColumn[] = [
{
title: '设备号',
align: "center",
dataIndex: 'address',
},
{
title: '设备状态',
align: "center",
dataIndex: 'relayState',
customRender:({record})=>{
return record.relayState?(record.relayState=='1'?'合闸':'拉闸'):'';
},
},
{
title: '在线状态',
align: "center",
dataIndex: 'online',
customRender:({record})=>{
return record.online?(record.online=='true'?'在线':'离线'):'';
},
},
{
title: '信号强度',
align: "center",
dataIndex: 'csq',
customRender:({record})=>{
if(record.csq){
if(record.csq < 10){
return '低';
}else if(record.csq > 20){
return '高';
}else{
return '中';
}
}else{
return '';
}
}
},
{
title: 'NUID',
align: "center",
dataIndex: 'nuId',
},
{
title: '操作',
align: "center",
dataIndex: 'action',
width: 120,
},
];
export const checkDbColumns: BasicColumn[] = [
{
title: '设备号',
align: "center",
dataIndex: 'cid',
},
{
title: '设备状态',
align: "center",
dataIndex: 'relayState',
customRender:({record})=>{
return record.relayState?(record.relayState=='1'?'合闸':'拉闸'):'';
},
},
{
title: '在线状态',
align: "center",
dataIndex: 'online',
customRender:({record})=>{
return record.online?(record.online=='true'?'在线':'离线'):'';
},
},
{
title: '信号强度',
align: "center",
dataIndex: 'csq',
customRender:({record})=>{
if(record.csq){
if(record.csq < 10){
return '低';
}else if(record.csq > 20){
return '高';
}else{
return '中';
}
}else{
return '';
}
}
},
{
title: '操作',
align: "center",
dataIndex: 'action',
width: 120,
},
];
//列表数据
export const baseSbColumns: BasicColumn[] = [
{
title: '设备号',
align: "center",
dataIndex: 'address',
},
{
title: '设备状态',
align: "center",
dataIndex: 'relayState',
customRender:({record})=>{
return record.relayState?(record.relayState=='1'?'开阀':'关阀'):'';
},
},
{
title: '在线状态',
align: "center",
dataIndex: 'online',
customRender:({record})=>{
return record.online?(record.online=='true'?'在线':'离线'):'';
},
},
{
title: '信号强度',
align: "center",
dataIndex: 'csq',
customRender:({record})=>{
if(record.csq){
if(record.csq < 10){
return '低';
}else if(record.csq > 20){
return '高';
}else{
return '中';
}
}else{
return '';
}
}
},
{
title: 'NUID',
align: "center",
dataIndex: 'nuId',
},
{
title: '操作',
align: "center",
dataIndex: 'action',
width: 120,
},
];
export const checkSbColumns: BasicColumn[] = [
{
title: '设备号',
align: "center",
dataIndex: 'cid',
},
{
title: '设备状态',
align: "center",
dataIndex: 'relayState',
customRender:({record})=>{
return record.relayState?(record.relayState=='1'?'开阀':'关阀'):'';
},
},
{
title: '在线状态',
align: "center",
dataIndex: 'online',
customRender:({record})=>{
return record.online?(record.online=='true'?'在线':'离线'):'';
},
},
{
title: '信号强度',
align: "center",
dataIndex: 'csq',
customRender:({record})=>{
if(record.csq){
if(record.csq < 10){
return '低';
}else if(record.csq > 20){
return '高';
}else{
return '中';
}
}else{
return '';
}
}
},
{
title: '操作',
align: "center",
dataIndex: 'action',
width: 120,
},
];
//列表数据
export const baseWsdColumns: BasicColumn[] = [
{
title: '设备号',
align: "center",
dataIndex: 'sn'
},
{
title: '设备名称',
align: "center",
dataIndex: 'deviceName'
},
{
title: '在线状态',
align: "center",
dataIndex: 'status',
customRender:({record})=>{
return record.status?(record.status=='0'?'在线':'离线'):'';
},
},
{
title: '启用状态',
align: "center",
dataIndex: 'delFlag',
customRender:({record})=>{
return record.delFlag?(record.delFlag=='0'?'启用':'停用'):'';
},
},
{
title: 'NUID',
align: "center",
dataIndex: 'nuId'
},
{
title: '操作',
align: "center",
dataIndex: 'action',
width: 120,
},
];
//列表数据
export const checkWsdColumns: BasicColumn[] = [
{
title: '设备号',
align: "center",
dataIndex: 'sn'
},
{
title: '设备名称',
align: "center",
dataIndex: 'deviceName'
},
{
title: '在线状态',
align: "center",
dataIndex: 'status',
customRender:({record})=>{
return record.status?(record.status=='0'?'在线':'离线'):'';
},
},
{
title: '启用状态',
align: "center",
dataIndex: 'delFlag',
customRender:({record})=>{
return record.delFlag?(record.delFlag=='0'?'启用':'停用'):'';
},
},
{
title: '操作',
align: "center",
dataIndex: 'action',
width: 120,
},
];

View File

@ -0,0 +1,224 @@
<template>
<div class="p-2">
<div v-show="activeKey==='1'">
<!--查询区域-->
<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" style="margin-top:10px;">
<a-col :lg="6">
<a-form-item name="syncType">
<template #label><span title="机构名称">机构名称</span></template>
<j-dict-select-tag type='list' v-model:value="queryParam.id" dictCode="sys_depart,depart_name,id"
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-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>
</span>
</a-col>
</a-row>
</a-form>
</div>
<a-row>
<a-col v-for="(item,index) in orgList" style="padding: 5px" :key="index" :xs="24" :sm="24" :md="12" :lg="12" :xl="8" :xxl="6">
<a-card :title="item.departName"
:class="['card-3d', { 'card-selected': isSelected===item }]"
@mouseenter="item.key"
@mouseleave="item.key"
@click="isSelected = item">
<p>机构编码{{item.orgCode}}</p>
<p>创建时间{{item.createTime}}</p>
<p style="text-align: right"><a-button @click="handleCheckOrg(item)">选择</a-button></p>
</a-card>
</a-col>
</a-row>
</div>
<div v-show="activeKey==='2'">
<a-row style="padding:10px;">
<a-col :span="12"><span style="font-size: 18px;">{{orgInfo.departName}} - 物联设备配置</span></a-col>
<a-col :span="12" style="text-align: right"><a-button @click="activeKey = '1'">返回上一页</a-button></a-col>
<a-col v-for="(item,index) in baseList" style="padding: 5px" :key="index" :xs="24" :sm="24" :md="12" :lg="12" :xl="8" :xxl="6">
<a-card :title="`NUID`+item.nuId"
:class="['card-3d', { 'card-selected': isSelected===item }]"
@mouseenter="item.key"
@mouseleave="item.key"
@click="isSelected = item">
<p>单元名称{{item.nuName}}</p>
<p>创建时间{{item.createTime}}</p>
<p>单元类型{{item.areaFlagText}}</p>
<div style="text-align: center;">
<a-badge :count="item.sxtNum">
<a-button type="dashed" size="small" @click="handleSxt(item)" style="margin-left: 10px;">摄像头</a-button>
</a-badge>
<a-badge :count="item.dbNum">
<a-button type="dashed" size="small" @click="handleDb(item)" style="margin-left: 10px;">电表</a-button>
</a-badge>
<a-badge :count="item.sbNum" >
<a-button type="dashed" size="small" @click="handleSb(item)" style="margin-left: 10px;">水表</a-button>
</a-badge>
<a-badge :count="item.wsdjNum" >
<a-button type="dashed" size="small" @click="handleWsd(item)" style="margin-left: 10px;">温湿度</a-button>
</a-badge>
</div>
</a-card>
</a-col>
</a-row>
</div>
<SxtModal ref="sxtModal" @success="handleWlsbSuccess"></SxtModal>
<DbModal ref="dbModal" @success="handleWlsbSuccess"></DbModal>
<SbModal ref="sbModal" @success="handleWlsbSuccess"></SbModal>
<WsdModal ref="wsdModal" @success="handleWlsbSuccess"></WsdModal>
</div>
</template>
<script lang="ts" name="ElectricitySyncLog-ElectricitySyncLog" setup>
import { ref, reactive,onMounted } from 'vue';
import { defHttp } from '/@/utils/http/axios';
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
import SxtModal from '/@/views/iot/baseIot/compoents/SxtModal.vue';
import DbModal from '/@/views/iot/baseIot/compoents/DbModal.vue';
import SbModal from '/@/views/iot/baseIot/compoents/SbModal.vue';
import WsdModal from '/@/views/iot/baseIot/compoents/WsdModal.vue';
const formRef = ref();
const sxtModal = ref();
const dbModal = ref();
const sbModal = ref();
const wsdModal = ref();
const queryParam = reactive<any>({});
const activeKey= ref('1');
const orgInfo= ref<any>({});
const orgList= ref<any>([]);
const baseList= ref<any>([]);
const isHover = ref(false);
const isSelected = ref(false);
const labelCol = reactive({
xs:24, sm:8
});
const wrapperCol = reactive({
xs: 24, sm: 15,
});
//
function searchQuery() {
defHttp.get({ url: '/sys/sysDepart/listAll', params: queryParam }).then((res) => {
orgList.value = res;
});
}
//
function searchReset() {
queryParam.id = '';
searchQuery();
}
//
function handleSuccess(){
searchQuery();
}
//
function handleCheckOrg(item){
activeKey.value = "2";
orgInfo.value = item;
getBaseList(item);
}
//
function getBaseList(item){
defHttp.get({ url: '/admin/nuBaseInfo/nuBaseInfo/getBaseWlsbList', params: {orgCode:item.orgCode} }).then((res) => {
baseList.value = res;
});
}
//
function handleSxt(item){
console.log("🚀 ~ handleSxt ~ item:", item)
item.orgInfo = orgInfo.value;
sxtModal.value.init(item);
}
//
function handleDb(item){
console.log("🚀 ~ handleDb ~ item:", item)
item.orgInfo = orgInfo.value;
dbModal.value.init(item);
}
//
function handleSb(item){
console.log("🚀 ~ handleSb ~ item:", item)
item.orgInfo = orgInfo.value;
sbModal.value.init(item);
}
//湿
function handleWsd(item){
console.log("🚀 ~ handleWsd ~ item:", item)
item.orgInfo = orgInfo.value;
wsdModal.value.init(item);
}
//
function handleWlsbSuccess(){
console.log("🚀 ~ handleWlsbSuccess ~ handleWlsbSuccess:", orgInfo.value)
getBaseList(orgInfo.value)
}
//
onMounted(() => {
activeKey.value = "1";
searchQuery();
});
</script>
<style lang="less" scoped>
/* 基础卡片样式 */
.card-3d {
border-radius: 8px;
border: 1px solid #f0f0f0; /* 边框增强立体感 */
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
background: white;
position: relative;
}
/* 鼠标悬停:阴影加深 + 轻微上浮 */
.card-3d:hover {
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.15);
transform: translate(-2px,-2px);
}
/* 选中状态:蓝色边框 + 更明显的阴影 */
.card-3d.card-selected {
box-shadow: 0 8px 24px rgba(24, 144, 255, 0.3);
border: 1px solid #1890ff;
}
/* 选中 + 悬停:阴影更强 */
.card-3d.card-selected.card-hover {
box-shadow: 0 10px 28px rgba(24, 144, 255, 0.4);
transform: translate(-3px,-3px);
}
.jeecg-basic-table-form-container {
padding: 14px 0 0 14px;
background: white;
border-radius: 8px;
.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%;
}
}
</style>

View File

@ -0,0 +1,142 @@
<template>
<div class="p-2">
<div style="margin-bottom: 30px;">
<SectionDivider :title="'基础信息'" />
<span class="jcxxClass">NUID{{baseIotInfo.nuId}}</span>
<span class="jcxxClass">单元名称{{baseIotInfo.nuName}}</span>
<span class="jcxxClass">单元类型{{baseIotInfo.areaFlagText}}</span>
</div>
<SectionDivider :title="'电表列表'" />
<div style="padding-left: 40px;margin-bottom: 10px;">
<span style="font-size:16px;">是否分配</span>
<a-radio-group v-model:value="queryParam.checkType" @change="handleTableChange({current:1})">
<a-radio-button value="">全部</a-radio-button>
<a-radio-button value="1">已分配</a-radio-button>
<a-radio-button value="0">未分配</a-radio-button>
</a-radio-group>
</div>
<a-table :columns="baseDbColumns" :data-source="dataList.records" :pagination="pageParams" @change="handleTableChange" >
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'action'">
<span>
<a @click="handleSelect(record)">选择</a>
</span>
</template>
</template>
</a-table>
<SectionDivider :title="'已选择列表'" />
<a-table :columns="checkDbColumns" :data-source="checkDataList.records" :pagination="false">
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'action'">
<span>
<a @click="handleUnSelect(record)">移除</a>
</span>
</template>
</template>
</a-table>
</div>
</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 { baseDbColumns,checkDbColumns } from '../BaseIot.data';
import { Pagination } from 'ant-design-vue';
const formRef = ref();
const queryParam = reactive<any>({checkType:''});
const emit = defineEmits(['register', 'ok']);
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 dataList= ref<any>([]);
const checkDataList= ref<any>([]);
const baseIotInfo= ref<any>({});
const pageParams = ref({ pageNo: 1, pageSize: 10, total: 0, showTotal: (total) => `${total} 条数据` })
/**
* 初始化
*/
function init(record) {
console.log("🚀 ~ init ~ record:", record)
baseIotInfo.value = record;
queryParam.pageNo = 1;
queryParam.checkType = '0';
getDataList();
getCheckDataList();
}
/**
* 分页触发方法
*/
function handleTableChange(record){
queryParam.pageNo = record.current;
getDataList();
}
/**
* 获取数据列表
*/
function getDataList() {
queryParam.pageSize = pageParams.value.pageSize;
defHttp.get({ url: '/iot/tq/electricityMeter/list',params:queryParam }).then((res) => {
dataList.value = res;
pageParams.value.total = res.total;
});
}
/**
* 获取已选的数据列表
*/
function getCheckDataList(){
const params = {nuId:baseIotInfo.value.nuId}
defHttp.get({ url: '/iot/tq/electricityMeter/list',params }).then((res) => {
checkDataList.value = res;
});
}
function handleSelect(record){
if(checkDataList.value.records.some(item => item.id === record.id)){
createMessage.error('已选择该设备')
}else{
checkDataList.value.records.push(record)
}
}
function handleUnSelect(record){
checkDataList.value.records = checkDataList.value.records.filter(item => item.id !== record.id)
}
/**
* 提交数据
*/
function submitForm() {
const list = checkDataList.value.records;
const orgInfo = baseIotInfo.value.orgInfo;
const params = {nuId:baseIotInfo.value.nuId,
nuName:baseIotInfo.value.nuName,
dataSourceCode:baseIotInfo.value.sysOrgCode,
departId: orgInfo.id,
departName: orgInfo.departName,
list}
defHttp.post({url:"/iot/tq/electricityMeter/syncElectricityList",params}).then((res)=>{
console.log("🚀 ~ submitForm ~ res:", res)
emit("ok")
})
}
defineExpose({
init,
submitForm,
});
</script>
<style lang="less" scoped>
.antd-modal-form {
padding: 14px;
}
.jcxxClass{
margin-left: 35px;
}
</style>

View File

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

View File

@ -0,0 +1,142 @@
<template>
<div class="p-2">
<div style="margin-bottom: 30px;">
<SectionDivider :title="'基础信息'" />
<span class="jcxxClass">NUID{{baseIotInfo.nuId}}</span>
<span class="jcxxClass">单元名称{{baseIotInfo.nuName}}</span>
<span class="jcxxClass">单元类型{{baseIotInfo.areaFlagText}}</span>
</div>
<SectionDivider :title="'水表列表'" />
<div style="padding-left: 40px;margin-bottom: 10px;">
<span style="font-size:16px;">是否分配</span>
<a-radio-group v-model:value="queryParam.checkType" @change="handleTableChange({current:1})">
<a-radio-button value="">全部</a-radio-button>
<a-radio-button value="1">已分配</a-radio-button>
<a-radio-button value="0">未分配</a-radio-button>
</a-radio-group>
</div>
<a-table :columns="baseSbColumns" :data-source="dataList.records" :pagination="pageParams" @change="handleTableChange" >
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'action'">
<span>
<a @click="handleSelect(record)">选择</a>
</span>
</template>
</template>
</a-table>
<SectionDivider :title="'已选择列表'" />
<a-table :columns="checkSbColumns" :data-source="checkDataList.records" :pagination="false">
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'action'">
<span>
<a @click="handleUnSelect(record)">移除</a>
</span>
</template>
</template>
</a-table>
</div>
</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 { baseSbColumns,checkSbColumns } from '../BaseIot.data';
import { Pagination } from 'ant-design-vue';
const formRef = ref();
const queryParam = reactive<any>({checkType:''});
const emit = defineEmits(['register', 'ok']);
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 dataList= ref<any>([]);
const checkDataList= ref<any>([]);
const baseIotInfo= ref<any>({});
const pageParams = ref({ pageNo: 1, pageSize: 10, total: 0, showTotal: (total) => `${total} 条数据` })
/**
* 初始化
*/
function init(record) {
console.log("🚀 ~ init ~ record:", record)
baseIotInfo.value = record;
queryParam.pageNo = 1;
queryParam.checkType = '0';
getDataList();
getCheckDataList();
}
/**
* 分页触发方法
*/
function handleTableChange(record){
queryParam.pageNo = record.current;
getDataList();
}
/**
* 获取数据列表
*/
function getDataList() {
queryParam.pageSize = pageParams.value.pageSize;
defHttp.get({ url: '/iot/tq/waterMeter/list',params:queryParam }).then((res) => {
dataList.value = res;
pageParams.value.total = res.total;
});
}
/**
* 获取已选的数据列表
*/
function getCheckDataList(){
const params = {nuId:baseIotInfo.value.nuId}
defHttp.get({ url: '/iot/tq/waterMeter/list',params }).then((res) => {
checkDataList.value = res;
});
}
function handleSelect(record){
if(checkDataList.value.records.some(item => item.id === record.id)){
createMessage.error('已选择该设备')
}else{
checkDataList.value.records.push(record)
}
}
function handleUnSelect(record){
checkDataList.value.records = checkDataList.value.records.filter(item => item.id !== record.id)
}
/**
* 提交数据
*/
function submitForm() {
const list = checkDataList.value.records;
const orgInfo = baseIotInfo.value.orgInfo;
const params = {nuId:baseIotInfo.value.nuId,
nuName:baseIotInfo.value.nuName,
dataSourceCode:baseIotInfo.value.sysOrgCode,
departId: orgInfo.id,
departName: orgInfo.departName,
list}
defHttp.post({url:"/iot/tq/waterMeter/syncWaterList",params}).then((res)=>{
console.log("🚀 ~ submitForm ~ res:", res)
emit("ok")
})
}
defineExpose({
init,
submitForm,
});
</script>
<style lang="less" scoped>
.antd-modal-form {
padding: 14px;
}
.jcxxClass{
margin-left: 35px;
}
</style>

View File

@ -0,0 +1,71 @@
<template>
<a-drawer :title="title" :width="width" v-model:visible="visible" :closable="true"
:footer-style="{ textAlign: 'right' }" @close="handleCancel">
<SbForm ref="registerForm" @ok="submitCallback"></SbForm>
<template #footer>
<a-button type="primary" style="margin-right: 8px" @click="handleCancel">关闭</a-button>
<a-button type="primary" @click="handleOk" v-if="!disableSubmit">确认</a-button>
</template>
</a-drawer>
</template>
<script lang="ts" setup>
import { ref, nextTick, defineExpose } from 'vue';
import SbForm from './SbForm.vue'
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
const title = ref<string>('');
const width = ref<string>('80%');
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();
const emit = defineEmits(['register', 'success']);
/**
* 编辑
* @param record
*/
function init(record) {
title.value = '水表';
visible.value = true;
nextTick(() => {
registerForm.value.init(record);
});
}
/**
* 确定按钮点击事件
*/
function handleOk() {
registerForm.value.submitForm();
}
/**
* form保存回调事件
*/
function submitCallback() {
handleCancel();
emit('success');
}
/**
* 取消按钮回调事件
*/
function handleCancel() {
visible.value = false;
}
defineExpose({
init,
disableSubmit,
});
</script>
<style lang="less">
/**隐藏样式-modal确定按钮 */
.jee-hidden {
display: none !important;
}
</style>
<style lang="less" scoped></style>

View File

@ -0,0 +1,142 @@
<template>
<div class="p-2">
<div style="margin-bottom: 30px;">
<SectionDivider :title="'基础信息'" />
<span class="jcxxClass">NUID{{baseIotInfo.nuId}}</span>
<span class="jcxxClass">单元名称{{baseIotInfo.nuName}}</span>
<span class="jcxxClass">单元类型{{baseIotInfo.areaFlagText}}</span>
</div>
<SectionDivider :title="'摄像头列表'" />
<div style="padding-left: 40px;margin-bottom: 10px;">
<span style="font-size:16px;">是否分配</span>
<a-radio-group v-model:value="queryParam.checkType" @change="handleTableChange({current:1})">
<a-radio-button value="">全部</a-radio-button>
<a-radio-button value="1">已分配</a-radio-button>
<a-radio-button value="0">未分配</a-radio-button>
</a-radio-group>
</div>
<a-table :columns="baseSxtColumns" :data-source="dataList.records" :pagination="pageParams" @change="handleTableChange" >
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'action'">
<span>
<a @click="handleSelect(record)">选择</a>
</span>
</template>
</template>
</a-table>
<SectionDivider :title="'已选择列表'" />
<a-table :columns="checkSxtColumns" :data-source="checkDataList.records" :pagination="false">
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'action'">
<span>
<a @click="handleUnSelect(record)">移除</a>
</span>
</template>
</template>
</a-table>
</div>
</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 { baseSxtColumns,checkSxtColumns } from '../BaseIot.data';
import { Pagination } from 'ant-design-vue';
const formRef = ref();
const queryParam = reactive<any>({checkType:''});
const emit = defineEmits(['register', 'ok']);
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 dataList= ref<any>([]);
const checkDataList= ref<any>([]);
const baseIotInfo= ref<any>({});
const pageParams = ref({ pageNo: 1, pageSize: 10, total: 0, showTotal: (total) => `${total} 条数据` })
/**
* 初始化
*/
function init(record) {
console.log("🚀 ~ init ~ record:", record)
baseIotInfo.value = record;
queryParam.pageNo = 1;
queryParam.checkType = '0';
getDataList();
getCheckDataList();
}
/**
* 分页触发方法
*/
function handleTableChange(record){
queryParam.pageNo = record.current;
getDataList();
}
/**
* 获取数据列表
*/
function getDataList() {
queryParam.pageSize = pageParams.value.pageSize;
defHttp.get({ url: '/iot/tplink/cameraInfo/list',params:queryParam }).then((res) => {
dataList.value = res;
pageParams.value.total = res.total;
});
}
/**
* 获取已选的数据列表
*/
function getCheckDataList(){
const params = {nuId:baseIotInfo.value.nuId}
defHttp.get({ url: '/iot/tplink/cameraInfo/list',params }).then((res) => {
checkDataList.value = res;
});
}
function handleSelect(record){
if(checkDataList.value.records.some(item => item.id === record.id)){
createMessage.error('已选择该设备')
}else{
checkDataList.value.records.push(record)
}
}
function handleUnSelect(record){
checkDataList.value.records = checkDataList.value.records.filter(item => item.id !== record.id)
}
/**
* 提交数据
*/
function submitForm() {
const list = checkDataList.value.records;
const orgInfo = baseIotInfo.value.orgInfo;
const params = {nuId:baseIotInfo.value.nuId,
nuName:baseIotInfo.value.nuName,
dataSourceCode:baseIotInfo.value.sysOrgCode,
departId: orgInfo.id,
departName: orgInfo.departName,
list}
defHttp.post({url:"/iot/tplink/cameraInfo/syncCameraList",params}).then((res)=>{
console.log("🚀 ~ submitForm ~ res:", res)
emit("ok")
})
}
defineExpose({
init,
submitForm,
});
</script>
<style lang="less" scoped>
.antd-modal-form {
padding: 14px;
}
.jcxxClass{
margin-left: 35px;
}
</style>

View File

@ -0,0 +1,71 @@
<template>
<a-drawer :title="title" :width="width" v-model:visible="visible" :closable="true"
:footer-style="{ textAlign: 'right' }" @close="handleCancel">
<SxtForm ref="registerForm" @ok="submitCallback"></SxtForm>
<template #footer>
<a-button type="primary" style="margin-right: 8px" @click="handleCancel">关闭</a-button>
<a-button type="primary" @click="handleOk" v-if="!disableSubmit">确认</a-button>
</template>
</a-drawer>
</template>
<script lang="ts" setup>
import { ref, nextTick, defineExpose } from 'vue';
import SxtForm from './SxtForm.vue'
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
const title = ref<string>('');
const width = ref<string>('80%');
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();
const emit = defineEmits(['register', 'success']);
/**
* 编辑
* @param record
*/
function init(record) {
title.value = '摄像头';
visible.value = true;
nextTick(() => {
registerForm.value.init(record);
});
}
/**
* 确定按钮点击事件
*/
function handleOk() {
registerForm.value.submitForm();
}
/**
* form保存回调事件
*/
function submitCallback() {
handleCancel();
emit('success');
}
/**
* 取消按钮回调事件
*/
function handleCancel() {
visible.value = false;
}
defineExpose({
init,
disableSubmit,
});
</script>
<style lang="less">
/**隐藏样式-modal确定按钮 */
.jee-hidden {
display: none !important;
}
</style>
<style lang="less" scoped></style>

View File

@ -0,0 +1,142 @@
<template>
<div class="p-2">
<div style="margin-bottom: 30px;">
<SectionDivider :title="'基础信息'" />
<span class="jcxxClass">NUID{{baseIotInfo.nuId}}</span>
<span class="jcxxClass">单元名称{{baseIotInfo.nuName}}</span>
<span class="jcxxClass">单元类型{{baseIotInfo.areaFlagText}}</span>
</div>
<SectionDivider :title="'温湿度计列表'" />
<div style="padding-left: 40px;margin-bottom: 10px;">
<span style="font-size:16px;">是否分配</span>
<a-radio-group v-model:value="queryParam.checkType" @change="handleTableChange({current:1})">
<a-radio-button value="">全部</a-radio-button>
<a-radio-button value="1">已分配</a-radio-button>
<a-radio-button value="0">未分配</a-radio-button>
</a-radio-group>
</div>
<a-table :columns="baseWsdColumns" :data-source="dataList.records" :pagination="pageParams" @change="handleTableChange" >
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'action'">
<span>
<a @click="handleSelect(record)">选择</a>
</span>
</template>
</template>
</a-table>
<SectionDivider :title="'已选择列表'" />
<a-table :columns="checkWsdColumns" :data-source="checkDataList.records" :pagination="false">
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'action'">
<span>
<a @click="handleUnSelect(record)">移除</a>
</span>
</template>
</template>
</a-table>
</div>
</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 { baseWsdColumns,checkWsdColumns } from '../BaseIot.data';
import { Pagination } from 'ant-design-vue';
const formRef = ref();
const queryParam = reactive<any>({checkType:''});
const emit = defineEmits(['register', 'ok']);
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 dataList= ref<any>([]);
const checkDataList= ref<any>([]);
const baseIotInfo= ref<any>({});
const pageParams = ref({ pageNo: 1, pageSize: 10, total: 0, showTotal: (total) => `${total} 条数据` })
/**
* 初始化
*/
function init(record) {
console.log("🚀 ~ init ~ record:", record)
baseIotInfo.value = record;
queryParam.pageNo = 1;
queryParam.checkType = '0';
getDataList();
getCheckDataList();
}
/**
* 分页触发方法
*/
function handleTableChange(record){
queryParam.pageNo = record.current;
getDataList();
}
/**
* 获取数据列表
*/
function getDataList() {
queryParam.pageSize = pageParams.value.pageSize;
defHttp.get({ url: '/iot/yiweilian/humidDevice/list',params:queryParam }).then((res) => {
dataList.value = res;
pageParams.value.total = res.total;
});
}
/**
* 获取已选的数据列表
*/
function getCheckDataList(){
const params = {nuId:baseIotInfo.value.nuId}
defHttp.get({ url: '/iot/yiweilian/humidDevice/list',params }).then((res) => {
checkDataList.value = res;
});
}
function handleSelect(record){
if(checkDataList.value.records.some(item => item.id === record.id)){
createMessage.error('已选择该设备')
}else{
checkDataList.value.records.push(record)
}
}
function handleUnSelect(record){
checkDataList.value.records = checkDataList.value.records.filter(item => item.id !== record.id)
}
/**
* 提交数据
*/
function submitForm() {
const list = checkDataList.value.records;
const orgInfo = baseIotInfo.value.orgInfo;
const params = {nuId:baseIotInfo.value.nuId,
nuName:baseIotInfo.value.nuName,
dataSourceCode:baseIotInfo.value.sysOrgCode,
departId: orgInfo.id,
departName: orgInfo.departName,
list}
defHttp.post({url:"/iot/yiweilian/humidDevice/syncHumidList",params}).then((res)=>{
console.log("🚀 ~ submitForm ~ res:", res)
emit("ok")
})
}
defineExpose({
init,
submitForm,
});
</script>
<style lang="less" scoped>
.antd-modal-form {
padding: 14px;
}
.jcxxClass{
margin-left: 35px;
}
</style>

View File

@ -0,0 +1,71 @@
<template>
<a-drawer :title="title" :width="width" v-model:visible="visible" :closable="true"
:footer-style="{ textAlign: 'right' }" @close="handleCancel">
<WsdForm ref="registerForm" @ok="submitCallback"></WsdForm>
<template #footer>
<a-button type="primary" style="margin-right: 8px" @click="handleCancel">关闭</a-button>
<a-button type="primary" @click="handleOk" v-if="!disableSubmit">确认</a-button>
</template>
</a-drawer>
</template>
<script lang="ts" setup>
import { ref, nextTick, defineExpose } from 'vue';
import WsdForm from './WsdForm.vue'
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
const title = ref<string>('');
const width = ref<string>('80%');
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();
const emit = defineEmits(['register', 'success']);
/**
* 编辑
* @param record
*/
function init(record) {
title.value = '温湿度计';
visible.value = true;
nextTick(() => {
registerForm.value.init(record);
});
}
/**
* 确定按钮点击事件
*/
function handleOk() {
registerForm.value.submitForm();
}
/**
* form保存回调事件
*/
function submitCallback() {
handleCancel();
emit('success');
}
/**
* 取消按钮回调事件
*/
function handleCancel() {
visible.value = false;
}
defineExpose({
init,
disableSubmit,
});
</script>
<style lang="less">
/**隐藏样式-modal确定按钮 */
.jee-hidden {
display: none !important;
}
</style>
<style lang="less" scoped></style>

View File

@ -55,15 +55,20 @@ export const columns: BasicColumn[] = [
// dataIndex: 'locationName'
// },
// {
// title: '护理单元',
// title: '区域',
// align: "center",
// dataIndex: 'nuId_dictText',
// },
// {
// title: '护理单元',
// title: '区域',
// align: "center",
// dataIndex: 'nuName'
// },
{
title: 'MAC地址',
align: "center",
dataIndex: 'mac'
},
{
title: 'FTP地址',
align: "center",
@ -171,7 +176,7 @@ export const formSchema: FormSchema[] = [
// dynamicDisabled: true
// },
// {
// label: '护理单元',
// label: '区域',
// field: 'nuId',
// component: 'JSelectNu',
// componentProps: {

View File

@ -45,7 +45,7 @@ import {ref, reactive, createVNode, h, onMounted, watch, unref} from 'vue';
//table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '护理单元-物联管理-摄像头信息',
title: '区域-物联管理-摄像头信息',
api: list,
columns,
canResize: false,

View File

@ -109,6 +109,9 @@
</a-tab-pane>-->
</a-tabs>
</a-tab-pane>
<a-tab-pane key="E" tab="录像设置" forceRender="true">
<PlanAddForm ref="addForm" :initData="formData" :data="cameraData" @success="submitCallback" />
</a-tab-pane>
</a-tabs>
</div>
</template>
@ -128,6 +131,7 @@ import {ref, onMounted, reactive, onUnmounted} from "vue";
import CameraSoundAlarmForm from './CameraSoundAlarmForm.vue';//
import CameraRecordList from './CameraRecordList.vue';//
import CameraUploadForm from './CameraUploadForm.vue';//FTP
import PlanAddForm from '/@/views/iot/tplink/plan/components/PlanAddForm.vue';//
import { useMessage } from "@/hooks/web/useMessage";
const { createMessage } = useMessage();
@ -208,6 +212,7 @@ import {ref, onMounted, reactive, onUnmounted} from "vue";
function edit(record) {
formData.deviceIndex = record.deviceIndex;
formData.deviceName = record.deviceName;
formData.parentId = record.parentId;
formData.multitrans = record.multitrans;
formData.projectId = record.projectId;
@ -215,6 +220,7 @@ function edit(record) {
formData.ip = record.ip;
cameraData.value.deviceIndex = formData.deviceIndex;
cameraData.value.deviceName = formData.deviceName;
cameraData.value.projectId = formData.projectId;
cameraData.value.regionId = formData.regionId;
cameraData.value.multitrans = formData.multitrans;

View File

@ -1,7 +1,14 @@
<template>
<j-modal :title="title" :width="width" :fullscreen="true" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<!-- <j-modal :title="title" :width="width" :fullscreen="true" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
</j-modal> -->
<a-drawer :title="title" :width="width" v-model:visible="visible" :closable="true"
:footer-style="{ textAlign: 'right' }" @close="handleCancel">
<CameraPictureConfig ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></CameraPictureConfig>
</j-modal>
<template #footer>
<a-button type="primary" style="margin-right: 8px" @click="handleCancel">关闭</a-button>
<a-button type="primary" @click="handleOk" v-if="!disableSubmit">确认</a-button>
</template>
</a-drawer>
</template>
<script lang="ts" setup>

View File

@ -4,7 +4,7 @@
<a-col :span="24">
<div id="video-container"></div>
</a-col>
<a-col :span="24">
<a-col :span="20">
<a-col :span="24" style="padding: 5px;">
<span style="margin-left: 5px;" v-show="!izPlaying">
<a-button preIcon="ant-design:play-circle-outlined" @click="play">播放</a-button>
@ -62,18 +62,24 @@
<a-button preIcon="ant-design:alert-outlined" @click="manualAlarm">报警</a-button>
</span>
</a-col>
<a-col :span="24">
<a-col :span="24" v-show="formData.ptz == '1' && formData.smartCode == '1' ">
<a-col :span="24" style="padding: 5px;display: flex;">
<span style="margin-left: 5px;">
变焦
</span>
<span style="margin-left: 5px;">
<!-- <a-button :disabled="formData.zoom<=1" preIcon="ant-design:zoom-out-outlined" @click="zoomInOut('out')" title="缩小"></a-button>-->
<a-button preIcon="ant-design:zoom-out-outlined" @click="zoomInOut('out')" title="缩小"></a-button>
<!-- <a-button preIcon="ant-design:zoom-out-outlined" @click="zoomInOut('out')" title="缩小"></a-button>-->
<a-button preIcon="ant-design:zoom-out-outlined" @mousedown="moveCtrl(9,1,1)" @mouseup="moveCtrl(9,0,1)" title="缩小">缩小</a-button>
</span>
<span style="margin-left: 5px;">
<!-- <a-button :disabled="formData.zoom>=4" preIcon="ant-design:zoom-in-outlined" @click="zoomInOut('in')" title="放大"></a-button>-->
<a-button preIcon="ant-design:zoom-in-outlined" @click="zoomInOut('in')" title="放大"></a-button>
<span style="margin-left: 5px;">
<!-- <a-button preIcon="ant-design:zoom-in-outlined" @click="zoomInOut('in')" title="放大"></a-button>-->
<a-button preIcon="ant-design:zoom-in-outlined" @mousedown="moveCtrl(10,1,1)" @mouseup="moveCtrl(10,0,1)" title="放大">放大</a-button>
</span>
<span style="margin-left: 5px;">
<a-button preIcon="ant-design:zoom-out-outlined" @mousedown="moveCtrl(11,1,1)" @mouseup="moveCtrl(11,0,1)">对近焦</a-button>
</span>
<span style="margin-left: 5px;">
<a-button preIcon="ant-design:zoom-in-outlined" @mousedown="moveCtrl(11,1,1)" @mouseup="moveCtrl(11,0,1)">对远焦</a-button>
</span>
<!-- <span style="margin-left: 5px;width: 60%">
<a-slider v-model:value="formData.zoom" :min="1.0" :max="4.0" :step="0.2" :marks="{1:1.0,2:2.0,3:3.0,4:4.0}" @afterChange="(value) => changeZoom(value)" />
@ -84,27 +90,27 @@
</a-col>
</a-col>
</a-col>
<!-- <a-col :span="4">
<table style="width: 102px">
<a-col :span="4" v-show="formData.ptz == '1'">
<table style="width: 96px;height:96px;margin: 5px 0px 5px 0px;">
<tbody>
<tr>
<td></td>
<td><a-button preIcon="ant-design:caret-up-outlined" @mousedown="moveCtrl(1,1)" @mouseup="moveCtrl(1,0)"></a-button></td>
<td><a-button preIcon="ant-design:caret-up-outlined" @mousedown="moveCtrl(1,1,1)" @mouseup="moveCtrl(1,0,1)"></a-button></td>
<td></td>
</tr>
<tr>
<td><a-button preIcon="ant-design:caret-left-outlined" @mousedown="moveCtrl(3,1)" @mouseup="moveCtrl(3,0)"></a-button></td>
<td><a-button preIcon="ant-design:caret-left-outlined" @mousedown="moveCtrl(3,1,1)" @mouseup="moveCtrl(3,0,1)"></a-button></td>
<td><a-button preIcon="ant-design:compress-outlined"></a-button></td>
<td><a-button preIcon="ant-design:caret-right-outlined" @mousedown="moveCtrl(5,1)" @mouseup="moveCtrl(5,0)"></a-button></td>
<td><a-button preIcon="ant-design:caret-right-outlined" @mousedown="moveCtrl(5,1,1)" @mouseup="moveCtrl(5,0,1)"></a-button></td>
</tr>
<tr>
<td></td>
<td><a-button preIcon="ant-design:caret-down-outlined" @mousedown="moveCtrl(7,1)" @mouseup="moveCtrl(7,0)"></a-button></td>
<td><a-button preIcon="ant-design:caret-down-outlined" @mousedown="moveCtrl(7,1,1)" @mouseup="moveCtrl(7,0,1)"></a-button></td>
<td></td>
</tr>
</tbody>
</table>
</a-col>-->
</a-col>
</a-row>
</a-spin>
</template>
@ -144,7 +150,7 @@
//
deviceIndex: '',//
streamType: 0,// 0 1
streamType: 1,// 0 1
//
url: '',//URL
@ -155,6 +161,8 @@
flip_type: '',// "off"// "left_and_right"// "up_and_down"// "center"//
zoom: 1, //
sliderValue : 1,//
ptz : 0,//
smartCode : 0,//
});
const { createMessage } = useMessage();
const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } });
@ -195,6 +203,8 @@
Object.assign(formData, tmpData);
});
console.log(formData);
createPreview();
getSwitch();
}
@ -496,6 +506,8 @@
td button{
padding: 0;
margin: 0;
width: 30px !important;
height: 30px;
border-color:white;
}

View File

@ -44,7 +44,7 @@ import {ref, reactive, createVNode, h, onMounted, watch, unref} from 'vue';
//table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '护理单元-物联管理-录像信息',
title: '区域-物联管理-录像信息',
api: searchVideo,
columns: recordingColumns,
canResize: false,

View File

@ -155,14 +155,17 @@ function handleSuccess() {
* 画面配置
*/
function handlePicConfig(record) {
console.log("🚀 ~ handlePicConfig ~ record:", record)
var params = {
deviceIndex: record.deviceIndex,
deviceName: record.deviceName,
parentId: record.parentId,
multitrans: record.multitrans,
projectId: record.projectId,
regionId: record.regionId,
ip: record.ip
}
console.log("🚀 ~ handlePicConfig ~ params:", params)
cameraPictureConfigModal.value.disableSubmit = true;
cameraPictureConfigModal.value.edit(params);
}

View File

@ -0,0 +1,91 @@
<template>
<BasicDrawer
v-bind="$attrs"
@register="registerDrawer"
:title="getTitle"
:width="adaptiveWidth"
@ok="handleSubmit"
:showFooter="showFooter"
destroyOnClose
>
<BasicForm @register="registerForm" >
</BasicForm>
</BasicDrawer>
</template>
<script lang="ts" setup>
import {defineComponent, ref, computed, unref, useAttrs, createVNode, h} from 'vue';
import { BasicForm, useForm } from '/@/components/Form/index';
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
import { useDrawerAdaptiveWidth } from '/@/hooks/jeecg/useAdaptiveWidth';
import {Modal} from "ant-design-vue";
import {ExclamationCircleOutlined} from "@ant-design/icons-vue";
import { formSchema } from "../config.data";
import { add,edit } from '../config.api';
// Emits
const emit = defineEmits(['success', 'register']);
const attrs = useAttrs();
const isUpdate = ref(true);
const rowId = ref('');
const departOptions = ref([]);
let isFormDepartUser = false;
//
const [registerForm, { setProps, resetFields, setFieldsValue, validate, updateSchema }] = useForm({
labelWidth: 90,
schemas: formSchema,
showActionButtonGroup: false,
});
const showFooter = ref(true);
//
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
await resetFields();
showFooter.value = data?.showFooter ?? true;
setDrawerProps({ confirmLoading: false, showFooter: showFooter.value });
isUpdate.value = !!data?.isUpdate;
//
if (typeof data.record === 'object') {
setFieldsValue({
...data.record,
});
}
//
setProps({ disabled: !showFooter.value });
});
//
const getTitle = computed(() => {
if (!unref(isUpdate)) {
return '新增配置';
} else {
return unref(showFooter) ? '编辑配置' : '配置详情';
}
});
const { adaptiveWidth } = useDrawerAdaptiveWidth();
/**
* 提交事件
*/
async function handleSubmit() {
try {
let values = await validate();
setDrawerProps({ confirmLoading: true });
let params = values;
if (!unref(isUpdate)) {
await add(params);
}else {
await edit(params);
}
//
closeDrawer();
//
emit('success');
} finally {
setDrawerProps({ confirmLoading: false });
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,28 @@
import { defHttp } from '/@/utils/http/axios';
enum Api {
list = '/iot/tplink/config/list',
add = '/iot/tplink/config/add',
edit = '/iot/tplink/config/edit',
}
/**
*
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
/**
*
* @param params
*/
export const add = (params) => {
return defHttp.post({ url: Api.add, params });
}
/**
*
* @param params
*/
export const edit = (params) => {
return defHttp.post({ url: Api.edit, params });
}

View File

@ -0,0 +1,104 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
//列表数据
export const columns: BasicColumn[] = [
{
title: '图门地址',
align: "center",
dataIndex: 'tumsUrl',
width: 340,
},
{
title: '用户',
align: "center",
dataIndex: 'tumsUsername'
},
{
title: '密码',
align: "center",
dataIndex: 'tumsPassword'
},
{
title: 'FTP地址',
align: "center",
dataIndex: 'ftpIp'
},
{
title: 'FTP端口',
align: "center",
dataIndex: 'ftpPort'
},
{
title: 'FTP用户',
align: "center",
dataIndex: 'ftpUsername'
},
{
title: 'FTP密码',
align: "center",
dataIndex: 'ftpPassword'
},
{
title: 'FTP上传路径',
align: "center",
dataIndex: 'ftpUploadpath'
},
{
title: '更新时间',
align: "center",
dataIndex: 'updateDate'
},
];
export const formSchema: FormSchema[] = [
{
label: '',
field: 'id',
component: 'Input',
show: false,
},
{
label: '图门地址',
field: 'tumsUrl',
component: 'Input',
required: true
},
{
label: '用户',
field: 'tumsUsername',
component: 'Input',
required: true
},
{
label: '密码',
field: 'tumsPassword',
component: 'Input',
required: true
},
{
label: 'FTP地址',
field: 'ftpIp',
component: 'Input',
},
{
label: 'FTP端口',
field: 'ftpPort',
component: 'Input',
},
{
label: 'FTP用户',
field: 'ftpUsername',
component: 'Input',
},
{
label: 'FTP密码',
field: 'ftpPassword',
component: 'Input',
},
{
label: 'FTP上传路径',
field: 'ftpUploadpath',
component: 'Input',
}
];

View File

@ -0,0 +1,175 @@
<template>
<div>
<a-tabs v-model:activeKey="tabActiveKey" class="tabs-container">
<a-tab-pane key="dataAsync" tab="配置信息">
<!--引用表格-->
<BasicTable ref="tableRef" @register="registerTable">
<!--插槽:table标题-->
<template #tableTitle>
<a-button v-show="isShow" type="primary" preIcon="ant-design:plus-outlined" @click="handleAdd"> 新增</a-button>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)"/>
</template>
<template v-slot:bodyCell="{ column, record, index, text }">
</template>
</BasicTable>
</a-tab-pane>
<a-tab-pane key="syncLogList" tab="同步历史">
<SyncConfigLogList ref="syncConfigLogListRef" :serverType="serverType"></SyncConfigLogList>
</a-tab-pane>
</a-tabs>
</div>
<!-- 表单区域 -->
<ConfigDrawer @register="registerDrawer" @success="handleSuccess" />
</template>
<script lang="ts" name="iot-nuIotCameraInfo" setup>
import {ref, reactive, createVNode, h, onMounted, watch, unref} from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { columns } from './config.data';
import { list } from './config.api';
import { useUserStore } from '/@/store/modules/user';
import { useDrawer } from "@/components/Drawer";
import { useRouter } from 'vue-router';
import ConfigDrawer from './components/ConfigDrawer.vue';
import SyncConfigLogList from '@/views/iot/ConfigLog/SyncConfigLogList.vue';
//drawer
const [registerDrawer, { openDrawer }] = useDrawer();
let router = useRouter();
const formRef = ref();
const tableRef = ref();
const isShow = ref(false);
const serverType = ref('摄像头');
const queryParam = reactive<any>({});
const userStore = useUserStore();
//table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '配置信息',
api: list,
columns,
canResize: false,
showIndexColumn: true,
actionColumn: {
width: 100,
fixed: 'right',
},
beforeFetch: async (params) => {
return Object.assign(params, queryParam);
},
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = tableContext;
const labelCol = reactive({
xs:24,
sm:4,
xl:6,
xxl:4
});
const wrapperCol = reactive({
xs: 24,
sm: 20,
});
/**
* 新增
*/
function handleAdd(record: Recordable) {
openDrawer(true, {
record,
isUpdate: false,
showFooter: true,
tenantSaas: false,
});
}
/**
* 编辑
*/
function handleEdit(record: Recordable) {
openDrawer(true, {
record,
isUpdate: true,
showFooter: true,
tenantSaas: false,
});
}
/**
* 成功回调
*/
function handleSuccess() {
reload();
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
},
];
}
onMounted(() => {
watch(
() => tableRef.value.getDataSource(),
async () => {
if(tableRef.value.getDataSource().length<1){
isShow.value = true
}else{
isShow.value = false
}
},
{ deep: true, immediate: true }
);
});
</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%;
}
}
.p-2{
height: calc(100vh - 120px);
}
.tabs-container {
width: 100%;
background-color: white;
padding: 20px;
}
</style>

View File

@ -1,7 +1,7 @@
<template>
<a-card :bordered="false" style="height: 100%">
<div class="title">
2.选择录像存储位置码流计划
选择录像存储位置码流计划
</div>
<a-divider />
<a-spin :spinning="loading">
@ -25,6 +25,9 @@
</a-select>
</template>
</BasicForm>
<div style="text-align: center;margin-bottom:20px;">
<a-button @click="submitForm">确认</a-button>
</div>
</a-spin>
</a-card>
</template>
@ -32,11 +35,12 @@
<script lang="ts" setup>
import { watch, computed, inject, ref, unref, onMounted } from 'vue';
import { BasicForm, useForm } from '/@/components/Form/index';
import { addRecordCfgs, getAllRecordPlans, getStorageDevice } from '../plan.api';
import { list,addRecordCfgs, getAllRecordPlans, getStorageDevice } from '../plan.api';
import { addFormSchema } from "../plan.data";
import { useDesign } from '/@/hooks/web/useDesign';
import { useMessage } from '/@/hooks/web/useMessage';
import {propTypes} from "@/utils/propTypes";
import { nextTick } from 'process';
const { createMessage, createSuccessModal } = useMessage();
const emit = defineEmits(['success']);
const props = defineProps({
@ -75,6 +79,13 @@
// if(record.projectId!=''&&record.regionId!=''){
await fetchStorageDev(record.projectId,record.regionId);
await fetchPlan();
const data111 = await list(record);
var listInfo = data111.records;
if(listInfo.length>0){
setFieldsValue(listInfo[0]);
}else{
setFieldsValue(null);
}
// }
},
{ deep: true, immediate: true }
@ -96,29 +107,24 @@
//
async function submitForm() {
if(treeModel.value!=null){
if(treeModel.value.length == 0){
createMessage.info('请选择监控点!');
}else{
try {
loading.value = true;
let values = await validate();
console.log("🚀 ~ submitForm ~ values:", values)
values = Object.assign({}, model.value, values);
console.log(values);
values["ids"] = treeModel.value.join(',');
console.log("🚀 ~ submitForm ~ model:", model)
values['ids'] = initModel.value.deviceIndex;
console.log("🚀 ~ submitForm ~ values:", values)
//
await addRecordCfgs(values);
//
emit('success');
Object.assign(model.value, {});
} finally {
loading.value = false;
}
}
}
}
const fetchStorageDev = async (projectId,regionId) => {
console.log("🚀 ~ fetchStorageDev ~ projectId,regionId:", projectId,regionId)
storageDevOptions.value = [];
const data = await getStorageDevice({ projectId : projectId, regionId: regionId });
console.log(data);
@ -128,7 +134,7 @@
const fetchPlan = async () => {
planOptions.value = [];
const data = await getAllRecordPlans({});
console.log(data);
console.log("🚀 ~ fetchPlan ~ data:", data)
Object.assign(planOptions.value, data);
}

View File

@ -55,7 +55,7 @@
//table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '护理单元-物联管理-录像计划',
title: '区域-物联管理-录像计划',
api: list,
columns,
rowKey : "ids",

View File

@ -85,6 +85,11 @@ export const formSchema: FormSchema[] = [
field: 'storageDevName',
component: 'Input',
slot: 'storageDevInput',
componentProps: {
options: [
{label:'默认存储位置' , value: 0},
]
},
},
{
label: '录像码流',

View File

@ -43,7 +43,7 @@
//table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '护理单元-物联管理-机构信息',
title: '区域-物联管理-机构信息',
api: list,
columns,
canResize:false,

View File

@ -45,7 +45,7 @@
//table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '护理单元-物联管理-区域信息',
title: '区域-物联管理-区域信息',
api: list,
columns,
canResize:false,

View File

@ -5,17 +5,22 @@
<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="requestStatus">
<template #label><span title="请求状态">请求状态</span></template>
<j-select-multiple placeholder="请选择请求状态" v-model:value="queryParam.requestStatus" dictCode="dbsb_status" allow-clear />
<a-form-item name="paramStatus">
<template #label><span title="反馈状态">本次反馈状态</span></template>
<a-select placeholder="请选择反馈状态" v-model:value="queryParam.paramStatus" all-clear>
<a-select-option value="">全部</a-select-option>
<a-select-option value="0">成功</a-select-option>
<a-select-option value="1">失败</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="resolveStatus">
<template #label><span title="反馈状态">反馈状态</span></template>
<j-select-multiple placeholder="请选择反馈状态" v-model:value="queryParam.resolveStatus" dictCode="dbsb_status" allow-clear />
<a-form-item name="paramsRequestTime">
<template #label><span title="抄表时间">本次抄表时间</span></template>
<a-date-picker placeholder="请选择日期" format="YYYY-MM-DD" valueFormat="YYYY-MM-DD" v-model:value="queryParam.paramsRequestTime" style="width: 100%" />
</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">

View File

@ -0,0 +1,91 @@
<template>
<BasicDrawer
v-bind="$attrs"
@register="registerDrawer"
:title="getTitle"
:width="adaptiveWidth"
@ok="handleSubmit"
:showFooter="showFooter"
destroyOnClose
>
<BasicForm @register="registerForm" >
</BasicForm>
</BasicDrawer>
</template>
<script lang="ts" setup>
import {defineComponent, ref, computed, unref, useAttrs, createVNode, h} from 'vue';
import { BasicForm, useForm } from '/@/components/Form/index';
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
import { useDrawerAdaptiveWidth } from '/@/hooks/jeecg/useAdaptiveWidth';
import {Modal} from "ant-design-vue";
import {ExclamationCircleOutlined} from "@ant-design/icons-vue";
import { formSchema } from "../config.data";
import { add,edit } from '../config.api';
// Emits
const emit = defineEmits(['success', 'register']);
const attrs = useAttrs();
const isUpdate = ref(true);
const rowId = ref('');
const departOptions = ref([]);
let isFormDepartUser = false;
//
const [registerForm, { setProps, resetFields, setFieldsValue, validate, updateSchema }] = useForm({
labelWidth: 90,
schemas: formSchema,
showActionButtonGroup: false,
});
const showFooter = ref(true);
//
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
await resetFields();
showFooter.value = data?.showFooter ?? true;
setDrawerProps({ confirmLoading: false, showFooter: showFooter.value });
isUpdate.value = !!data?.isUpdate;
//
if (typeof data.record === 'object') {
setFieldsValue({
...data.record,
});
}
//
setProps({ disabled: !showFooter.value });
});
//
const getTitle = computed(() => {
if (!unref(isUpdate)) {
return '新增配置';
} else {
return unref(showFooter) ? '编辑配置' : '配置详情';
}
});
const { adaptiveWidth } = useDrawerAdaptiveWidth();
/**
* 提交事件
*/
async function handleSubmit() {
try {
let values = await validate();
setDrawerProps({ confirmLoading: true });
let params = values;
if (!unref(isUpdate)) {
await add(params);
}else {
await edit(params);
}
//
closeDrawer();
//
emit('success');
} finally {
setDrawerProps({ confirmLoading: false });
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,28 @@
import { defHttp } from '/@/utils/http/axios';
enum Api {
list = '/iot/tq/config/list',
add = '/iot/tq/config/add',
edit = '/iot/tq/config/edit',
}
/**
*
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
/**
*
* @param params
*/
export const add = (params) => {
return defHttp.post({ url: Api.add, params });
}
/**
*
* @param params
*/
export const edit = (params) => {
return defHttp.post({ url: Api.edit, params });
}

View File

@ -0,0 +1,89 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
//列表数据
export const columns: BasicColumn[] = [
{
title: '机构编码',
align: "center",
dataIndex: 'orgCode',
width: 80,
},
{
title: '机构名称',
align: "center",
dataIndex: 'orgCode_dictText',
width: 240,
},
{
title: '厂家云地址',
align: "center",
dataIndex: 'requestUrl',
},
{
title: '授权码',
align: "center",
dataIndex: 'authCode',
width: 260,
},
{
title: '随机字符串',
align: "center",
dataIndex: 'randomCode',
width: 260,
},
{
title: '通知地址',
align: "center",
dataIndex: 'notifyUrl'
},
{
title: '更新时间',
align: "center",
dataIndex: 'updateDate',
width: 160,
},
];
export const formSchema: FormSchema[] = [
{
label: '',
field: 'id',
component: 'Input',
show: false,
},
{
label: '机构',
field: 'orgCode',
component: 'JSelectDept',
componentProps: {
rowKey: 'orgCode',
labelKey: 'departName',
selectType: true,
},
},
{
label: '厂家云地址',
field: 'requestUrl',
component: 'Input',
required: true
},
{
label: '授权码',
field: 'authCode',
component: 'Input',
required: true
},
{
label: '随机字符串',
field: 'randomCode',
component: 'Input',
required: true
},
{
label: '通知地址',
field: 'notifyUrl',
component: 'Input',
},
];

View File

@ -0,0 +1,160 @@
<template>
<div>
<a-tabs v-model:activeKey="tabActiveKey" class="tabs-container">
<a-tab-pane key="dataAsync" tab="配置信息">
<!--引用表格-->
<BasicTable @register="registerTable">
<!--插槽:table标题-->
<template #tableTitle>
<a-button type="primary" preIcon="ant-design:plus-outlined" @click="handleAdd"> 新增</a-button>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)"/>
</template>
<template v-slot:bodyCell="{ column, record, index, text }">
</template>
</BasicTable>
</a-tab-pane>
<a-tab-pane key="syncLogList" tab="同步历史">
<SyncConfigLogList ref="syncConfigLogListRef" :serverType="serverType"></SyncConfigLogList>
</a-tab-pane>
</a-tabs>
</div>
<!-- 表单区域 -->
<ConfigDrawer @register="registerDrawer" @success="handleSuccess" />
</template>
<script lang="ts" name="iot-nuIotCameraInfo" setup>
import {ref, reactive, createVNode, h, onMounted, watch, unref} from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { columns } from './config.data';
import { list } from './config.api';
import { useUserStore } from '/@/store/modules/user';
import { useDrawer } from "@/components/Drawer";
import { useRouter } from 'vue-router';
import ConfigDrawer from './components/ConfigDrawer.vue';
import SyncConfigLogList from '@/views/iot/ConfigLog/SyncConfigLogList.vue';
//drawer
const [registerDrawer, { openDrawer }] = useDrawer();
let router = useRouter();
const formRef = ref();
const serverType = ref('电水表');
const queryParam = reactive<any>({});
const userStore = useUserStore();
//table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '配置信息',
api: list,
columns,
canResize: false,
showIndexColumn: true,
actionColumn: {
width: 100,
fixed: 'right',
},
beforeFetch: async (params) => {
params.column = 'id'
params.order = 'asc'
return Object.assign(params, queryParam);
},
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = tableContext;
const labelCol = reactive({
xs:24,
sm:4,
xl:6,
xxl:4
});
const wrapperCol = reactive({
xs: 24,
sm: 20,
});
/**
* 新增
*/
function handleAdd(record: Recordable) {
openDrawer(true, {
record,
isUpdate: false,
showFooter: true,
tenantSaas: false,
});
}
/**
* 编辑
*/
function handleEdit(record: Recordable) {
openDrawer(true, {
record,
isUpdate: true,
showFooter: true,
tenantSaas: false,
});
}
/**
* 成功回调
*/
function handleSuccess() {
reload();
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
},
];
}
</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%;
}
}
.p-2{
height: calc(100vh - 120px);
}
.tabs-container {
width: 100%;
background-color: white;
padding: 20px;
}
</style>

View File

@ -1,7 +1,14 @@
<template>
<j-modal :title="title" width="70%" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<a-drawer :title="title" :width="width" v-model:visible="visible" :closable="true"
:footer-style="{ textAlign: 'right' }" @close="handleCancel">
<DepartUtilsList ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></DepartUtilsList>
</j-modal>
<ConfigMaterialTypeForm ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></ConfigMaterialTypeForm>
<template #footer>
<a-button type="primary" style="margin-right: 8px" @click="handleCancel">关闭</a-button>
<a-button type="primary" @click="handleOk" v-if="!disableSubmit">确认</a-button>
</template>
</a-drawer>
</template>
<script lang="ts" setup>
@ -10,7 +17,7 @@
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
const title = ref<string>('');
const width = ref<number>(800);
const width = ref<string>('80%');
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();

View File

@ -1,7 +1,13 @@
<template>
<j-modal :title="title" width="70%" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<a-drawer :title="title" :width="width" v-model:visible="visible" :closable="true"
:footer-style="{ textAlign: 'right' }" @close="handleCancel">
<WaterApiLogList ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></WaterApiLogList>
</j-modal>
<template #footer>
<a-button type="primary" style="margin-right: 8px" @click="handleCancel">关闭</a-button>
<a-button type="primary" @click="handleOk" v-if="!disableSubmit">确认</a-button>
</template>
</a-drawer>
</template>
<script lang="ts" setup>
@ -10,7 +16,7 @@
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
const title = ref<string>('');
const width = ref<number>(800);
const width = ref<string>('80%');
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();

View File

@ -102,11 +102,11 @@ export const searchFormSchema: FormSchema[] = [
// colProps: { span: 6 },
// },
// {
// label: '护理单元',
// label: '区域',
// field: 'deviceStatus',
// component: 'JDictSelectTag',
// componentProps: {
// placeholder: '请选择护理单元',
// placeholder: '请选择区域',
// dictCode: 'nu_base_info,nu_name,id,del_flag = 0 order by nu_name asc',
// },
// colProps: { span: 6 },

View File

@ -84,7 +84,7 @@ import { defHttp } from '/@/utils/http/axios';
//labelWidth: 120,
schemas: searchFormSchema,
autoSubmitOnEnter:true,
showAdvancedButton:true,
showAdvancedButton:false,
fieldMapToNumber: [
],
fieldMapToTime: [
@ -109,7 +109,7 @@ import { defHttp } from '/@/utils/http/axios';
(selectedRowKeys.value = []) && reload();
}
//
//
function handleHldyParams(params){
defHttp.post({
url: "/iot/tq/electricityMeter/editHldy",
@ -245,7 +245,7 @@ import { defHttp } from '/@/utils/http/axios';
apiLogModal.value.showApiLog(record);
}
/**
* 配置护理单元
* 配置区域
*/
function handlePzhldy(record){
hldyUtilsModal.value.disableSubmit = true;

View File

@ -94,7 +94,7 @@
//labelWidth: 120,
schemas: searchFormSchema,
autoSubmitOnEnter:true,
showAdvancedButton:true,
showAdvancedButton:false,
fieldMapToNumber: [
],
fieldMapToTime: [
@ -239,14 +239,14 @@
apiLogModal.value.showApiLog(record);
}
/**
* 配置护理单元
* 配置区域
*/
function handlePzhldy(record){
hldyUtilsModal.value.disableSubmit = true;
hldyUtilsModal.value.edit(record);
}
//
//
function handleHldyParams(params){
defHttp.post({
url: "/iot/tq/waterMeter/editHldy",

View File

@ -110,11 +110,11 @@ export const searchFormSchema: FormSchema[] = [
// colProps: { span: 6 },
// },
// {
// label: '护理单元',
// label: '区域',
// field: 'deviceStatus',
// component: 'JDictSelectTag',
// componentProps: {
// placeholder: '请选择护理单元',
// placeholder: '请选择区域',
// dictCode: 'nu_base_info,nu_name,id,del_flag = 0 order by nu_name asc',
// },
// colProps: { span: 6 },

View File

@ -0,0 +1,91 @@
<template>
<BasicDrawer
v-bind="$attrs"
@register="registerDrawer"
:title="getTitle"
:width="adaptiveWidth"
@ok="handleSubmit"
:showFooter="showFooter"
destroyOnClose
>
<BasicForm @register="registerForm" >
</BasicForm>
</BasicDrawer>
</template>
<script lang="ts" setup>
import {defineComponent, ref, computed, unref, useAttrs, createVNode, h} from 'vue';
import { BasicForm, useForm } from '/@/components/Form/index';
import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
import { useDrawerAdaptiveWidth } from '/@/hooks/jeecg/useAdaptiveWidth';
import {Modal} from "ant-design-vue";
import {ExclamationCircleOutlined} from "@ant-design/icons-vue";
import { formSchema } from "../config.data";
import { add,edit } from '../config.api';
// Emits
const emit = defineEmits(['success', 'register']);
const attrs = useAttrs();
const isUpdate = ref(true);
const rowId = ref('');
const departOptions = ref([]);
let isFormDepartUser = false;
//
const [registerForm, { setProps, resetFields, setFieldsValue, validate, updateSchema }] = useForm({
labelWidth: 90,
schemas: formSchema,
showActionButtonGroup: false,
});
const showFooter = ref(true);
//
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
await resetFields();
showFooter.value = data?.showFooter ?? true;
setDrawerProps({ confirmLoading: false, showFooter: showFooter.value });
isUpdate.value = !!data?.isUpdate;
//
if (typeof data.record === 'object') {
setFieldsValue({
...data.record,
});
}
//
setProps({ disabled: !showFooter.value });
});
//
const getTitle = computed(() => {
if (!unref(isUpdate)) {
return '新增配置';
} else {
return unref(showFooter) ? '编辑配置' : '配置详情';
}
});
const { adaptiveWidth } = useDrawerAdaptiveWidth();
/**
* 提交事件
*/
async function handleSubmit() {
try {
let values = await validate();
setDrawerProps({ confirmLoading: true });
let params = values;
if (!unref(isUpdate)) {
await add(params);
}else {
await edit(params);
}
//
closeDrawer();
//
emit('success');
} finally {
setDrawerProps({ confirmLoading: false });
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,28 @@
import { defHttp } from '/@/utils/http/axios';
enum Api {
list = '/iot/yiweilian/config/list',
add = '/iot/yiweilian/config/add',
edit = '/iot/yiweilian/config/edit',
}
/**
*
* @param params
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
/**
*
* @param params
*/
export const add = (params) => {
return defHttp.post({ url: Api.add, params });
}
/**
*
* @param params
*/
export const edit = (params) => {
return defHttp.post({ url: Api.edit, params });
}

View File

@ -0,0 +1,42 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
//列表数据
export const columns: BasicColumn[] = [
{
title: '厂家云地址',
align: "center",
dataIndex: 'requestUrl',
},
{
title: '用户标识',
align: "center",
dataIndex: 'clientId'
},
{
title: '更新时间',
align: "center",
dataIndex: 'updateDate'
},
];
export const formSchema: FormSchema[] = [
{
label: '',
field: 'id',
component: 'Input',
show: false,
},
{
label: '厂家云地址',
field: 'requestUrl',
component: 'Input',
required: true
},
{
label: '用户标识',
field: 'clientId',
component: 'Input',
required: true
},
];

View File

@ -0,0 +1,174 @@
<template>
<div>
<a-tabs v-model:activeKey="tabActiveKey" class="tabs-container">
<a-tab-pane key="dataAsync" tab="配置信息">
<!--引用表格-->
<BasicTable ref="tableRef" @register="registerTable">
<!--插槽:table标题-->
<template #tableTitle>
<a-button v-show="isShow" type="primary" preIcon="ant-design:plus-outlined" @click="handleAdd"> 新增</a-button>
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)"/>
</template>
<template v-slot:bodyCell="{ column, record, index, text }">
</template>
</BasicTable>
</a-tab-pane>
<a-tab-pane key="syncLogList" tab="同步历史">
<SyncConfigLogList ref="syncConfigLogListRef" :serverType="serverType"></SyncConfigLogList>
</a-tab-pane>
</a-tabs>
</div>
<!-- 表单区域 -->
<ConfigDrawer @register="registerDrawer" @success="handleSuccess" />
</template>
<script lang="ts" name="iot-nuIotCameraInfo" setup>
import {ref, reactive, createVNode, h, onMounted, watch, unref} from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { columns } from './config.data';
import { list } from './config.api';
import { useUserStore } from '/@/store/modules/user';
import { useDrawer } from "@/components/Drawer";
import { useRouter } from 'vue-router';
import ConfigDrawer from './components/ConfigDrawer.vue'
import SyncConfigLogList from '@/views/iot/ConfigLog/SyncConfigLogList.vue';
//drawer
const [registerDrawer, { openDrawer }] = useDrawer();
let router = useRouter();
const formRef = ref();
const tableRef = ref();
const isShow = ref(false);
const serverType = ref('温湿度计');
const queryParam = reactive<any>({});
const userStore = useUserStore();
//table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '配置信息',
api: list,
columns,
canResize: false,
showIndexColumn: true,
actionColumn: {
width: 100,
fixed: 'right',
},
beforeFetch: async (params) => {
return Object.assign(params, queryParam);
},
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = tableContext;
const labelCol = reactive({
xs:24,
sm:4,
xl:6,
xxl:4
});
const wrapperCol = reactive({
xs: 24,
sm: 20,
});
/**
* 新增
*/
function handleAdd(record: Recordable) {
openDrawer(true, {
record,
isUpdate: false,
showFooter: true,
tenantSaas: false,
});
}
/**
* 编辑
*/
function handleEdit(record: Recordable) {
openDrawer(true, {
record,
isUpdate: true,
showFooter: true,
tenantSaas: false,
});
}
/**
* 成功回调
*/
function handleSuccess() {
reload();
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
},
];
}
onMounted(() => {
watch(
() => tableRef.value.getDataSource(),
async () => {
if(tableRef.value.getDataSource().length<1){
isShow.value = true
}else{
isShow.value = false
}
},
{ deep: true, immediate: true }
);
});
</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%;
}
}
.p-2{
height: calc(100vh - 120px);
}
.tabs-container {
width: 100%;
background-color: white;
padding: 20px;
}
</style>

View File

@ -0,0 +1,74 @@
<template>
<!-- <j-modal :title="title" width="70%" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
</j-modal> -->
<a-drawer :title="title" :width="width" v-model:visible="visible" :closable="true"
:footer-style="{ textAlign: 'right' }" @close="handleCancel">
<ApiLogAlarmList ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></ApiLogAlarmList>
<ConfigMaterialTypeForm ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></ConfigMaterialTypeForm>
<template #footer>
<a-button type="primary" style="margin-right: 8px" @click="handleCancel">关闭</a-button>
<a-button type="primary" @click="handleOk" v-if="!disableSubmit">确认</a-button>
</template>
</a-drawer>
</template>
<script lang="ts" setup>
import { ref, nextTick, defineExpose } from 'vue';
import ApiLogAlarmList from './ApiLogAlarmList.vue'
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
const title = ref<string>('');
const width = ref<string>('80%');
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();
const emit = defineEmits(['register', 'success']);
/**
* 日志
* @param record
*/
function showLogAlarm(record) {
title.value = '日志';
visible.value = true;
nextTick(() => {
registerForm.value.init(record);
});
}
/**
* 确定按钮点击事件
*/
function handleOk() {
registerForm.value.submitForm();
}
/**
* form保存回调事件
*/
function submitCallback(params) {
handleCancel();
emit('success',params);
}
/**
* 取消按钮回调事件
*/
function handleCancel() {
visible.value = false;
}
defineExpose({
showLogAlarm,
disableSubmit,
});
</script>
<style lang="less">
/**隐藏样式-modal确定按钮 */
.jee-hidden {
display: none !important;
}
</style>
<style lang="less" scoped></style>

View File

@ -0,0 +1,158 @@
<template>
<div class="p-2">
<!--查询区域-->
<div class="jeecg-basic-table-form-container">
<a-form ref="formRef" @keyup.enter.native="searchQuery" :model="queryParam" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-row :gutter="24">
<a-col :lg="6">
<a-form-item name="paramsRequestTime">
<template #label><span title="抄表时间">操作时间</span></template>
<a-date-picker placeholder="请选择日期" format="YYYY-MM-DD" valueFormat="YYYY-MM-DD" v-model:value="queryParam.paramsRequestTime" style="width: 100%" />
</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-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>
</span>
</a-col>
</a-row>
</a-form>
</div>
<!--引用表格-->
<BasicTable @register="registerTable">
<!--插槽:table标题-->
<template #tableTitle>
</template>
<template v-slot:bodyCell="{ column, record, index, text }">
</template>
</BasicTable>
</div>
</template>
<script lang="ts" name="yiweilian-apiLogList" setup>
import { ref, reactive } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { logColumns, logQuerySchema } from '../humid.data';
import { logList } from '../humid.api';
import { useUserStore } from '/@/store/modules/user';
const formRef = ref();
const queryParam = reactive<any>({});
const toggleSearchStatus = ref<boolean>(false);
const registerModal = ref();
const userStore = useUserStore();
//table
const { prefixCls, tableContext } = useListPage({
tableProps: {
title: '操作日志',
api: logList,
columns:logColumns,
canResize:false,
showActionColumn: false,
// showTableSetting: false,
// formConfig: {
// schemas: logQuerySchema,
// autoSubmitOnEnter:false,
// showAdvancedButton:false,
// fieldMapToNumber: [
// ],
// fieldMapToTime: [
// ],
// },
actionColumn: {
width: 120,
fixed: 'right',
},
beforeFetch: async (params) => {
return Object.assign(params, queryParam);
},
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = tableContext;
const labelCol = reactive({
xs:24,
sm:8,
xl:6,
xxl:8
});
const wrapperCol = reactive({
xs: 24,
sm: 16,
});
/**
* 高级查询事件
*/
function handleSuperQuery(params) {
Object.keys(params).map((k) => {
queryParam[k] = params[k];
});
searchQuery();
}
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 查询
*/
function searchQuery() {
reload();
}
/**
* 重置
*/
function searchReset() {
formRef.value.resetFields();
selectedRowKeys.value = [];
//
reload();
}
function init(record) {
console.log("🚀 ~ init ~ record:", record)
queryParam.sn = record.sn;
reload();
}
defineExpose({
init,
});
</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%;
}
}
</style>

View File

@ -98,11 +98,11 @@ export const searchFormSchema: FormSchema[] = [
// colProps: { span: 6 },
// },
// {
// label: '护理单元',
// label: '区域',
// field: 'deviceStatus',
// component: 'JDictSelectTag',
// componentProps: {
// placeholder: '请选择护理单元',
// placeholder: '请选择区域',
// dictCode: 'nu_base_info,nu_name,id,del_flag = 0 order by nu_name asc',
// },
// colProps: { span: 6 },

View File

@ -192,7 +192,7 @@
}
//
//
function handleHldyParams(params){
defHttp.post({
url: "/iot/yiweilian/humidDevice/editHldy",
@ -203,7 +203,7 @@
})
}
/**
* 配置护理单元
* 配置区域
*/
function handlePzhldy(record){
hldyUtilsModal.value.disableSubmit = true;

View File

@ -0,0 +1,12 @@
import { defHttp } from '/@/utils/http/axios';
enum Api {
getOrgInfo = '/admin/orgapplyinfo/orgApplyInfo/getOrgInfo',
}
/**
* sys_depart信息
* @param params orgCode部门编码
* @returns
*/
export const getOrgInfo = (params) => defHttp.get({ url: Api.getOrgInfo, params });

View File

@ -0,0 +1,420 @@
<template>
<div class="p-2 base-class">
<a-card class="base-con-class">
<div class="org-info-card">
<div class="org-info-header">
<div class="org-title">
<span class="base-info-label">机构信息:</span>
<span v-if="!orgData" class="base-info-label" style="color: #ff4d4f;"> 请先选择机构</span>
<span v-else class="base-info-label">{{ orgData?.departName }}</span>
<span v-if="orgData" class="base-info-label" style="margin-left:30px;">机构编码{{ orgData?.orgCode || '-' }}</span>
</div>
<a-button v-if="!orgSelectedCon" class="reset-btn" type="primary" @click.stop="orgReset" style="margin-top:10px;">
<span>重新选择</span>
</a-button>
</div>
<!-- <div class="org-info-content">
<div class="info-row">
<div class="info-item">
<span class="label">机构编码</span>
<span class="value">{{ orgData?.orgCode || '-' }}</span>
</div>
<div class="info-item">
<span class="label">加盟时间</span>
<span class="value">{{ orgData?.franchiseTime?.substring(0, 10) || '-' }}</span>
</div>
<div class="info-item">
<span class="label">负责人</span>
<span class="value">{{ orgData?.orgLeader || '-' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="label">电话</span>
<span class="value">{{ orgData?.orgLeaderPhone || '-' }}</span>
</div>
<div class="info-item">
<span class="label">地址</span>
<span class="value">{{ orgData?.comRegisterAddress || '-' }}</span>
</div>
<div class="info-item">
</div>
</div>
</div> -->
</div>
</a-card>
</div>
<div class="p-2 con-class" style="margin-top: -10px;" v-show="orgSelectedCon">
<a-card :bordered="false" class="org-container">
<a-row :style="props.layout === 'half' ? { height: '68vh', overflow: 'auto' } : {}">
<a-col v-for="item 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"
style="padding: 8px;min-height: 290px;">
<div class="org-card" :class="{ 'active': item.orgId == orgData?.orgId }" @click="handleOrgSelected(item)">
<a-card
:class="{ 'selected-card': selectedOrgs.some(org => org.orgCode === item.orgCode) }"
style="width: 100%; border-radius: 8px; border:0px; "
:headStyle="{ height: '60px', padding: '0 24px' }"
:style="{ cursor: showChoose ? 'pointer' : 'default' }"
:bodyStyle="{ padding: '24px 24px 4px 24px !important' }">
<template #title>
<a-row style="font-weight: normal;">
<a-col :span="props.layout == 'full' ? 22 : 21" style="font-size: 14px; padding-top: 4px;">
<div>
<span style="font-weight: bold;">{{ item.departName }}</span>
<!-- 如果是已选择显示"已选择" -->
<span style="color: green; font-size: 12px; margin-left: 8px;" v-if="selectedOrgs.some(org => org.orgCode === item.orgCode)">已选择</span>
</div>
</a-col>
<a-col :span="props.layout == 'full' ? 2 : 3" style="text-align: center; padding-top: 4px;">
<div class="zxClass">{{ item.orgCode }}</div>
</a-col>
</a-row>
</template>
<p>加盟时间{{ item.franchiseTime?.substring(0, 10) }}</p>
<p>机构负责人{{ item.orgLeader }}</p>
<p>负责人电话{{ item.orgLeaderPhone }}</p>
<p :title="item.comRegisterAddress">
机构地址{{ item.comRegisterAddress }}</p>
</a-card>
</div>
</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'">
<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>
</a-card>
</div>
</template>
<script lang="ts" name="synchronization-directive" setup>
import {ref, reactive, onMounted} from 'vue';
import {Empty} from 'ant-design-vue';
import {Modal} from 'ant-design-vue';
import { Pagination } from 'ant-design-vue'
import {getOrgInfo} from './OrgApplyInfo.api'
const emit = defineEmits(['orgChanged']);
const props = defineProps({
showChoose: {type: Boolean, default: false},
layout: {type: String, default: 'full'}, // : 'full' 'half'
})
const orgTableList = ref<any>({records: [], total: 0})
const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE;
interface OrganizationData {
orgId?: string;
departName: string;
orgCode: string;
franchiseTime?: string;
orgLeader?: string;
orgLeaderPhone?: string;
comRegisterAddress?: string;
}
const queryParam = reactive<any>({})
const pageParams = ref({pageNo: 1, pageSize: 8})
const orgData = ref<OrganizationData | null>(null);
const orgSelectedCon = ref(true);
// ID
const selectedOrgs = ref<string[]>([])
const handleOrgSelected = async (org) => {
if (!!orgData.value && orgData.value.orgId != org.orgId) {
// Modal.confirm({
// title: '',
// content: '',
// okText: '',
// cancelText: '',
// onOk: async () => {
// await loadOrgData(org);
// },
// });
await loadOrgData(org);
} else {
await loadOrgData(org);
}
};
const loadOrgData = async (org) => {
//
orgData.value = org;
emit('orgChanged', org)
};
const orgReset = () => {
orgSelectedCon.value = true;
emit('orgReset');
}
const resetOrgSelectedCon = (v_) => {
orgSelectedCon.value = v_
}
/** 数据加载 */
function reload() {
queryParam.pageSize = pageParams.value.pageSize
queryParam.pageNo = pageParams.value.pageNo
if (props.layout == 'half') {
queryParam.pageSize = -1
}
getOrgInfo(queryParam).then(res => {
orgTableList.value = res
})
}
onMounted(() => {
reload()
});
defineExpose({
orgData,
resetOrgSelectedCon,
});
</script>
<style lang="less" scoped>
:deep(.ant-card-bordered) {
border-radius: 8px !important;
}
.base-class {
:deep(.ant-card .ant-card-body) {
padding-top: 10px !important;
padding-bottom: 10px !important;
}
}
.con-class {
:deep(.ant-card-body) {
padding: 0px !important;
}
}
.base-con-class {
background: white;
border-radius: 8px;
cursor: pointer;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
transform: translateY(-2px);
border: 1px solid rgba(0, 0, 0, 0.05);
}
.org-info-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 5px;
padding-bottom: 5px;
// border-bottom: 1px solid #f0f0f0;
height: 38px;
}
.org-title {
display: flex;
align-items: center;
margin-top: 9px;
.base-info-label {
font-weight: 600;
color: #595959;
font-size: 15px;
}
.org-name {
margin-left: 10px;
font-weight: 600;
color: #262626;
font-size: 16px;
}
}
.reset-btn {
background-color: #1890ff;
border-color: #1890ff;
height: 32px;
border-radius: 4px;
font-weight: 500;
}
/* 新增的机构卡片样式 */
.org-cards-container {
max-height: 75vh;
overflow-y: auto;
padding: 8px;
}
.org-card {
margin-bottom: 16px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
height: 100%;
&:hover {
transform: translateY(-4px);
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
background: radial-gradient(circle at center, #c7e6ff 0%, #d4eeff 70%, #e4f0ff 100%);
}
:deep(.ant-card-head) {
border-bottom: 1px solid #f0f0f0;
padding: 0 16px;
min-height: 48px;
.ant-card-head-title {
padding: 12px 0;
font-weight: 500;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
.org-container {
//background: transparent;
background: white;
.org-card {
padding: 0px;
border: 1px solid #f0f0f0;
border-radius: 8px;
transition: all 0.3s;
background: white;
&:hover {
border-color: #1890ff;
box-shadow: 0 2px 12px rgba(24, 144, 255, 0.2);
}
&.active {
border: 1px solid #1890ff;
//background: #f0f8ff;
}
.org-header {
display: flex;
align-items: center;
margin-bottom: 12px;
.org-title {
margin: 0 0 0 8px;
font-size: 16px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.contact-line {
display: flex;
justify-content: space-between;
>span {
display: inline-flex;
align-items: center;
.anticon {
margin-right: 4px;
color: #8c8c8c;
}
}
}
:deep(.ant-descriptions) {
.ant-descriptions-item-label {
width: 80px;
color: #666;
}
}
}
}
.org-info-content {
.info-row {
display: flex;
margin-bottom: 5px;
&:last-child {
margin-bottom: 0;
}
}
.info-item {
flex: 1;
padding: 0 8px;
.label {
color: #8c8c8c;
font-size: 13px;
margin-right: 8px;
}
.value {
color: #262626;
font-size: 13px;
word-break: break-all;
}
}
}
.zxClass {
font-size: 12px;
background: linear-gradient(to right, #1ea0fa, #017de9);
border-radius: 8px;
height: 25px;
color: white;
line-height: 25px;
}
.tbClass {
background: #f6f6f6;
padding: 8px;
border-radius: 5px;
}
.antTitle {
margin-top: 10px;
display: block;
font-size: 12px;
}
.ellipsis-one-lines {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
text-overflow: ellipsis;
}
.selected-card {
border: 2px solid #1890ff;
box-shadow: 0 0 8px rgba(24, 144, 255, 0.3);
}
</style>

View File

@ -0,0 +1,49 @@
import { defHttp } from '/@/utils/http/axios';
enum Api {
sourceList = '/iot/tplink/cameraInfo/sourceList',
departList = '/iot/tplink/cameraInfo/departList',
nuList = '/iot/tplink/cameraInfo/departNuList',
businessList = '/iot/tplink/cameraInfo/businessList',
nuSyncList = '/iot/tplink/cameraInfo/nuSyncList',
syncDevices = '/iot/tplink/cameraInfo/syncDevices',
syncLogList = '/iot/tplink/cameraInfo/syncLogList',
}
/**
*
* @param params
*/
export const sourceListApi = (params) => defHttp.get({ url: Api.sourceList, params });
/**
*
* @param params
*/
export const departListApi = (params) => defHttp.get({ url: Api.departList, params });
/**
*
* @param params
*/
export const nuListApi = (params) => defHttp.get({ url: Api.nuList, params });
/**
*
* @param params
*/
export const businessListApi = (params) => defHttp.get({ url: Api.businessList, params });
/**
*
* @param params
*/
export const nuSyncListApi = (params) => defHttp.get({ url: Api.nuSyncList, params });
/**
*
* @param params
*/
export const syncDevicesApi = (params) => {
return defHttp.post({ url: Api.syncDevices, params });
}
/**
*
* @param params
*/
export const syncLogListApi = (params) => defHttp.get({ url: Api.syncLogList, params });

View File

@ -0,0 +1,280 @@
import {BasicColumn, FormSchema} from '/@/components/Table';
export const businessColumns: BasicColumn[] = [
{
title: 'SN',
align: 'center',
dataIndex: 'deviceIndex',
width: 60,
},
{
title: '名称',
align: 'center',
dataIndex: 'deviceName',
width: 140,
},
{
title: 'MAC',
align: 'center',
dataIndex: 'mac',
width: 140,
},
{
title: '区域编码',
align: "center",
dataIndex: 'nuId',
resizable: true,
},
{
title: '区域名称',
align: "center",
dataIndex: 'nuName',
resizable: true,
},
{
title: '区域标签',
align: "center",
dataIndex: 'areaFlag_dictText',
resizable: true,
}
];
//列表数据
export const unselectedSourceColumns: BasicColumn[] = [
{
title: 'SN',
align: 'center',
dataIndex: 'deviceIndex',
width: 60,
},
{
title: '名称',
align: 'center',
dataIndex: 'deviceName',
width: 140,
},
{
title: 'MAC',
align: 'center',
dataIndex: 'mac',
width: 140,
},
];
//列表数据
export const selectedSourceColumns: BasicColumn[] = [
{
title: 'SN',
align: 'center',
dataIndex: 'deviceIndex',
width: 60,
},
{
title: '名称',
align: 'center',
dataIndex: 'deviceName',
width: 140,
},
{
title: 'MAC',
align: 'center',
dataIndex: 'mac',
width: 140,
},
{
title: '机构',
align: "center",
dataIndex: 'departName',
resizable: true,
},
{
title: '区域编码',
align: "center",
dataIndex: 'nuId',
resizable: true,
},
{
title: '区域名称',
align: "center",
dataIndex: 'nuName',
resizable: true,
},
{
title: '区域标签',
align: "center",
dataIndex: 'areaFlag_dictText',
resizable: true,
},
];
export const nusColumns: BasicColumn[] = [
{
title: '区域编码',
align: "center",
dataIndex: 'nuId',
resizable: true,
},
{
title: '区域名称',
align: "center",
dataIndex: 'nuName',
resizable: true,
},
{
title: '区域标签',
align: "center",
dataIndex: 'areaFlag_dictText',
resizable: true,
},
{
title: '绑定设备数量',
align: "center",
dataIndex: 'deviceNum'
}
];
export const nuFormSchema: FormSchema[] = [
{
label: '区域标签',
field: 'areaFlag',
component: 'JDictSelectTag',
componentProps: {
dictCode: 'nu_type',
},
colProps: { span: 6 },
},
];
export const selectedColumns: BasicColumn[] = [
{
title: 'SN',
align: 'center',
dataIndex: 'deviceIndex',
width: 60,
},
{
title: '名称',
align: 'center',
dataIndex: 'deviceName',
width: 140,
},
{
title: 'MAC',
align: 'center',
dataIndex: 'mac',
width: 140,
},
{
title: '操作区域',
align: 'center',
dataIndex: 'dataTypeText',
width: 80,
},
{
title: '操作类型',
align: 'center',
dataIndex: 'actionType',
width: 80,
},
{
title: '区域编码',
align: "center",
dataIndex: 'nuId',
resizable: true,
},
{
title: '区域名称',
align: "center",
dataIndex: 'nuName',
resizable: true,
},
{
title: '区域标签',
align: "center",
dataIndex: 'areaFlag_dictText',
resizable: true,
}
];
export const asyncMaincolumns: BasicColumn[] = [
{
title: 'SN',
align: 'center',
dataIndex: 'sn',
},
{
title: '设备名称',
align: "center",
dataIndex: 'deviceName',
},
{
title: '设备类型',
align: "center",
dataIndex: 'serverType',
},
{
title: '同步时间',
align: "center",
dataIndex: 'createTime',
}
];
export const asyncSeedColumns: BasicColumn[] = [
{
title: '同步类型',
align: "center",
dataIndex: 'syncType',
},
{
title: '同步状态',
align: "center",
dataIndex: 'status',
},
{
title: '同步时间',
align: "center",
dataIndex: 'createTime',
},
{
title: '现机构',
align: "center",
dataIndex: 'departName',
},
{
title: '现区域',
align: "center",
dataIndex: 'nuId',
},
{
title: '原机构',
align: "center",
dataIndex: 'oldDepartName',
},
{
title: '原区域',
align: "center",
dataIndex: 'oldNuId',
},
];
export const logFormSchema: FormSchema[] = [
{
label: 'SN',
field: 'sn',
component: 'Input',
componentProps: {
placeholder: '请输入SN',
},
// colProps: { span: 6 },
},
{
label: '名称',
field: 'deviceName',
component: 'Input',
componentProps: {
placeholder: '请输入名称',
},
// colProps: { span: 6 },
},
];

View File

@ -0,0 +1,214 @@
<template>
<div class="p-2">
<BasicTable ref="tableRef" @register="registerTable" :scroll="{ y: '56vh' }" :rowSelection="rowSelection" :rowClassName="getRowClassName" @selection-change="handleSelectionChange" size="small">
<template #tableTitle></template>
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
</BasicTable>
</div>
</template>
<script lang="ts" name="tplink-camera-businessTable" setup>
import { ref, reactive, watch,computed } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { businessColumns } from '../camera.data';
import { businessListApi } from '../camera.api';
const props = defineProps({
queryParams: {
type: Object,
default: () => ({})
},
});
const emit = defineEmits(['select-change']);
const queryParam = reactive<any>({});
const tableRef = ref();
const selectedRowIds = ref<Set<string | number>>(new Set());
const allSelectedRows = ref<any[]>([]);
//
const getRowClassName = (record) => {
return selectedRowIds.value.has(record.deviceIndex) ? 'selected-row' : '';
};
watch(() => props.queryParams, (newParams) => {
reload();
}, { deep: true });
//
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '已同步设备表',
api: businessListApi,
columns:businessColumns,
size: 'small',
showTableSetting: false,
canResize: false,
useSearchForm: false,
showIndexColumn: true,
rowSelection: {type:'checkbox'},
rowKey: 'id',
actionColumn: {
width: 120,
fixed: 'right',
},
beforeFetch: async (params) => {
Object.assign(params, props.queryParams);
params.selectedRowIds = Array.from(selectedRowIds.value)
return params;
},
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection,selectedRows, selectedRowKeys }] = tableContext;
function getTableAction(record) {
const actions = [];
if (selectedRowIds.value.has(record.deviceIndex)) {
actions.push({
label: '取消',
color: 'error',
onClick: () => {
removeSelected(record);
}
});
} else {
actions.push({
label: '变更',
onClick: () => {
toggleSelect(record);
}
});
actions.push({
label: '移除',
onClick: () => {
deleteSelect(record);
}
});
}
return actions;
}
function handleSelectionChange(selectedRowSet) {
// console.log(':', selectedRowSet);
allSelectedRows.value = selectedRowSet.rows;
selectedRowKeys.value = selectedRowSet.keys;
}
//
function clearSelected(){
// console.log('');
selectedRowKeys.value = [];
allSelectedRows.value = [];
}
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
//
const toggleSelect = (record) => {
if (!selectedRowIds.value.has(record.deviceIndex)) {
selectedRowIds.value.add(record.deviceIndex);
}
allSelectedRows.value = [];
allSelectedRows.value.push(record);
emit('editSelect');
};
//
const deleteSelect = (record) => {
if (!selectedRowIds.value.has(record.deviceIndex)) {
selectedRowIds.value.add(record.deviceIndex);
}
allSelectedRows.value = [];
allSelectedRows.value.push(record);
emit('deleteSelect');
};
//
const removeSelected = (record) => {
selectedRowIds.value.delete(record.deviceIndex);
emit('removeSelect',record);
};
const updateSelection = (selectedRecords) => {
selectedRowIds.value.clear();
selectedRecords.forEach((value, key) => {
selectedRowIds.value.add(key);
});
//
if (registerTable) {
registerTable.toggleRowSelection?.(Array.from(selectedRowIds.value), true);
}
};
function reloadData(){
reload();
}
//
defineExpose({
updateSelection,
clearSelected,
reloadData,
allSelectedRows,
});
</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;
}
//:deep(.ant-table-title) {
// display: none !important;
//}
:deep(.selected-row) {
background-color: #e6f7ff !important;
&:hover td {
background-color: #e6f7ff !important;
}
}
</style>

View File

@ -0,0 +1,123 @@
<template>
<!--引用表格-->
<BasicTable @register="registerTable">
<!--插槽:table标题-->
<template #tableTitle></template>
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
</BasicTable>
</template>
<script lang="ts" name="tplink-camera-apiLogList" setup>
import { ref, reactive } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import {nuFormSchema, nusColumns} from '../camera.data';
import {nuSyncListApi} from '../camera.api';
import { useUserStore } from '/@/store/modules/user';
const emit = defineEmits(['register', 'success']);
// const props = defineProps({
// orgCode: '',
// });
const formRef = ref();
const queryParam = reactive<any>({});
const toggleSearchStatus = ref<boolean>(false);
const registerModal = ref();
const userStore = useUserStore();
//table
const { prefixCls, tableContext } = useListPage({
tableProps: {
title: '区域列表',
api: nuSyncListApi,
columns:nusColumns,
canResize:false,
showActionColumn: true,
showTableSetting: false,
showIndexColumn: true,
formConfig: {
//labelWidth: 120,
schemas: nuFormSchema,
autoSubmitOnEnter:false,
showAdvancedButton:false,
fieldMapToNumber: [
],
fieldMapToTime: [
],
},
actionColumn: {
width: 120,
fixed: 'right',
},
beforeFetch: async (params) => {
// queryParam.orgCode = props.orgCode //
return Object.assign(params, queryParam);
},
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = tableContext;
const labelCol = reactive({
xs:24,
sm:8,
xl:6,
xxl:8
});
const wrapperCol = reactive({
xs: 24,
sm: 16,
});
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 查询
*/
function searchQuery() {
reload();
}
/**
* 重置
*/
function searchReset() {
formRef.value.resetFields();
selectedRowKeys.value = [];
//
reload();
}
//
async function handleSelectNu(record: Recordable) {
// console.log(record);
emit('ok',record);
}
function getTableAction(record) {
return [
{
label: '选择',
onClick: handleSelectNu.bind(null, record)
}
]
}
function init(record,type) {
// console.log("🚀 ~ init ~ record:", record)
queryParam.orgCode = record.orgCode;
reload();
}
defineExpose({
init,
});
</script>
<style lang="less" scoped>
</style>

View File

@ -1,12 +1,12 @@
<template>
<j-modal :title="title" width="70%" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
<ApiLogAlarmList ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></ApiLogAlarmList>
<SelectNuList ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></SelectNuList>
</j-modal>
</template>
<script lang="ts" setup>
import { ref, nextTick, defineExpose } from 'vue';
import ApiLogAlarmList from './ApiLogAlarmList.vue'
import SelectNuList from './SelectNuList.vue'
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
const title = ref<string>('');
@ -14,16 +14,17 @@
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();
const emit = defineEmits(['register', 'success']);
const emit = defineEmits(['register', 'success','cancel']);
const type = ref<string>('');
/**
* 日志
* @param record
*/
function showLogAlarm(record) {
title.value = '日志';
function showNuList(record,_type) {
title.value = '选择区域';
visible.value = true;
type.value = _type;
nextTick(() => {
registerForm.value.init(record);
});
@ -40,7 +41,8 @@
* form保存回调事件
*/
function submitCallback(params) {
handleCancel();
params.type = type.value;
visible.value = false;
emit('success',params);
}
@ -48,11 +50,13 @@
* 取消按钮回调事件
*/
function handleCancel() {
let params = {'type':type.value};
visible.value = false;
emit('cancel',params);
}
defineExpose({
showLogAlarm,
showNuList,
disableSubmit,
});
</script>

View File

@ -0,0 +1,147 @@
<template>
<div class="p-2">
<BasicTable ref="tableRef" @register="registerTable" :scroll="{ y: '56vh' }" size="small">
<template #tableTitle></template>
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
</BasicTable>
</div>
</template>
<script lang="ts" name="tplink-camera-selectedTable" setup>
import { ref, reactive, watch,computed } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { selectedColumns } from '../camera.data';
const props = defineProps({
queryParams: {
type: Object,
default: () => ({})
},
dataSource: { //
type: Array,
default: () => []
},
});
const emit = defineEmits(['select-change']);
const queryParam = reactive<any>({});
const tableRef = ref();
const selectedRowIds = ref<Set<string | number>>(new Set());
const allSelectedRows = ref<any[]>([]);
watch(() => props.dataSource, (newParams) => {
// console.log(props.dataSource);
// reload();
// 使
tableRef.value?.setTableData(newParams);
}, { deep: true });
//
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '已选择数据表',
columns:selectedColumns,
size: 'small',
showTableSetting: false,
canResize: false,
useSearchForm: false,
showIndexColumn: true,
rowSelection: {type:'checkbox'},
rowKey: 'id',
actionColumn: {
width: 100,
fixed: 'right',
},
beforeFetch: async (params) => {
Object.assign(params, props.queryParams);
return params;
},
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection,selectedRows, selectedRowKeys }] = tableContext;
function getTableAction(record) {
return [
{
label: '取消',
color: 'error',
onClick: () => {
removeSelected(record);
}
}
];
}
//
const removeSelected = (record) => {
emit('removeSelect',record);
};
function reloadData(){
reload();
}
//
defineExpose({
reloadData,
allSelectedRows,
});
</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;
}
:deep(.ant-table-title) {
display: none !important;
}
:deep(.selected-row) {
background-color: #e6f7ff !important;
&:hover td {
background-color: #e6f7ff !important;
}
}
</style>

View File

@ -0,0 +1,209 @@
<template>
<div class="p-2">
<BasicTable ref="tableRef" @register="registerTable" :scroll="{ y: '56vh' }" :rowSelection="rowSelection" :rowClassName="getRowClassName" @selection-change="handleSelectionChange" size="small">
<template #tableTitle></template>
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
</BasicTable>
</div>
</template>
<script lang="ts" name="tplink-camera-sourceTable" setup>
import { ref, reactive, watch,computed } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { selectedSourceColumns,unselectedSourceColumns } from '../camera.data';
import { sourceListApi } from '../camera.api';
const props = defineProps({
queryParams: {
type: Object,
default: () => ({})
},
});
const emit = defineEmits(['select-change']);
const queryParam = reactive<any>({});
const tableRef = ref();
const selectedRowIds = ref<Set<string | number>>(new Set());
const allSelectedRows = ref<any[]>([]);
//
const getRowClassName = (record) => {
return selectedRowIds.value.has(record.deviceIndex) ? 'selected-row' : '';
};
watch(() => props.queryParams, (newParams) => {
reload();
}, { deep: true });
const tableColumns = computed(() => {
return props.queryParams.viewType === 'selected' ? selectedSourceColumns : unselectedSourceColumns;
});
//
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '设备源表',
api: sourceListApi,
columns:tableColumns,
size: 'small',
showTableSetting: false,
canResize: false,
useSearchForm: false,
showIndexColumn: true,
rowSelection: {type:'checkbox'},
rowKey: 'id',
actionColumn: {
width: 100,
fixed: 'right',
},
beforeFetch: async (params) => {
Object.assign(params, props.queryParams);
params.column = 'createTime'
params.order = 'desc'
params.selectedRowIds = Array.from(selectedRowIds.value)
return params;
},
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection,selectedRows, selectedRowKeys }] = tableContext;
function getTableAction(record) {
const actions = [];
if (selectedRowIds.value.has(record.deviceIndex)) {
actions.push({
label: '取消',
color: 'error',
onClick: () => {
removeSelected(record);
}
});
} else {
let label = '添加';
if(record.nuId){
label = '变更';
}
actions.push({
label: label,
onClick: () => {
toggleSelect(record);
}
});
}
return actions;
}
function handleSelectionChange(selectedRowSet) {
// console.log(':', selectedRowSet);
allSelectedRows.value = selectedRowSet.rows;
selectedRowKeys.value = selectedRowSet.keys;
}
//
function clearSelected(){
// console.log('');
selectedRowKeys.value = [];
allSelectedRows.value = [];
}
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
//
const toggleSelect = (record) => {
if (!selectedRowIds.value.has(record.deviceIndex)) {
selectedRowIds.value.add(record.deviceIndex);
}
allSelectedRows.value = [];
allSelectedRows.value.push(record);
emit('addSelect');
};
//
const removeSelected = (record) => {
selectedRowIds.value.delete(record.deviceIndex);
emit('removeSelect',record);
};
const updateSelection = (selectedRecords) => {
selectedRowIds.value.clear();
selectedRecords.forEach((value, key) => {
selectedRowIds.value.add(key);
});
//
if (registerTable) {
registerTable.toggleRowSelection?.(Array.from(selectedRowIds.value), true);
}
};
function reloadData(){
reload();
}
//
defineExpose({
updateSelection,
clearSelected,
reloadData,
allSelectedRows,
});
</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;
}
//:deep(.ant-table-title) {
// display: none !important;
//}
:deep(.selected-row) {
background-color: #e6f7ff !important;
&:hover td {
background-color: #e6f7ff !important;
}
}
</style>

View File

@ -0,0 +1,125 @@
<template>
<div class="p-2">
<!--引用表格-->
<BasicTable @register="registerTable">
<!--插槽:table标题-->
<template #tableTitle>
</template>
<template #expandedRowRender="{ record, index, indent, expanded }">
<a-table :columns="asyncSeedColumns" :data-source="record.seedList" :pagination="false" bordered
class="z-table-class" size="small">
<template #bodyCell="{ column }">
</template>
</a-table>
</template>
</BasicTable>
</div>
</template>
<script lang="ts" name="tplink-camera-asyncMain" setup>
import { ref, reactive } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import {asyncMaincolumns, asyncSeedColumns, logFormSchema} from '../camera.data';
import { syncLogListApi } from '../camera.api';
import AsyncMainModal from './components/AsyncMainModal.vue'
const props = defineProps({
orgCode: 'orgCode',
});
const queryParam = reactive<any>({});
//table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '数据同步日志主表',
api: syncLogListApi,
columns: asyncMaincolumns,
formConfig: {
schemas: logFormSchema
},
canResize: false,
useSearchForm: true,
showTableSetting: false,
showActionColumn: false,
beforeFetch: async (params) => {
queryParam.departServerUrl = props.orgCode
return Object.assign(params, queryParam);
},
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = tableContext;
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 查询
*/
function searchQuery() {
reload();
}
defineExpose({
searchQuery
});
</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%;
}
}
:deep(.ant-table-title) {
display: none !important;
}
:deep(.darkened-table) {
.ant-table-thead>tr>th {
background-color: #dadadaee;
}
.ant-table-tbody>tr>td {
background-color: #f3f3f3f5;
}
}
:deep(.z-table-class) {
.ant-table-thead>tr>th {
background-color: #e6f0fd;
}
.ant-table-tbody>tr>td {
background-color: #FBFBFB;
}
}
</style>

View File

@ -0,0 +1,568 @@
<template>
<OrgSelectComponent ref="orgSelectComRef" @orgChanged="orgChanged" @orgReset="orgReset"></OrgSelectComponent>
<div class="p-2 base-class" style="margin-top: -0.5rem;" v-if="showDevices">
<!-- <div class="p-2 base-class" style="margin-top: -0.5rem;">-->
<a-card class="container" v-show="toggleSearchStatus && tabActiveKey == 'dataAsync'" >
<a-form ref="formRef" @keyup.enter.native="searchQuery" :model="queryParam" :label-col="labelCol"
:wrapper-col="wrapperCol">
<a-row :gutter="24">
<a-col :span="4">
<a-form-item name="dataType">
<template #label><span title="dataType">操作源</span></template>
<a-select v-model:value="dataType" placeholder="请选择来源" allowClear @change="dataTypeChanged(dataType)">
<a-select-option value="source" key="source">源数据</a-select-option>
<a-select-option value="business" key="business">已同步</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="4">
<a-form-item name="sn">
<template #label><span title="SN">SN</span></template>
<a-input v-model:value="queryParam.deviceIndex" placeholder="请输入SN" allowClear />
</a-form-item>
</a-col>
<a-col :span="4" v-show="viewType =='selected'||dataType=='business'">
<a-form-item name="departId">
<template #label><span title="机构">机构</span></template>
<a-select v-model:value="queryParam.departId" placeholder="请选择机构" allowClear @change="handleDepartChange">
<a-select-option :value="item.departId" v-for="item in departList" :key="item.departId">{{item.departName}}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="4" v-show="viewType =='selected'||dataType=='business'">
<a-form-item name="nuId">
<template #label><span title="区域">区域</span></template>
<a-select v-model:value="queryParam.nuId" placeholder="请选择区域" allowClear>
<a-select-option :value="item.nuId" v-for="item in nuList" :key="item.nuId">{{item.nuName}}</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="4" v-show="viewType =='selected'||dataType=='business'">
<a-form-item name="status">
<template #label><span title="状态">状态</span></template>
<a-select v-model:value="queryParam.status" placeholder="请选择状态" allowClear>
<a-select-option value="0" key="0">正常</a-select-option>
<a-select-option value="1" key="1">作废</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="4">
<span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
<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>
</span>
</a-col>
</a-row>
</a-form>
</a-card>
<a-card class="container">
<div class="tab-header-container" v-if="showDevices">
<!-- <div class="tab-header-container">-->
<a-tabs v-model:activeKey="tabActiveKey" class="tabs-container">
<a-tab-pane key="dataAsync" tab="数据同步">
<a-card>
<a-row>
<a-col :span="sourceScreenSpan">
<div style="height: 16px;margin-left: 15px">
<a-tag color="#2DB7F5">源数据</a-tag>
<a-radio-group v-model:value="viewType" size="small" style="margin-left: 10px;" @change="viewTypeChanged(viewType)">
<a-radio-button value="unselected">未选择</a-radio-button>
<a-radio-button value="selected">已选择</a-radio-button>
</a-radio-group>
<div class="toggle-add-button-container">
<a-button type="primary" size="small" @click="handleAddSourceSelect"
style="margin-left: 8px">{{sourceButtonText}}</a-button>
</div>
</div>
<SourceTable ref="sourceComRef" :queryParams="sourceParam" @addSelect="handleAddSourceSelect" @removeSelect="handleRemoveSourceSelect"/>
</a-col>
<a-col :span="selectedScreenSpan">
<div style="height: 16px;margin-left: 15px">
<a-tag color="#2db7f5">待同步
<span style="font-size: 13px;font-weight: bold;">{{ ' ' + Array.from(allSelectedItems.values()).length + ' ' }}</span>
</a-tag>
<a-radio-group v-model:value="businessView" size="small" style="margin-left: 10px;">
<a-radio-button value="unselected">待同步</a-radio-button>
<a-radio-button value="selected">已同步</a-radio-button>
</a-radio-group>
<div class="toggle-add-button-container" v-show="businessView=='selected'">
<a-button type="primary" size="small" @click="handleEditBusinessSelect" style="margin-left: 8px">调整</a-button>
<a-button type="primary" size="small" @click="handleDeleteBusinessSelect" style="margin-left: 8px">移除</a-button>
</div>
</div>
<SelectedTable v-show="businessView=='unselected'" ref="selectedComRef" :dataSource="Array.from(allSelectedItems.values())" @removeSelect="handleRemoveSelect"/>
<BusinessTable v-show="businessView=='selected'" ref="businessComRef" :queryParams="businessParam" @editSelect="handleEditBusinessSelect" @deleteSelect="handleDeleteBusinessSelect" @removeSelect="handleRemoveBusinessSelect"/>
</a-col>
</a-row>
</a-card>
</a-tab-pane>
<a-tab-pane key="syncLogList" tab="同步历史">
<SyncLogList ref="syncLogListRef" :orgCode="orgData.orgCode"></SyncLogList>
</a-tab-pane>
</a-tabs>
<div class="toggle-button-container">
<a-button type="primary" size="small" @click.stop="refreshHistory()" style="margin-right: 10px;"
v-show="tabActiveKey == 'syncLogList'">
<span>刷新</span>
</a-button>
<a-button type="warning" size="small" @click.stop="handleAsync()"
style="margin-left: 5px;margin-right: 5px;" v-show="tabActiveKey == 'dataAsync'">
<span>同步</span>
</a-button>
<a-divider type="vertical" style="background-color: #CDCDCF"
v-show="tabActiveKey == 'dataAsync'" />
<a-button type="primary" size="small" @click.stop="handleReload"
v-show="tabActiveKey == 'dataAsync'" style="margin-left: 8px">还原</a-button>
<a-divider type="vertical" style="background-color: #CDCDCF"
v-show="tabActiveKey == 'dataAsync'" />
<a-radio-group v-model:value="splitVal" button-style="solid" size="small"
@change="splitScreenChanged" style="margin-left: 5px;margin-right: 5px;"
v-show="tabActiveKey == 'dataAsync'">
<a-radio-button value="sc">源数据</a-radio-button>
<a-radio-button value="sc2sed1">分屏1</a-radio-button>
<a-radio-button value="sc1sed1">分屏2</a-radio-button>
<a-radio-button value="sc1sed2">分屏3</a-radio-button>
<a-radio-button value="sed">已选择</a-radio-button>
</a-radio-group>
<a-divider type="vertical" style="background-color: #CDCDCF" v-show="tabActiveKey == 'dataAsync'" />
<a @click="toggleSearchStatus = !toggleSearchStatus" class="toggle-button" v-show="tabActiveKey == 'dataAsync'"
style="margin-left: 5px;margin-right: 5px;">
{{ toggleSearchStatus ? '收缩' : '展开' }}
<Icon :icon="toggleSearchStatus ? 'humbleicons:align-objects-top' : 'humbleicons:align-objects-bottom'" />
</a>
</div>
</div>
</a-card>
</div>
<SelectNuModal ref="selectNuModal" @success="selectNuHandleSuccess" @cancel="selectNuHandleCancel"></SelectNuModal>
</template>
<script setup name="tq-camera-index" lang="ts">
import {ref, reactive, onMounted, watch} from 'vue'
import OrgSelectComponent from '../../components/OrgSelect.vue'
import SourceTable from './components/SourceTable.vue'
import SelectedTable from './components/SelectedTable.vue'
import BusinessTable from './components/BusinessTable.vue'
import SelectNuModal from './components/SelectNuModal.vue'
import SyncLogList from './components/SyncLogList.vue'
import { useMessage } from "/@/hooks/web/useMessage";
import JInput from "/@/components/Form/src/jeecg/components/JInput.vue";
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
import {departListApi, nuListApi, syncDevicesApi} from './camera.api';
import {selectedColumns} from './camera.data';
const { createMessage } = useMessage();
const orgSelectComRef = ref(null);
const showDevices = ref(false);
const selectNuModal = ref();
const labelCol = reactive({
xs: 24,
sm: 4,
xl: 6,
xxl: 5
});
const wrapperCol = reactive({
xs: 24,
sm: 20,
});
const queryParam = ref({status: '0'})//
const sourceParam = ref({viewType: 'unselected',departServerUrl:'',status: '0'})//
const businessParam = ref({departServerUrl:'',status: '0'})//
const sourceComRef = ref();
const selectedComRef = ref();
const businessComRef = ref();
const syncLogListRef = ref();
const toggleSearchStatus = ref<boolean>(true);
const tabActiveKey = ref('dataAsync');
const sourceScreenSpan = ref(12);
const selectedScreenSpan = ref(12);
const sourceButtonText = ref('添加');
//
const dataType = ref('source');
const viewType = ref('unselected');
const businessView = ref('unselected');
const splitVal = ref<string>('sc1sed1');
const orgData = ref();
const allSelectedItems = ref<Map<string | number, any>>(new Map());
const selectedItems = ref([]);//
/**
* 机构变更
*/
const orgChanged = async (org) => {
orgData.value = org;
dataType.value = 'source';
viewType.value = 'unselected';
businessView.value = 'unselected';
tabActiveKey.value = 'dataAsync';
//
allSelectedItems.value.clear();
//
queryParam.value = {status: '0'};
//
sourceParam.value = { viewType: 'unselected',departServerUrl:org.orgCode,status: '0'};
//
businessParam.value = {departServerUrl: org.orgCode};
//
orgSelectComRef?.value?.resetOrgSelectedCon(false);
showDevices.value = true;
toggleSearchStatus.value = true;
}
/**
* 机构变更
*/
const orgReset = async (org) => {
showDevices.value = false;
}
/**
* 查询
*/
function searchQuery() {
if(dataType.value=='source'){
sourceParam.value.deviceIndex = queryParam.value.deviceIndex;
sourceParam.value.departId = queryParam.value.departId;
sourceParam.value.nuId = queryParam.value.nuId;
sourceParam.value.status = queryParam.value.status;
sourceComRef.value.reloadData();
}else{
businessParam.value.deviceIndex = queryParam.value.deviceIndex;
businessParam.value.departId = queryParam.value.departId;
businessParam.value.nuId = queryParam.value.nuId;
businessParam.value.status = queryParam.value.status;
businessComRef.value.reloadData();
}
}
function searchReset() {
queryParam.value = {
status: '0'
};
if(dataType.value=='source'){
let vt = sourceParam.value.viewType;
let dsu = sourceParam.value.departServerUrl;
sourceParam.value = { viewType: vt,departServerUrl:dsu,status: '0' };
}else{
let dsu = businessParam.value.departServerUrl;
businessParam.value = { departServerUrl: dsu,status: '0' };
}
}
const splitScreenChanged = (val) => {
let v_ = val.target.value;
if (v_ == 'sc') {
sourceScreenSpan.value = 24;
selectedScreenSpan.value = 0;
}
if (v_ == 'sc2sed1') {
sourceScreenSpan.value = 16;
selectedScreenSpan.value = 8;
}
if (v_ == 'sc1sed1') {
sourceScreenSpan.value = 12;
selectedScreenSpan.value = 12;
}
if (v_ == 'sc1sed2') {
sourceScreenSpan.value = 8;
selectedScreenSpan.value = 16;
}
if (v_ == 'sed') {
sourceScreenSpan.value = 0;
selectedScreenSpan.value = 24;
}
};
const dataTypeChanged = (value) => {
if(value=='source'){
if(viewType.value=='selected'){
sourceButtonText.value = '变更';
const departServerUrl = sourceParam.value.departServerUrl;
getDepartList({dataType:'source',departServerUrl:departServerUrl});
getNuList({dataType:'source',departServerUrl:departServerUrl});
}else{
sourceButtonText.value = '添加';
}
}else{
const departServerUrl = businessParam.value.departServerUrl;
getDepartList({dataType:'business',departServerUrl:departServerUrl});
getNuList({dataType:'business',departServerUrl:departServerUrl});
}
}
const viewTypeChanged = (value) => {
sourceButtonText.value = '添加';
sourceParam.value.viewType = value
if(value=='selected'){
const departServerUrl = sourceParam.value.departServerUrl;
sourceButtonText.value = '变更';
getDepartList({dataType:'source',departServerUrl:departServerUrl});
getNuList({dataType:'source',departServerUrl:departServerUrl});
}
}
const departList = ref();
async function getDepartList(record){
departList.value = await departListApi(record);
}
const nuList = ref();
async function getNuList(record){
nuList.value = await nuListApi(record);
}
async function handleDepartChange(record){
let params = {departId:record,dataType:'',departServerUrl:''};
if(dataType.value=='source'){
params.dataType = 'source';
params.departServerUrl = sourceParam.value.departServerUrl;
}else{
params.dataType = 'business';
params.departServerUrl = businessParam.value.departServerUrl;
}
nuList.value = await nuListApi(params);
}
const handleRemoveFromRight = (key: string | number) => {
selectedItems.value.delete(key);
sourceComRef.value?.removeSelectedItem?.(key);
};
function handleAddSourceSelect(){
const allSelectedRows = sourceComRef.value.allSelectedRows;
if (allSelectedRows && allSelectedRows.length > 0) {
selectNuModal.value.disableSubmit = true;
selectNuModal.value.showNuList(orgData.value,'source');
}else{
createMessage.warning('请先选择源数据');
}
}
function handleEditBusinessSelect(){
const allSelectedRows = businessComRef.value.allSelectedRows;
if (allSelectedRows && allSelectedRows.length > 0) {
selectNuModal.value.disableSubmit = true;
selectNuModal.value.showNuList(orgData.value,'business');
}else{
createMessage.warning('请先选择已同步数据');
}
}
function handleDeleteBusinessSelect(){
const businessSelectedRows = businessComRef.value.allSelectedRows;
if (businessSelectedRows && businessSelectedRows.length > 0) {
businessSelectedRows.forEach(record => {
if (allSelectedItems.value.has(record.deviceIndex)) {
allSelectedItems.value.delete(record.deviceIndex);
}
let item = {};
item["deviceIndex"] = record.deviceIndex;
item["deviceName"] = record.deviceName;
item["mac"] = record.mac;
item["actionType"] = '删除';
item["dataType"] = 'business';
item["dataTypeText"] = '已同步区';
item["nuId"] = record.nuId;
item["nuName"] = record.nuName;
item["areaFlag_dictText"] = record.areaFlag_dictText;
item["orgCode"] = '';
item["departId"] = '';
item["departName"] = '';
item["oldOrgCode"] = record.departServerUrl;
item["oldDepartId"] = record.departId;
item["oldDepartName"] = record.departName;
allSelectedItems.value.set(record.deviceIndex, item);
});
updateBusinessSelection();
}
}
function handleRemoveSourceSelect(record){
if (allSelectedItems.value.has(record.deviceIndex)) {
allSelectedItems.value.delete(record.deviceIndex);
}
updateSourceSelection();
}
function handleRemoveBusinessSelect(record){
if (allSelectedItems.value.has(record.deviceIndex)) {
allSelectedItems.value.delete(record.deviceIndex);
}
updateBusinessSelection();
}
function handleRemoveSelect(record){
if (allSelectedItems.value.has(record.deviceIndex)) {
allSelectedItems.value.delete(record.deviceIndex);
}
if(record.dataType == 'source'){
updateSourceSelection();
}
if(record.dataType == 'business'){
updateBusinessSelection();
}
}
function selectNuHandleSuccess(nuInfo){
if(nuInfo.type == 'source'){
const sourceSelectedRows = sourceComRef.value.allSelectedRows;
if (sourceSelectedRows && sourceSelectedRows.length > 0) {
sourceSelectedRows.forEach(record => {
if (allSelectedItems.value.has(record.deviceIndex)) {
allSelectedItems.value.delete(record.deviceIndex);
}
let item = {};
item["deviceIndex"] = record.deviceIndex;
item["deviceName"] = record.deviceName;
item["mac"] = record.mac;
item["actionType"] = sourceButtonText.value;
item["dataType"] = 'source';
item["dataTypeText"] = '源数据区';
item["nuId"] = nuInfo.nuId;
item["nuName"] = nuInfo.nuName;
item["areaFlag_dictText"] = nuInfo.areaFlag_dictText;
item["orgCode"] = orgData.value.orgCode;
item["departId"] = orgData.value.orgId;
item["departName"] = orgData.value.departName;
item["oldOrgCode"] = record.departServerUrl;
item["oldDepartId"] = record.departId;
item["oldDepartName"] = record.departName;
allSelectedItems.value.set(record.deviceIndex, item);
});
updateSourceSelection();
}
}else{
const businessSelectedRows = businessComRef.value.allSelectedRows;
if (businessSelectedRows && businessSelectedRows.length > 0) {
businessSelectedRows.forEach(record => {
if (allSelectedItems.value.has(record.deviceIndex)) {
allSelectedItems.value.delete(record.deviceIndex);
}
let item = {};
item["deviceIndex"] = record.deviceIndex;
item["deviceName"] = record.deviceName;
item["mac"] = record.mac;
item["actionType"] = '调整';
item["dataType"] = 'business';
item["dataTypeText"] = '已同步区';
item["nuId"] = nuInfo.nuId;
item["nuName"] = nuInfo.nuName;
item["areaFlag_dictText"] = nuInfo.areaFlag_dictText;
item["orgCode"] = orgData.value.orgCode;
item["departId"] = orgData.value.orgId;
item["departName"] = orgData.value.departName;
item["oldOrgCode"] = record.departServerUrl;
item["oldDepartId"] = record.departId;
item["oldDepartName"] = record.departName;
allSelectedItems.value.set(record.deviceIndex, item);
});
updateBusinessSelection();
}
}
}
function selectNuHandleCancel(nuInfo){
if(nuInfo.type == 'source'){
updateSourceSelection();
}else{
updateBusinessSelection();
}
}
//
function updateSourceSelection(){
//
sourceComRef.value.clearSelected();
//
sourceComRef.value?.updateSelection?.(allSelectedItems.value);
}
//
function updateBusinessSelection(){
//
businessComRef.value.clearSelected();
//
businessComRef.value?.updateSelection?.(allSelectedItems.value);
}
//
function handleReload(){
allSelectedItems.value.clear();
updateSourceSelection();
updateBusinessSelection();
}
//
async function handleAsync(){
const arr = Array.from(allSelectedItems.value.values())
await syncDevicesApi(arr);
sourceComRef.value.reloadData();
businessComRef.value.reloadData();
handleReload();
}
//
const refreshHistory = () => {
syncLogListRef.value?.searchQuery()
}
</script>
<style lang="less" scoped>
.container {
max-width: 100% !important;
margin-bottom: 10px;
}
.ant-form-item{
margin-bottom: 0px;
}
.base-class {
:deep(.ant-card .ant-card-body) {
padding-top: 10px !important;
padding-bottom: 10px !important;
}
}
.tabs-container {
width: 100%;
:deep(.ant-tabs-content) {
height: calc(100% - 40px); // tab
overflow: auto;
}
}
.selected-list-container {
height: calc(100vh - 310px);
overflow: auto;
:deep(.ant-table) {
width: 100% !important;
max-width: 100%;
}
}
.toggle-add-button-container {
position: absolute;
right: 16px;
top: 0px;
z-index: 1;
}
.toggle-button-container {
position: absolute;
right: 16px;
top: 16px;
z-index: 1;
}
</style>

View File

@ -0,0 +1,214 @@
<template>
<div class="p-2">
<BasicTable ref="tableRef" @register="registerTable" :scroll="{ y: '56vh' }" :rowSelection="rowSelection" :rowClassName="getRowClassName" @selection-change="handleSelectionChange" size="small">
<template #tableTitle></template>
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
</BasicTable>
</div>
</template>
<script lang="ts" name="tq-electricity-businessTable" setup>
import { ref, reactive, watch,computed } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { businessColumns } from '../electricity.data';
import { businessListApi } from '../electricity.api';
const props = defineProps({
queryParams: {
type: Object,
default: () => ({})
},
});
const emit = defineEmits(['select-change']);
const queryParam = reactive<any>({});
const tableRef = ref();
const selectedRowIds = ref<Set<string | number>>(new Set());
const allSelectedRows = ref<any[]>([]);
//
const getRowClassName = (record) => {
return selectedRowIds.value.has(record.address) ? 'selected-row' : '';
};
watch(() => props.queryParams, (newParams) => {
reload();
}, { deep: true });
//
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '已同步设备表',
api: businessListApi,
columns:businessColumns,
size: 'small',
showTableSetting: false,
canResize: false,
useSearchForm: false,
showIndexColumn: true,
rowSelection: {type:'checkbox'},
rowKey: 'id',
actionColumn: {
width: 120,
fixed: 'right',
},
beforeFetch: async (params) => {
Object.assign(params, props.queryParams);
params.selectedRowIds = Array.from(selectedRowIds.value)
return params;
},
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection,selectedRows, selectedRowKeys }] = tableContext;
function getTableAction(record) {
const actions = [];
if (selectedRowIds.value.has(record.address)) {
actions.push({
label: '取消',
color: 'error',
onClick: () => {
removeSelected(record);
}
});
} else {
actions.push({
label: '变更',
onClick: () => {
toggleSelect(record);
}
});
actions.push({
label: '移除',
onClick: () => {
deleteSelect(record);
}
});
}
return actions;
}
function handleSelectionChange(selectedRowSet) {
// console.log(':', selectedRowSet);
allSelectedRows.value = selectedRowSet.rows;
selectedRowKeys.value = selectedRowSet.keys;
}
//
function clearSelected(){
// console.log('');
selectedRowKeys.value = [];
allSelectedRows.value = [];
}
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
//
const toggleSelect = (record) => {
if (!selectedRowIds.value.has(record.address)) {
selectedRowIds.value.add(record.address);
}
allSelectedRows.value = [];
allSelectedRows.value.push(record);
emit('editSelect');
};
//
const deleteSelect = (record) => {
if (!selectedRowIds.value.has(record.address)) {
selectedRowIds.value.add(record.address);
}
allSelectedRows.value = [];
allSelectedRows.value.push(record);
emit('deleteSelect');
};
//
const removeSelected = (record) => {
selectedRowIds.value.delete(record.address);
emit('removeSelect',record);
};
const updateSelection = (selectedRecords) => {
selectedRowIds.value.clear();
selectedRecords.forEach((value, key) => {
selectedRowIds.value.add(key);
});
//
if (registerTable) {
registerTable.toggleRowSelection?.(Array.from(selectedRowIds.value), true);
}
};
function reloadData(){
reload();
}
//
defineExpose({
updateSelection,
clearSelected,
reloadData,
allSelectedRows,
});
</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;
}
//:deep(.ant-table-title) {
// display: none !important;
//}
:deep(.selected-row) {
background-color: #e6f7ff !important;
&:hover td {
background-color: #e6f7ff !important;
}
}
</style>

View File

@ -0,0 +1,123 @@
<template>
<!--引用表格-->
<BasicTable @register="registerTable">
<!--插槽:table标题-->
<template #tableTitle></template>
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" />
</template>
</BasicTable>
</template>
<script lang="ts" name="tq-electricity-apiLogList" setup>
import { ref, reactive } from 'vue';
import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import {nuFormSchema, nusColumns} from '../electricity.data';
import {nuSyncListApi} from '../electricity.api';
import { useUserStore } from '/@/store/modules/user';
const emit = defineEmits(['register', 'success']);
// const props = defineProps({
// orgCode: '',
// });
const formRef = ref();
const queryParam = reactive<any>({});
const toggleSearchStatus = ref<boolean>(false);
const registerModal = ref();
const userStore = useUserStore();
//table
const { prefixCls, tableContext } = useListPage({
tableProps: {
title: '区域列表',
api: nuSyncListApi,
columns:nusColumns,
canResize:false,
showActionColumn: true,
showTableSetting: false,
showIndexColumn: true,
formConfig: {
//labelWidth: 120,
schemas: nuFormSchema,
autoSubmitOnEnter:false,
showAdvancedButton:false,
fieldMapToNumber: [
],
fieldMapToTime: [
],
},
actionColumn: {
width: 120,
fixed: 'right',
},
beforeFetch: async (params) => {
// queryParam.orgCode = props.orgCode //
return Object.assign(params, queryParam);
},
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = tableContext;
const labelCol = reactive({
xs:24,
sm:8,
xl:6,
xxl:8
});
const wrapperCol = reactive({
xs: 24,
sm: 16,
});
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
}
/**
* 查询
*/
function searchQuery() {
reload();
}
/**
* 重置
*/
function searchReset() {
formRef.value.resetFields();
selectedRowKeys.value = [];
//
reload();
}
//
async function handleSelectNu(record: Recordable) {
// console.log(record);
emit('ok',record);
}
function getTableAction(record) {
return [
{
label: '选择',
onClick: handleSelectNu.bind(null, record)
}
]
}
function init(record,type) {
// console.log("🚀 ~ init ~ record:", record)
queryParam.orgCode = record.orgCode;
reload();
}
defineExpose({
init,
});
</script>
<style lang="less" scoped>
</style>

Some files were not shown because too many files have changed in this diff Show More