Commit c0f86739dbb0f325f3049ae03ff675485c37c7ac

Authored by xp.Huang
2 parents cbad8dae 20bfc66f

Merge branch 'f-dev' into 'main'

fix:修改报表配置相关

See merge request huang/yun-teng-iot-front!278
1 1 <template>
2   - <BasicDrawer :maskClosable="false" @close="handleClose" destroyOnClose v-bind="$attrs" @register="registerDrawer"
3   - showFooter :title="getTitle" width="30%" @ok="handleSubmit">
  2 + <BasicDrawer
  3 + :maskClosable="false"
  4 + @close="handleClose"
  5 + destroyOnClose
  6 + v-bind="$attrs"
  7 + @register="registerDrawer"
  8 + showFooter
  9 + :title="getTitle"
  10 + width="30%"
  11 + @ok="handleSubmit"
  12 + >
4 13 <BasicForm @register="registerForm">
5   - <template #devices>
6   - <Select placeholder="请选择设备" v-model:value="selectDevice" style="width: 100%" :options="selectOptions"
7   - @change="handleDeviceChange" mode="multiple" labelInValue allowClear notFoundContent="请选择设备" />
  14 + <template #devices="{ model, field }">
  15 + <p style="display: none">{{ field }}</p>
  16 + <p>{{ orgFunc(model['organizationId']) }}</p>
  17 + <Select
  18 + placeholder="请选择设备"
  19 + v-model:value="selectDevice"
  20 + style="width: 100%"
  21 + :options="selectOptions"
  22 + @change="handleDeviceChange"
  23 + @deselect="handleDeselect"
  24 + mode="multiple"
  25 + labelInValue
  26 + allowClear
  27 + notFoundContent="请选择设备"
  28 + />
8 29 <div style="margin-top: 1.5vh"></div>
9   - <DeviceAttrCpns ref="deviceAttrRef" @change="handleChange" :value="deviceList"
10   - :orgId="organizationId || orgId" />
  30 + <template v-for="(item, index) in deviceList" :key="item.value">
  31 + <p style="display: none">{{ index }}</p>
  32 + <DeviceAttrCpns
  33 + :ref="bindDeviceRefObj.deviceAttrRef"
  34 + :value="item"
  35 + :orgId="organizationId || orgId"
  36 + />
  37 + </template>
11 38 </template>
12 39 </BasicForm>
13 40 </BasicDrawer>
14 41 </template>
15 42 <script lang="ts" setup>
16   -import { ref, computed, unref, reactive, watch, Ref } from 'vue';
17   -import { BasicForm, useForm } from '/@/components/Form';
18   -import { formSchema, organizationId } from './config.data';
19   -import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
20   -import { createOrEditReportManage, putReportConfigManage, reportEditDetailPage } from '/@/api/report/reportManager';
21   -import { useMessage } from '/@/hooks/web/useMessage';
22   -import moment from 'moment';
23   -import { screenLinkPageByDeptIdGetDevice } from '/@/api/ruleengine/ruleengineApi';
24   -import { Select } from 'ant-design-vue';
25   -import DeviceAttrCpns from './cpns/DeviceAttrCpns.vue';
26   -import { SelectTypes } from 'ant-design-vue/es/select';
27   -import { SchemaFiled } from './config.data';
28   -import { QueryWay } from '../../device/localtion/cpns/TimePeriodForm/config';
29   -import { AggregateDataEnum } from '../../device/localtion/cpns/TimePeriodForm/config';
  43 + import { ref, computed, unref, reactive, watch, Ref } from 'vue';
  44 + import { BasicForm, useForm } from '/@/components/Form';
  45 + import { formSchema, organizationId } from './config.data';
  46 + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
  47 + import {
  48 + createOrEditReportManage,
  49 + putReportConfigManage,
  50 + reportEditDetailPage,
  51 + } from '/@/api/report/reportManager';
  52 + import { useMessage } from '/@/hooks/web/useMessage';
  53 + import moment from 'moment';
  54 + import { screenLinkPageByDeptIdGetDevice } from '/@/api/ruleengine/ruleengineApi';
  55 + import { Select } from 'ant-design-vue';
  56 + import DeviceAttrCpns from './cpns/DeviceAttrCpns.vue';
  57 + import { SelectTypes } from 'ant-design-vue/es/select';
  58 + import { SchemaFiled } from './config.data';
  59 + import { QueryWay } from '../../device/localtion/cpns/TimePeriodForm/config';
  60 + import { AggregateDataEnum } from '../../device/localtion/cpns/TimePeriodForm/config';
30 61
31   -type TDeviceList = {
32   - key?: string,
33   - value?: string,
34   - label?: string,
35   - attribute?: string,
36   - device?: string,
37   - name?: string
38   -}
39   -const emit = defineEmits(['success', 'register']);
40   -const deviceAttrRef = ref<InstanceType<typeof DeviceAttrCpns> | null>(null)
41   -const isUpdate = ref(true);
42   -const editId = ref('');
43   -const orgId = ref('');
44   -const selectOptions: Ref<SelectTypes['options']> = ref([]);
45   -const selectDevice = ref([]);
46   -const deviceList: Ref<TDeviceList[]> = ref([]);
47   -const editDeviceList: Ref<TDeviceList[]> = ref([]);
48   -let editResData: any = reactive({})
49   -const watchOrgId = ref('')
50   -const editDeviceAttr: any = ref([])
51   -
52   -watch(organizationId, async (newValue: string) => {
53   - if (!newValue) return;
54   - //获取设备
55   - watchOrgId.value = newValue
56   - const { items } = await screenLinkPageByDeptIdGetDevice({
57   - organizationId: newValue,
58   - });
59   - selectOptions.value = items.map((item) => {
60   - if (item.deviceType !== 'GATEWAY')
61   - return {
62   - label: item.name,
63   - value: item.tbDeviceId,
64   - };
65   - });
66   -});
67   -const handleDeviceChange = (e) => {
68   - console.log(e)
69   - deviceList.value = e;
70   -};
71   -const [registerForm, { validate, setFieldsValue, resetFields, updateSchema, getFieldsValue }] = useForm({
72   - labelWidth: 120,
73   - schemas: formSchema,
74   - showActionButtonGroup: false,
75   - fieldMapToTime: [[SchemaFiled.DATE_RANGE, [SchemaFiled.START_TS, SchemaFiled.END_TS]]],
76   -});
77   -const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
78   - await resetFields();
79   - setDrawerProps({ confirmLoading: false });
80   - isUpdate.value = !!data?.isUpdate;
81   - if (unref(isUpdate)) {
82   - //编辑回显数据
83   - editResData = await reportEditDetailPage(data.record.id)
84   - //回显基础数据
85   - editId.value = editResData.data.id;
86   - await setFieldsValue(editResData.data);
87   - //回显嵌套数据
88   - await setFieldsValue({
89   - agg: editResData.data.queryCondition?.agg,
90   - interval: editResData.data.queryCondition?.interval,
91   - limit1: editResData.data.queryCondition?.limit,
92   - orderBy: editResData.data.queryCondition?.orderBy,
93   - useStrictDataTypes: editResData.data.queryCondition?.useStrictDataTypes
94   - });
95   - //回显聚合条件
96   - const dataCompareOpions = [
97   - { label: '最小值', value: AggregateDataEnum.MIN },
98   - { label: '最大值', value: AggregateDataEnum.MAX },
99   - { label: '平均值', value: AggregateDataEnum.AVG },
100   - { label: '求和', value: AggregateDataEnum.SUM },
101   - { label: '空', value: AggregateDataEnum.NONE }
102   - ]
103   - const updateSchemaAgg = (options: {}) => {
104   - updateSchema({
105   - field: SchemaFiled.AGG,
106   - componentProps: {
107   - options,
108   - },
109   - });
  62 + type TDeviceList = {
  63 + key?: string;
  64 + value?: string;
  65 + label?: string;
  66 + attribute?: string;
  67 + device?: string;
  68 + name?: string;
  69 + };
  70 + const emit = defineEmits(['success', 'register']);
  71 + const bindDeviceRefObj = {
  72 + deviceAttrRef: ref([]),
  73 + };
  74 + const isUpdate = ref(true);
  75 + const editId = ref('');
  76 + const orgId = ref('');
  77 + const selectOptions: Ref<SelectTypes['options']> = ref([]);
  78 + const selectDevice = ref([]);
  79 + const deviceList: Ref<TDeviceList[]> = ref([]);
  80 + const editDeviceList: Ref<TDeviceList[]> = ref([]);
  81 + let editResData: any = reactive({});
  82 + const editDeviceAttr: any = ref([]);
  83 + const orgFuncId = ref('');
  84 + const orgFunc = (e) => {
  85 + orgFuncId.value = e;
  86 + };
  87 + watch(
  88 + () => orgFuncId.value,
  89 + async (newValue: string) => {
  90 + if (newValue) {
  91 + //获取设备
  92 + const { items } = await screenLinkPageByDeptIdGetDevice({
  93 + organizationId: newValue,
  94 + });
  95 + selectOptions.value = items.map((item) => {
  96 + if (item.deviceType !== 'GATEWAY')
  97 + return {
  98 + label: item.name,
  99 + value: item.tbDeviceId,
  100 + };
  101 + });
  102 + }
110 103 }
111   - if (editResData.data.dataType == 1) updateSchemaAgg(dataCompareOpions.slice(0, 4))
112   - else updateSchemaAgg(dataCompareOpions.slice(4, 5))
113   - //回显执行方式和查询周期
114   - const dataQueryOpions = [
115   - { label: '固定周期', value: QueryWay.LATEST },
116   - { label: '自定义周期', value: QueryWay.TIME_PERIOD },
117   - ];
118   - const updateSchemaQuery = (options: {}) => {
119   - updateSchema({
120   - field: SchemaFiled.WAY,
121   - componentProps: {
122   - options,
123   - },
  104 + );
  105 + //设备Select选中
  106 + const handleDeviceChange = (e) => {
  107 + if (unref(isUpdate)) {
  108 + editDeviceAttr.value.forEach((f) => {
  109 + deviceList.value = [f, ...e];
124 110 });
  111 + let deWeightThree = () => {
  112 + let map = new Map();
  113 + for (let item of deviceList.value) {
  114 + if (!map.has(item.value)) {
  115 + map.set(item.value, item);
  116 + }
  117 + }
  118 + return [...map.values()];
  119 + };
  120 + deviceList.value = deWeightThree();
  121 + } else {
  122 + deviceList.value = e;
  123 + }
  124 + };
  125 + //设备取消删除
  126 + const handleDeselect = (e) => {
  127 + if (unref(isUpdate)) {
  128 + const eEditDevice = e.key || e.value;
  129 + let deWeightThree = () => {
  130 + let map = new Map();
  131 + for (let item of deviceList.value) {
  132 + if (!map.has(item.value)) {
  133 + map.set(item.value, item);
  134 + }
  135 + }
  136 + return [...map.values()];
  137 + };
  138 + deviceList.value = deWeightThree();
  139 + const findEditValue = deviceList.value.findIndex((f) => f.value == eEditDevice);
  140 + if (findEditValue !== -1) deviceList.value.splice(findEditValue, 1);
  141 + } else {
  142 + const eDevice = e.key || e.value;
  143 + const findValue = deviceList.value.findIndex((f) => f.value == eDevice);
  144 + if (findValue !== -1) deviceList.value.splice(findValue, 1);
125 145 }
126   - if (editResData.data.executeWay == 0) updateSchemaQuery(dataQueryOpions)
127   - else updateSchemaQuery(dataQueryOpions.slice(0, 1))
128   - //回显设备
129   - orgId.value = editResData.data.organizationId;
130   - const { items } = await screenLinkPageByDeptIdGetDevice({
131   - organizationId: editResData.data.organizationId,
  146 + };
  147 + const [registerForm, { validate, setFieldsValue, resetFields, updateSchema, getFieldsValue }] =
  148 + useForm({
  149 + labelWidth: 120,
  150 + schemas: formSchema,
  151 + showActionButtonGroup: false,
  152 + fieldMapToTime: [[SchemaFiled.DATE_RANGE, [SchemaFiled.START_TS, SchemaFiled.END_TS]]],
132 153 });
133   - selectOptions.value = items.map((item) => {
134   - if (item.deviceType !== 'GATEWAY')
  154 + const isViewDetail = ref(false);
  155 +
  156 + const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
  157 + await resetFields();
  158 + setDrawerProps({ confirmLoading: false });
  159 + isUpdate.value = !!data?.isUpdate;
  160 + isViewDetail.value = !!data?.isView;
  161 + if (unref(isViewDetail)) {
  162 + setDrawerProps({ showFooter: true });
  163 + if (unref(isUpdate)) {
  164 + setDrawerProps({ title: '编辑报表配置' });
  165 + } else {
  166 + setDrawerProps({ title: '新增报表配置' });
  167 + }
  168 + } else {
  169 + setDrawerProps({ showFooter: false });
  170 + setDrawerProps({ title: '查看报表配置' });
  171 + }
  172 + if (unref(isUpdate)) {
  173 + //编辑回显数据
  174 + editResData = await reportEditDetailPage(data.record.id);
  175 + //回显基础数据
  176 + editId.value = editResData.data.id;
  177 + await setFieldsValue(editResData.data);
  178 + //回显嵌套数据
  179 + await setFieldsValue({
  180 + agg: editResData.data.queryCondition?.agg,
  181 + interval: editResData.data.queryCondition?.interval,
  182 + limit1: editResData.data.queryCondition?.limit,
  183 + orderBy: editResData.data.queryCondition?.orderBy,
  184 + useStrictDataTypes: editResData.data.queryCondition?.useStrictDataTypes,
  185 + startTs: editResData.data.queryCondition?.startTs,
  186 + endTs: editResData.data.queryCondition?.endTs,
  187 + });
  188 + //回显聚合条件
  189 + const dataCompareOpions = [
  190 + { label: '最小值', value: AggregateDataEnum.MIN },
  191 + { label: '最大值', value: AggregateDataEnum.MAX },
  192 + { label: '平均值', value: AggregateDataEnum.AVG },
  193 + { label: '求和', value: AggregateDataEnum.SUM },
  194 + { label: '空', value: AggregateDataEnum.NONE },
  195 + ];
  196 + const updateSchemaAgg = (options: {}) => {
  197 + updateSchema({
  198 + field: SchemaFiled.AGG,
  199 + componentProps: {
  200 + options,
  201 + },
  202 + });
  203 + };
  204 + if (editResData.data.dataType == 1) updateSchemaAgg(dataCompareOpions.slice(0, 4));
  205 + else updateSchemaAgg(dataCompareOpions.slice(4, 5));
  206 + //回显执行方式和查询周期
  207 + const dataQueryOpions = [
  208 + { label: '固定周期', value: QueryWay.LATEST },
  209 + { label: '自定义周期', value: QueryWay.TIME_PERIOD },
  210 + ];
  211 + const updateSchemaQuery = (options: {}) => {
  212 + updateSchema({
  213 + field: SchemaFiled.WAY,
  214 + componentProps: {
  215 + options,
  216 + },
  217 + });
  218 + };
  219 + if (editResData.data.executeWay == 0) updateSchemaQuery(dataQueryOpions);
  220 + else updateSchemaQuery(dataQueryOpions.slice(0, 1));
  221 + //回显设备
  222 + orgId.value = editResData.data.organizationId;
  223 + const { items } = await screenLinkPageByDeptIdGetDevice({
  224 + organizationId: editResData.data.organizationId,
  225 + });
  226 + selectOptions.value = items.map((item) => {
  227 + if (item.deviceType !== 'GATEWAY')
  228 + return {
  229 + label: item.name,
  230 + value: item.tbDeviceId,
  231 + };
  232 + });
  233 + const deviceIds = editResData.data.executeAttributes.map((m) => {
  234 + return {
  235 + label: m.name,
  236 + key: m.device,
  237 + };
  238 + });
  239 + selectDevice.value = deviceIds;
  240 + //回显设备属性
  241 + editDeviceAttr.value = editResData.data.executeAttributes?.map((item) => {
135 242 return {
136 243 label: item.name,
137   - value: item.tbDeviceId,
  244 + value: item.device,
  245 + attributes: item.attributes,
138 246 };
139   - });
140   - const deviceIds = editResData.data.executeAttributes.map(m => {
141   - return {
142   - label: m.name,
143   - key: m.device
144   - }
145   - })
146   - selectDevice.value = deviceIds;
147   - //回显设备属性
148   - editDeviceAttr.value = editResData.data.executeAttributes?.map(item => {
149   - return {
150   - label: item.name,
151   - value: item.device,
152   - attributes: item.attributes,
153   - }
154   - })
155   - deviceList.value = editDeviceAttr.value
156   - editDeviceList.value = editResData.data.executeAttributes
157   - } else {
158   - editId.value = '';
159   - orgId.value = '';
160   - selectDevice.value = [];
161   - selectOptions.value = [];
162   - deviceList.value = [];
163   - getAttrDevice.value = []
164   - editDeviceList.value = []
165   - editDeviceAttr.value = []
166   - updateSchema({
167   - field: SchemaFiled.AGG,
168   - componentProps: {
169   - options: [],
170   - },
171   - });
172   - //新增显示执行方式和查询周期
173   - const dataQueryOpions = [
174   - { label: '固定周期', value: QueryWay.LATEST },
175   - { label: '自定义周期', value: QueryWay.TIME_PERIOD },
176   - ];
177   - const updateSchemaQuery = (options: {}) => {
  247 + });
  248 + deviceList.value = editDeviceAttr.value;
  249 + editDeviceList.value = editResData.data.executeAttributes;
  250 + } else {
  251 + editId.value = '';
  252 + orgId.value = '';
  253 + selectDevice.value = [];
  254 + selectOptions.value = [];
  255 + deviceList.value = [];
  256 + getAttrDevice.value = [];
  257 + editDeviceList.value = [];
  258 + editDeviceAttr.value = [];
178 259 updateSchema({
179   - field: SchemaFiled.WAY,
  260 + field: SchemaFiled.AGG,
180 261 componentProps: {
181   - options,
  262 + options: [],
182 263 },
183 264 });
  265 + //新增显示执行方式和查询周期
  266 + const dataQueryOpions = [
  267 + { label: '固定周期', value: QueryWay.LATEST },
  268 + { label: '自定义周期', value: QueryWay.TIME_PERIOD },
  269 + ];
  270 + const updateSchemaQuery = (options: {}) => {
  271 + updateSchema({
  272 + field: SchemaFiled.WAY,
  273 + componentProps: {
  274 + options,
  275 + },
  276 + });
  277 + };
  278 + if (getFieldsValue().executeWay == 0) updateSchemaQuery(dataQueryOpions);
184 279 }
185   - if (getFieldsValue().executeWay == 0) updateSchemaQuery(dataQueryOpions)
186   - }
187   -});
188   -const handleClose = () => {
189   - deviceList.value = [];
190   -}
191   -const getAttrDevice: Ref<TDeviceList[]> = ref([]);
192   -const getTitle = computed(() => (!unref(isUpdate) ? '新增报表配置' : '编辑报表配置'));
193   -const handleChange = (e: any) => {
194   - getAttrDevice.value = e
195   -};
196   -let postObj: any = reactive({});
197   -let queryCondition: any = reactive({});
198   -let executeContent: any = reactive({});
199   -const startTs = ref(0)
200   -const endTs = ref(0);
201   -async function handleSubmit() {
202   - setDrawerProps({ confirmLoading: true });
203   - try {
204   - const { createMessage } = useMessage();
205   - const values = await validate();
206   - if (!values) return;
207   - if (!unref(isUpdate)) {
208   - if (getAttrDevice.value.length === 0) {
209   - return createMessage.error('请选择设备及其属性');
  280 + });
  281 + const handleClose = () => {
  282 + deviceList.value = [];
  283 + editId.value = '';
  284 + orgId.value = '';
  285 + selectDevice.value = [];
  286 + selectOptions.value = [];
  287 + getAttrDevice.value = [];
  288 + editDeviceList.value = [];
  289 + editDeviceAttr.value = [];
  290 + };
  291 + const getAttrDevice: Ref<TDeviceList[]> = ref([]);
  292 + const getTitle = computed(() => (!unref(isUpdate) ? '新增报表配置' : '编辑报表配置'));
  293 + let postObj: any = reactive({});
  294 + let queryCondition: any = reactive({});
  295 + let executeContent: any = reactive({});
  296 + const startTs = ref(0);
  297 + const endTs = ref(0);
  298 +
  299 + const getFormValueFunc = () => {
  300 + const item: any = unref(bindDeviceRefObj.deviceAttrRef)?.map((item: any) => item.emitChange());
  301 + getAttrDevice.value = item;
  302 + };
  303 +
  304 + async function handleSubmit() {
  305 + setDrawerProps({ confirmLoading: true });
  306 + try {
  307 + const { createMessage } = useMessage();
  308 + const values = await validate();
  309 + if (!values) return;
  310 + getFormValueFunc();
  311 + if (!unref(isUpdate)) {
  312 + if (getAttrDevice.value.length === 0) {
  313 + return createMessage.error('请选择设备及其属性');
  314 + }
210 315 }
211   - }
212   - if (values.executeWay == 0) {
213   - executeContent = null;
214   - } else {
215   - executeContent = values.cronTime
216   - }
217   - queryCondition = {
218   - agg: values.agg,
219   - interval: values.interval,
220   - limit: values.limit1,
221   - };
222   - if (values.way === QueryWay.LATEST) {
223   - startTs.value = moment().subtract(values.startTs, 'ms').valueOf()
224   - endTs.value = Date.now()
225   - } else {
226   - startTs.value = moment(values.startTs).valueOf()
227   - endTs.value = moment(values.endTs).valueOf()
228   - }
229   - delete values.devices;
230   - delete values.agg;
231   - delete values.interval;
232   - delete values.timeZone;
233   - delete values.timeWeek;
234   - delete values.cronTime;
235   - delete values.cronWeek;
236   - delete values.cronYear;
237   - delete values.limit1;
238   - postObj = {
239   - ...values,
240   - ...{ executeAttributes: getAttrDevice.value.length == 0 ? editDeviceList.value : getAttrDevice.value },
241   - ...{ queryCondition },
242   - ...{
243   - startTs: startTs.value
244   - },
245   - ...{
246   - endTs: endTs.value
247   - },
248   - ...{ executeContent },
249   - ...{ id: editId.value !== '' ? editId.value : '' },
250   - };
251   - let saveMessage = '添加成功';
252   - let updateMessage = '修改成功';
253   - editId.value !== ''
254   - ? await putReportConfigManage(postObj)
255   - : await createOrEditReportManage(postObj);
  316 + if (values.executeWay == 0) {
  317 + executeContent = null;
  318 + } else {
  319 + executeContent = values.cronTime;
  320 + }
  321 + if (values.way === QueryWay.LATEST) {
  322 + startTs.value = moment().subtract(values.startTs, 'ms').valueOf();
  323 + endTs.value = Date.now();
  324 + } else {
  325 + startTs.value = moment(values.startTs).valueOf();
  326 + endTs.value = moment(values.endTs).valueOf();
  327 + }
  328 + queryCondition = {
  329 + agg: values.agg,
  330 + interval: values.interval,
  331 + limit: values.limit1,
  332 + ...{
  333 + startTs: startTs.value,
  334 + },
  335 + ...{
  336 + endTs: endTs.value,
  337 + },
  338 + };
  339 +
  340 + delete values.devices;
  341 + delete values.agg;
  342 + delete values.interval;
  343 + delete values.timeZone;
  344 + delete values.timeWeek;
  345 + delete values.cronTime;
  346 + delete values.cronWeek;
  347 + delete values.cronYear;
  348 + delete values.limit1;
  349 + delete values.startTs;
  350 + postObj = {
  351 + ...values,
  352 + ...{
  353 + executeAttributes:
  354 + getAttrDevice.value.length == 0 ? editDeviceList.value : getAttrDevice.value,
  355 + },
  356 + ...{ queryCondition },
  357 +
  358 + ...{ executeContent },
  359 + ...{ id: editId.value !== '' ? editId.value : '' },
  360 + };
  361 + let saveMessage = '添加成功';
  362 + let updateMessage = '修改成功';
  363 + editId.value !== ''
  364 + ? await putReportConfigManage(postObj)
  365 + : await createOrEditReportManage(postObj);
256 366
257   - closeDrawer();
258   - emit('success');
259   - createMessage.success(unref(isUpdate) ? updateMessage : saveMessage);
260   - } finally {
261   - setTimeout(() => {
262   - setDrawerProps({ confirmLoading: false });
263   - }, 300);
  367 + closeDrawer();
  368 + emit('success');
  369 + createMessage.success(unref(isUpdate) ? updateMessage : saveMessage);
  370 + handleClose();
  371 + } finally {
  372 + setTimeout(() => {
  373 + setDrawerProps({ confirmLoading: false });
  374 + }, 300);
  375 + }
264 376 }
265   -}
266 377 </script>
... ...
... ... @@ -173,7 +173,7 @@ export const formSchema: QFormSchema[] = [
173 173 copyTransFun(data as any as any[]);
174 174 return data;
175 175 },
176   - onChange(e) {
  176 + async onChange(e) {
177 177 organizationId.value = e;
178 178 },
179 179 };
... ... @@ -318,11 +318,6 @@ export const formSchema: QFormSchema[] = [
318 318 label: '设备',
319 319 helpMessage: ['报表配置只对拥有"数值型"属性的设备才能配置'],
320 320 component: 'Select',
321   - // required: true,
322   - componentProps: {
323   - placeholder: '请选择设备',
324   - mode: 'multiple',
325   - },
326 321 slot: 'devices',
327 322 colProps: { span: 24 },
328 323 },
... ...
1 1 <template>
2   - <div v-for="param in dynamicInput.params" :key="param.key" style="display: flex; margin-top: 0.25vh">
3   - <a-input :disabled="true" v-model:value="param.device" style="width: 38%; margin-bottom: 5px; margin-left: 1vh"
4   - @change="emitChange" />
5   - <Select placeholder="请选择设备属性" v-model:value="param.attributes" style="width: 160px; margin-left: 1.8vw"
6   - :options="selectOptions" @change="emitChange" allowClear mode="multiple" />
  2 + <div
  3 + v-for="param in dynamicInput.params"
  4 + :key="param.key"
  5 + style="display: flex; margin-top: 0.25vh"
  6 + >
  7 + <a-input
  8 + :disabled="true"
  9 + v-model:value="param.name"
  10 + style="width: 38%; margin-bottom: 5px; margin-left: 1vh"
  11 + @change="emitChange"
  12 + />
  13 + <Select
  14 + placeholder="请选择设备属性"
  15 + v-model:value="param.attributes"
  16 + style="width: 160px; margin-left: 1.8vw"
  17 + :options="selectOptions"
  18 + @change="emitChange"
  19 + mode="multiple"
  20 + allowClear
  21 + />
7 22 </div>
8 23 </template>
9 24 <script lang="ts">
10   -export default {
11   - inheritAttrs: false,
12   -};
  25 + export default {
  26 + inheritAttrs: false,
  27 + };
13 28 </script>
14 29 <script lang="ts" setup>
15   -import { reactive, UnwrapRef, watchEffect, ref } from 'vue';
16   -import { propTypes } from '/@/utils/propTypes';
17   -import { SelectTypes } from 'ant-design-vue/es/select';
18   -import { Select } from 'ant-design-vue';
19   -import { getAttribute } from '/@/api/ruleengine/ruleengineApi';
  30 + import { reactive, UnwrapRef, watchEffect, ref } from 'vue';
  31 + import { propTypes } from '/@/utils/propTypes';
  32 + import { SelectTypes } from 'ant-design-vue/es/select';
  33 + import { Select } from 'ant-design-vue';
  34 + import { getAttribute } from '/@/api/ruleengine/ruleengineApi';
20 35
21   -interface Params {
22   - [x: string]: string;
23   - attributes: any;
24   - device: string;
25   -}
26   -const props = defineProps({
27   - value: propTypes.array.def([]),
28   - orgId: propTypes.string.def(''),
29   -});
30   -const emits = defineEmits(['change', 'update:value']);
31   -const selectOptions = ref<SelectTypes['options']>([]);
32   -//获取属性
33   -const getAttr = async (orgId, deviceId) => {
34   - const res = await getAttribute(orgId, deviceId.join(','));
35   - selectOptions.value = res.map((o) => {
36   - return {
37   - label: o,
38   - value: o,
39   - };
  36 + interface Params {
  37 + [x: string]: string;
  38 + attributes: any;
  39 + device: string;
  40 + }
  41 + const props = defineProps({
  42 + value: propTypes.object.def({}),
  43 + orgId: propTypes.string.def(''),
40 44 });
41   -};
42   -//动态数据
43   -const dynamicInput: UnwrapRef<{ params: Params[] }> = reactive({ params: [] });
44   -//监听传入数据value
45   -watchEffect(() => {
46   - initVal();
47   -});
48   -/**
49   - * 初始化数值
50   - */
51   -async function initVal() {
52   - dynamicInput.params = []
53   - if (props.value && props.orgId) {
54   - let jsonObj = props.value;
55   - const deviceId = jsonObj.map((m: any) => m.value);
56   - await getAttr(props.orgId, deviceId);
57   - dynamicInput.params = jsonObj.map((item: any) => {
  45 + const selectOptions = ref<SelectTypes['options']>([]);
  46 + //获取属性
  47 + const getAttr = async (orgId, deviceId) => {
  48 + const res = await getAttribute(orgId, deviceId);
  49 + selectOptions.value = res.map((o) => {
58 50 return {
59   - attributes: item.attributes,
60   - device: item.label,
61   - value: item.value,
62   - }
63   - })
64   - }
65   -}
66   -/**
67   - * 数值改变
68   - */
69   -function emitChange() {
70   - let obj: any = [];
71   - if (dynamicInput.params.length > 0) {
72   - dynamicInput.params.forEach((item: Params) => {
73   - obj.push({
74   - attributes: item.attributes,
75   - device: item.value,
76   - name: item.device
77   - });
  51 + label: o,
  52 + value: o,
  53 + };
78 54 });
  55 + };
  56 + //动态数据
  57 + const dynamicInput: UnwrapRef<{ params: Params[] }> = reactive({ params: [] });
  58 + const rEffect = watchEffect(() => {
  59 + initVal();
  60 + });
  61 + rEffect();
  62 + /**
  63 + * 初始化数值
  64 + */
  65 + async function initVal() {
  66 + if (props.orgId && props.value.value) {
  67 + await getAttr(props.orgId, props.value.value);
  68 + dynamicInput.params.push({
  69 + name: props.value.label,
  70 + device: props.value.value,
  71 + attributes: props.value.attributes == [] ? [] : props.value.attributes,
  72 + });
  73 + }
  74 + }
  75 + /**
  76 + * 数值改变
  77 + */
  78 + function emitChange() {
  79 + return dynamicInput.params[0];
79 80 }
80   - emits('change', obj);
81   - emits('update:value', obj);
82   -}
  81 + defineExpose({
  82 + emitChange,
  83 + });
83 84 </script>
84 85 <style scoped lang="css">
85   -@import './deviceAttrCpns.css';
  86 + @import './deviceAttrCpns.css';
86 87 </style>
... ...
... ... @@ -9,7 +9,12 @@
9 9 <a-button type="primary" @click="go('/report/export')"> 下载报表 </a-button>
10 10 </Authority>
11 11 <Authority value="api:yt:report:delete">
12   - <Popconfirm title="您确定要批量删除数据" ok-text="确定" cancel-text="取消" @confirm="handleDeleteOrBatchDelete(null)">
  12 + <Popconfirm
  13 + title="您确定要批量删除数据"
  14 + ok-text="确定"
  15 + cancel-text="取消"
  16 + @confirm="handleDeleteOrBatchDelete(null)"
  17 + >
13 18 <a-button type="primary" color="error" :disabled="hasBatchDelete"> 批量删除 </a-button>
14 19 </Popconfirm>
15 20 </Authority>
... ... @@ -20,30 +25,44 @@
20 25 </a-button>
21 26 </template>
22 27 <template #action="{ record }">
23   - <TableAction :actions="[
24   - {
25   - label: '编辑',
26   - icon: 'clarity:note-edit-line',
27   - auth: 'api:yt:report:update',
28   - onClick: handleCreateOrEdit.bind(null, record),
29   - ifShow: record.status === 0,
30   - },
31   - {
32   - label: '删除',
33   - icon: 'ant-design:delete-outlined',
34   - auth: 'api:yt:report:delete',
35   - color: 'error',
36   - ifShow: record.status === 0,
37   - popConfirm: {
38   - title: '是否确认删除',
39   - confirm: handleDeleteOrBatchDelete.bind(null, record),
  28 + <TableAction
  29 + :actions="[
  30 + {
  31 + label: '查看',
  32 + icon: 'clarity:note-edit-line',
  33 + onClick: handleViewDetail.bind(null, record),
  34 + ifShow: record.status === 1,
40 35 },
41   - },
42   - ]" />
  36 + {
  37 + label: '编辑',
  38 + icon: 'clarity:note-edit-line',
  39 + auth: 'api:yt:report:update',
  40 + onClick: handleCreateOrEdit.bind(null, record),
  41 + ifShow: record.status === 0,
  42 + },
  43 + {
  44 + label: '删除',
  45 + icon: 'ant-design:delete-outlined',
  46 + auth: 'api:yt:report:delete',
  47 + color: 'error',
  48 + ifShow: record.status === 0,
  49 + popConfirm: {
  50 + title: '是否确认删除',
  51 + confirm: handleDeleteOrBatchDelete.bind(null, record),
  52 + },
  53 + },
  54 + ]"
  55 + />
43 56 </template>
44 57 <template #status="{ record }">
45   - <Switch :disabled="disabledSwitch" :checked="record.status === 1" :loading="record.pendingStatus"
46   - checkedChildren="启用" unCheckedChildren="禁用" @change="(checked: boolean) => statusChange(checked, record)" />
  58 + <Switch
  59 + :disabled="disabledSwitch"
  60 + :checked="record.status === 1"
  61 + :loading="record.pendingStatus"
  62 + checkedChildren="启用"
  63 + unCheckedChildren="禁用"
  64 + @change="(checked: boolean) => statusChange(checked, record)"
  65 + />
47 66 </template>
48 67 </BasicTable>
49 68 <ReportConfigDrawer @register="registerDrawer" @success="handleSuccess" />
... ... @@ -52,114 +71,125 @@
52 71 </template>
53 72
54 73 <script lang="ts" setup>
55   -import { reactive, nextTick, ref } from 'vue';
56   -import { BasicTable, useTable, TableAction } from '/@/components/Table';
57   -import { useDrawer } from '/@/components/Drawer';
58   -import ReportConfigDrawer from './ReportConfigDrawer.vue';
59   -import DevicePreviewModal from './DevicePreviewModal.vue';
60   -import {
61   - reportPage,
62   - deleteReportManage,
63   - putReportByidAndStatusManage,
64   -} from '/@/api/report/reportManager';
65   -import { searchFormSchema, columns } from './config.data';
66   -import { Authority } from '/@/components/Authority';
67   -import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
68   -import { Popconfirm, Switch } from 'ant-design-vue';
69   -import { useModal } from '/@/components/Modal';
70   -import { useGo } from '/@/hooks/web/usePage';
71   -import { useMessage } from '/@/hooks/web/useMessage';
  74 + import { reactive, nextTick, ref } from 'vue';
  75 + import { BasicTable, useTable, TableAction } from '/@/components/Table';
  76 + import { useDrawer } from '/@/components/Drawer';
  77 + import ReportConfigDrawer from './ReportConfigDrawer.vue';
  78 + import DevicePreviewModal from './DevicePreviewModal.vue';
  79 + import {
  80 + reportPage,
  81 + deleteReportManage,
  82 + putReportByidAndStatusManage,
  83 + } from '/@/api/report/reportManager';
  84 + import { searchFormSchema, columns } from './config.data';
  85 + import { Authority } from '/@/components/Authority';
  86 + import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
  87 + import { Popconfirm, Switch } from 'ant-design-vue';
  88 + import { useModal } from '/@/components/Modal';
  89 + import { useGo } from '/@/hooks/web/usePage';
  90 + import { useMessage } from '/@/hooks/web/useMessage';
72 91
73   -const searchInfo = reactive<Recordable>({});
74   -const disabledSwitch = ref(false);
  92 + const searchInfo = reactive<Recordable>({});
  93 + const disabledSwitch = ref(false);
75 94
76   -const [registerTable, { reload, setProps }] = useTable({
77   - title: '报表列表',
78   - api: reportPage,
79   - columns,
80   - showIndexColumn: false,
81   - clickToRowSelect: false,
82   - formConfig: {
83   - labelWidth: 120,
84   - schemas: searchFormSchema,
85   - fieldMapToTime: [['sendTime', ['startTime', 'endTime'], 'YYYY-MM-DD HH:mm:ss']],
86   - },
87   - useSearchForm: true,
88   - showTableSetting: true,
89   - bordered: true,
90   - rowKey: 'id',
91   - actionColumn: {
92   - width: 200,
93   - title: '操作',
94   - dataIndex: 'action',
95   - slots: { customRender: 'action' },
96   - fixed: 'right',
97   - },
98   -});
  95 + const [registerTable, { reload, setProps }] = useTable({
  96 + title: '报表列表',
  97 + api: reportPage,
  98 + columns,
  99 + showIndexColumn: false,
  100 + clickToRowSelect: false,
  101 + formConfig: {
  102 + labelWidth: 120,
  103 + schemas: searchFormSchema,
  104 + fieldMapToTime: [['sendTime', ['startTime', 'endTime'], 'x']],
  105 + },
  106 + useSearchForm: true,
  107 + showTableSetting: true,
  108 + bordered: true,
  109 + rowKey: 'id',
  110 + actionColumn: {
  111 + width: 200,
  112 + title: '操作',
  113 + dataIndex: 'action',
  114 + slots: { customRender: 'action' },
  115 + fixed: 'right',
  116 + },
  117 + });
99 118
100   -// 弹框
101   -const [registerDrawer, { openDrawer }] = useDrawer();
102   -const { createMessage } = useMessage();
  119 + // 弹框
  120 + const [registerDrawer, { openDrawer }] = useDrawer();
  121 + const { createMessage } = useMessage();
  122 +
  123 + // 刷新
  124 + const handleSuccess = () => {
  125 + reload();
  126 + };
103 127
104   -// 刷新
105   -const handleSuccess = () => {
106   - reload();
107   -};
  128 + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
  129 + deleteReportManage,
  130 + handleSuccess,
  131 + setProps
  132 + );
108 133
109   -const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
110   - deleteReportManage,
111   - handleSuccess,
112   - setProps
113   -);
  134 + nextTick(() => {
  135 + setProps(selectionOptions);
  136 + });
114 137
115   -nextTick(() => {
116   - setProps(selectionOptions);
117   -});
  138 + // 新增或编辑
  139 + const handleCreateOrEdit = (record: Recordable | null) => {
  140 + if (record) {
  141 + openDrawer(true, {
  142 + isUpdate: true,
  143 + record,
  144 + isView: true,
  145 + });
  146 + } else {
  147 + openDrawer(true, {
  148 + isUpdate: false,
  149 + isView: true,
  150 + });
  151 + }
  152 + };
  153 + const handleViewDetail = (record: Recordable) => {
  154 + if (record) {
  155 + openDrawer(true, {
  156 + isUpdate: true,
  157 + record,
  158 + isView: false,
  159 + });
  160 + }
  161 + };
118 162
119   -// 新增或编辑
120   -const handleCreateOrEdit = (record: Recordable | null) => {
121   - if (record) {
122   - openDrawer(true, {
  163 + //查看设备
  164 + const [registerModal, { openModal }] = useModal();
  165 + const handleDeviceView = (record) => {
  166 + openModal(true, {
123 167 isUpdate: true,
124 168 record,
125 169 });
126   - } else {
127   - openDrawer(true, {
128   - isUpdate: false,
129   - });
130   - }
131   -};
132   -
133   -//查看设备
134   -const [registerModal, { openModal }] = useModal();
135   -const handleDeviceView = (record) => {
136   - openModal(true, {
137   - isUpdate: true,
138   - record,
139   - });
140   -};
141   -const statusChange = async (checked, record) => {
142   - try {
143   - setProps({
144   - loading: true,
145   - });
146   - disabledSwitch.value = true;
147   - const newStatus = checked ? 1 : 0;
148   - const res = await putReportByidAndStatusManage(record.id, newStatus);
149   - if (res && newStatus) {
150   - createMessage.success(`启用成功`);
151   - } else {
152   - createMessage.success('禁用成功');
153   - }
154   - } finally {
155   - setTimeout(() => {
  170 + };
  171 + const statusChange = async (checked, record) => {
  172 + try {
156 173 setProps({
157   - loading: false,
  174 + loading: true,
158 175 });
159   - disabledSwitch.value = false;
160   - }, 500);
161   - reload();
162   - }
163   -};
164   -const go = useGo();
  176 + disabledSwitch.value = true;
  177 + const newStatus = checked ? 1 : 0;
  178 + const res = await putReportByidAndStatusManage(record.id, newStatus);
  179 + if (res && newStatus) {
  180 + createMessage.success(`启用成功`);
  181 + } else {
  182 + createMessage.success('禁用成功');
  183 + }
  184 + } finally {
  185 + setTimeout(() => {
  186 + setProps({
  187 + loading: false,
  188 + });
  189 + disabledSwitch.value = false;
  190 + }, 500);
  191 + reload();
  192 + }
  193 + };
  194 + const go = useGo();
165 195 </script>
... ...
... ... @@ -85,7 +85,7 @@ export const searchFormSchema: FormSchema[] = [
85 85 },
86 86 },
87 87 {
88   - field: 'executeTime',
  88 + field: 'sendTime',
89 89 label: '执行时间',
90 90 component: 'RangePicker',
91 91 componentProps: {
... ...
... ... @@ -18,7 +18,7 @@
18 18 :actions="[
19 19 {
20 20 label: '报表导出',
21   - icon: 'clarity:note-edit-line',
  21 + icon: 'ant-design:dot-chart-outlined',
22 22 auth: 'api:yt:reportExport:export',
23 23 onClick: handleExport.bind(null, record),
24 24 ifShow: record.executeStatus === 1,
... ... @@ -69,6 +69,7 @@
69 69 formConfig: {
70 70 labelWidth: 120,
71 71 schemas: searchFormSchema,
  72 + fieldMapToTime: [['sendTime', ['startTime', 'endTime'], 'x']],
72 73 },
73 74 useSearchForm: true,
74 75 showTableSetting: true,
... ... @@ -104,11 +105,18 @@
104 105 record,
105 106 });
106 107 };
  108 + const exportUrlsFunc = (fUrl) => {
  109 + const options: any = {
  110 + url: fUrl,
  111 + };
  112 + downloadByUrl(options);
  113 + };
107 114 const handleExport = (record) => {
108   - const url = record.reportPath;
109   - downloadByUrl({
110   - url,
111   - target: '_self',
112   - });
  115 + if (record.reportPath) {
  116 + const urls = record.reportPath.split(',');
  117 + urls.forEach((f: string) => {
  118 + exportUrlsFunc(f);
  119 + });
  120 + }
113 121 };
114 122 </script>
... ...
... ... @@ -21,7 +21,7 @@
21 21 const emit = defineEmits(['success', 'register']);
22 22 const isUpdate = ref(true);
23 23 const editId = ref('');
24   - const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({
  24 + const [registerForm, { validate, setFieldsValue, resetFields, updateSchema }] = useForm({
25 25 labelWidth: 120,
26 26 schemas: formSchema,
27 27 showActionButtonGroup: false,
... ... @@ -34,9 +34,21 @@
34 34 if (unref(isUpdate)) {
35 35 //回显基础数据
36 36 editId.value = data.record.id;
  37 + updateSchema({
  38 + field: 'invokeTarget',
  39 + componentProps: {
  40 + disabled: true,
  41 + },
  42 + });
37 43 await setFieldsValue(data.record);
38 44 } else {
39 45 editId.value = '';
  46 + updateSchema({
  47 + field: 'invokeTarget',
  48 + componentProps: {
  49 + disabled: false,
  50 + },
  51 + });
40 52 }
41 53 });
42 54 const getTitle = computed(() => (!unref(isUpdate) ? '新增定时任务' : '编辑定时任务'));
... ...
... ... @@ -37,7 +37,7 @@ export const personSchema: DescItem[] = [
37 37 label: 'cron表达式:',
38 38 },
39 39 {
40   - field: 'b6',
  40 + field: 'updateTime',
41 41 label: '下次执行时间:',
42 42 },
43 43 {
... ... @@ -52,12 +52,22 @@ export const personSchema: DescItem[] = [
52 52 },
53 53 },
54 54 {
55   - field: 'b9',
  55 + field: 'concurrent',
56 56 label: '是否并发:',
  57 + render: (_, data) => {
  58 + return data.concurrent == 0 ? '允许' : '禁止';
  59 + },
57 60 },
58 61 {
59   - field: 'b10',
  62 + field: 'misfirePolicy',
60 63 label: '执行策略:',
  64 + render: (_, data) => {
  65 + return data.misfirePolicy == 0
  66 + ? '立即执行'
  67 + : data.misfirePolicy == 1
  68 + ? '执行一次'
  69 + : '放弃执行';
  70 + },
61 71 },
62 72 ];
63 73
... ...
... ... @@ -67,10 +67,6 @@ export const searchSchedueFormSchema: FormSchema[] = [
67 67 label: '系统',
68 68 value: EJobGroup.SYSTEM,
69 69 },
70   - {
71   - label: '报表',
72   - value: EJobGroup.REPORT,
73   - },
74 70 ],
75 71 placeholder: '请选择任务组名',
76 72 },
... ... @@ -159,47 +155,47 @@ export const formSchema: QFormSchema[] = [
159 155 rules: [{ required: true, message: '请输入Cron表达式' }, { validator: JCronValidator }],
160 156 },
161 157 {
162   - field: 'field10',
  158 + field: 'misfirePolicy',
163 159 component: 'RadioButtonGroup',
164 160 label: '执行策略',
165 161 colProps: {
166 162 span: 24,
167 163 },
168   - defaultValue: '1',
  164 + defaultValue: 1,
169 165 componentProps: {
170 166 options: [
171 167 {
172 168 label: '立即执行',
173   - value: '1',
  169 + value: 0,
174 170 },
175 171 {
176 172 label: '执行一次',
177   - value: '2',
  173 + value: 1,
178 174 },
179 175 {
180 176 label: '放弃执行',
181   - value: '3',
  177 + value: 2,
182 178 },
183 179 ],
184 180 },
185 181 },
186 182 {
187   - field: 'field11',
  183 + field: 'concurrent',
188 184 component: 'RadioButtonGroup',
189 185 label: '是否并发',
190 186 colProps: {
191 187 span: 24,
192 188 },
193   - defaultValue: '2',
  189 + defaultValue: 1,
194 190 componentProps: {
195 191 options: [
196 192 {
197 193 label: '允许',
198   - value: '1',
  194 + value: 0,
199 195 },
200 196 {
201 197 label: '禁止',
202   - value: '2',
  198 + value: 1,
203 199 },
204 200 ],
205 201 },
... ... @@ -215,11 +211,11 @@ export const formSchema: QFormSchema[] = [
215 211 componentProps: {
216 212 options: [
217 213 {
218   - label: '正常',
  214 + label: '启用',
219 215 value: 1,
220 216 },
221 217 {
222   - label: '暂停',
  218 + label: '禁用',
223 219 value: 0,
224 220 },
225 221 ],
... ...