Commit c9f680abd7a800a93e09da724c4f733208581f6a

Authored by fengtao
1 parent 0c57c6d7

feat:pc端新增报表管理 未调服务端接口

  1 +<template>
  2 + <div>
  3 + <BasicModal
  4 + v-bind="$attrs"
  5 + width="55rem"
  6 + :height="heightNum"
  7 + @register="register"
  8 + title="执行设备及属性"
  9 + @cancel="handleCancel"
  10 + :showOkBtn="false"
  11 + >
  12 + <div>
  13 + <BasicTable @register="registerTable" :dataSource="tableData" />
  14 + </div>
  15 + </BasicModal>
  16 + </div>
  17 +</template>
  18 +<script setup lang="ts">
  19 + import { ref, nextTick } from 'vue';
  20 + import { BasicModal, useModalInner } from '/@/components/Modal';
  21 + import { BasicTable, useTable } from '/@/components/Table';
  22 + import { viewDeviceColumn } from './config.data';
  23 +
  24 + const heightNum = ref(800);
  25 + const tableData: any = ref([]);
  26 + const [registerTable] = useTable({
  27 + title: '执行设备及属性',
  28 + columns: viewDeviceColumn,
  29 + showIndexColumn: false,
  30 + clickToRowSelect: false,
  31 + showTableSetting: false,
  32 + bordered: true,
  33 + });
  34 + const [register] = useModalInner((data) => {
  35 + console.log(data);
  36 + const getTableData = () => {
  37 + for (let i = 0; i < 100; i++) {
  38 + tableData.value.push({
  39 + tdDevice: `设备${i}`,
  40 + attr: `CO${i}、Temp${i}`,
  41 + });
  42 + }
  43 + };
  44 + nextTick(() => {
  45 + getTableData();
  46 + });
  47 + });
  48 + const handleCancel = () => {};
  49 +</script>
  50 +<style></style>
... ...
  1 +<template>
  2 + <BasicDrawer
  3 + v-bind="$attrs"
  4 + @register="registerDrawer"
  5 + showFooter
  6 + :title="getTitle"
  7 + width="30%"
  8 + @ok="handleSubmit"
  9 + >
  10 + <BasicForm @register="registerForm" />
  11 + </BasicDrawer>
  12 +</template>
  13 +<script lang="ts" setup>
  14 + import { ref, computed, unref, nextTick } from 'vue';
  15 + import { BasicForm, useForm } from '/@/components/Form';
  16 + import { formSchema } from './config.data';
  17 + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
  18 + import { createOrEditCameraManage } from '/@/api/camera/cameraManager';
  19 + import { useMessage } from '/@/hooks/web/useMessage';
  20 +
  21 + const emit = defineEmits(['success', 'register']);
  22 + const isUpdate = ref(true);
  23 + const editId = ref('');
  24 + const [registerForm, { validate, setFieldsValue, resetFields }] = useForm({
  25 + labelWidth: 120,
  26 + schemas: formSchema,
  27 + showActionButtonGroup: false,
  28 + });
  29 +
  30 + const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
  31 + await resetFields();
  32 + setDrawerProps({ confirmLoading: false });
  33 + isUpdate.value = !!data?.isUpdate;
  34 + if (unref(isUpdate)) {
  35 + await nextTick();
  36 + editId.value = data.record.id;
  37 + await setFieldsValue(data.record);
  38 + } else {
  39 + editId.value = '';
  40 + }
  41 + });
  42 +
  43 + const getTitle = computed(() => (!unref(isUpdate) ? '新增报表配置' : '编辑报表配置'));
  44 +
  45 + async function handleSubmit() {
  46 + setDrawerProps({ confirmLoading: true });
  47 + try {
  48 + const { createMessage } = useMessage();
  49 + const values = await validate();
  50 + if (!values) return;
  51 + let saveMessage = '添加成功';
  52 + let updateMessage = '修改成功';
  53 + await createOrEditCameraManage(values);
  54 + closeDrawer();
  55 + emit('success');
  56 + createMessage.success(unref(isUpdate) ? updateMessage : saveMessage);
  57 + } finally {
  58 + setTimeout(() => {
  59 + setDrawerProps({ confirmLoading: false });
  60 + }, 300);
  61 + }
  62 + }
  63 +</script>
... ...
  1 +import { BasicColumn, FormSchema } from '/@/components/Table';
  2 +import type { FormSchema as QFormSchema } from '/@/components/Form/index';
  3 +import moment from 'moment';
  4 +import { getOrganizationList } from '/@/api/system/system';
  5 +import { copyTransFun } from '/@/utils/fnUtils';
  6 +import { screenLinkPageByDeptIdGetDevice } from '/@/api/ruleengine/ruleengineApi';
  7 +import { getAttribute } from '/@/api/ruleengine/ruleengineApi';
  8 +
  9 +export enum TypeEnum {
  10 + IS_TIMING = 'TIMING',
  11 + IS_WEEK = 'week',
  12 + IS_MONTH = 'month',
  13 +}
  14 +export const isTiming = (type: string) => {
  15 + return type === TypeEnum.IS_TIMING;
  16 +};
  17 +export const isWeek = (type: string) => {
  18 + return type === TypeEnum.IS_WEEK;
  19 +};
  20 +
  21 +export const isMonth = (type: string) => {
  22 + return type === TypeEnum.IS_MONTH;
  23 +};
  24 +
  25 +
  26 +export enum AggregateDataEnum {
  27 + MIN = 'MIN',
  28 + MAX = 'MAX',
  29 + AVG = 'AVG',
  30 + SUM = 'SUM',
  31 + COUNT = 'COUNT',
  32 + NONE = 'NONE',
  33 +}
  34 +
  35 +// 表格配置
  36 +export const columns: BasicColumn[] = [
  37 + {
  38 + title: '配置名称',
  39 + dataIndex: '1',
  40 + width: 80,
  41 + },
  42 + {
  43 + title: '所属组织',
  44 + dataIndex: '2',
  45 + width: 120,
  46 + },
  47 + {
  48 + title: '数据类型',
  49 + dataIndex: '3',
  50 + width: 120,
  51 + },
  52 + {
  53 + title: '配置状态',
  54 + dataIndex: '4',
  55 + width: 120,
  56 + },
  57 + {
  58 + title: '执行方式',
  59 + dataIndex: '5',
  60 + width: 160,
  61 + },
  62 + {
  63 + title: '执行设备',
  64 + dataIndex: '6',
  65 + width: 160,
  66 + slots: { customRender: 'doDeviceSlot' },
  67 + },
  68 + {
  69 + title: '创建人',
  70 + dataIndex: '7',
  71 + width: 180,
  72 + },
  73 + {
  74 + title: '创建日期',
  75 + dataIndex: '8',
  76 + width: 180,
  77 + },
  78 +];
  79 +export const viewDeviceColumn: BasicColumn[] = [
  80 + {
  81 + title: '设备',
  82 + dataIndex: 'tdDevice',
  83 + width: 80,
  84 + },
  85 + {
  86 + title: '属性',
  87 + dataIndex: 'attr',
  88 + width: 120,
  89 + },
  90 +];
  91 +
  92 +// 查询配置
  93 +export const searchFormSchema: FormSchema[] = [
  94 + {
  95 + field: '1',
  96 + label: '配置名称',
  97 + component: 'Input',
  98 + colProps: { span: 6 },
  99 + componentProps: {
  100 + maxLength: 36,
  101 + placeholder: '请输入配置名称',
  102 + },
  103 + },
  104 + {
  105 + field: '2',
  106 + label: '配置状态',
  107 + component: 'Select',
  108 + colProps: { span: 6 },
  109 + componentProps: {
  110 + options: [
  111 + {
  112 + label: '启用',
  113 + value: 1,
  114 + },
  115 + {
  116 + label: '禁用',
  117 + value: 0,
  118 + },
  119 + ],
  120 + placeholder: '请选择配置状态',
  121 + },
  122 + },
  123 + {
  124 + field: '3',
  125 + label: '创建时间',
  126 + component: 'RangePicker',
  127 + componentProps: {
  128 + showTime: {
  129 + defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
  130 + },
  131 + },
  132 + colProps: { span: 6 },
  133 + },
  134 +];
  135 +
  136 +// 新增编辑配置
  137 +export const formSchema: QFormSchema[] = [
  138 + {
  139 + field: '1',
  140 + label: '报表名称',
  141 + colProps: { span: 24 },
  142 + helpMessage: ['报表配置', '只对拥有数值型属性', '的设备才能配置'],
  143 + required: true,
  144 + component: 'Input',
  145 + componentProps: {
  146 + maxLength: 255,
  147 + placeholder: '请输入报表名称',
  148 + },
  149 + },
  150 + {
  151 + field: 'organizationId',
  152 + label: '所属组织',
  153 + colProps: { span: 24 },
  154 + component: 'ApiTreeSelect',
  155 + required: true,
  156 + componentProps: ({ formActionType }) => {
  157 + const { updateSchema } = formActionType;
  158 + return {
  159 + async onChange(e) {
  160 + if (e) {
  161 + //获取该组织下的设备
  162 + const { items } = await screenLinkPageByDeptIdGetDevice({
  163 + organizationId: e,
  164 + });
  165 + const options = items.map((item) => {
  166 + return {
  167 + label: item.name,
  168 + value: item.tbDeviceId,
  169 + };
  170 + });
  171 + updateSchema({
  172 + field: 'entityId',
  173 + componentProps: {
  174 + options,
  175 + async onChange(e1) {
  176 + if (e1) {
  177 + const res = await getAttribute(e, e1.join(','));
  178 + const attr = res.map((item) => {
  179 + return {
  180 + label: item,
  181 + value: item,
  182 + };
  183 + });
  184 + updateSchema({
  185 + field: 'attr',
  186 + componentProps: {
  187 + options: attr,
  188 + },
  189 + });
  190 + }
  191 + },
  192 + },
  193 + });
  194 + }
  195 + },
  196 + maxLength: 250,
  197 + placeholder: '请选择所属组织',
  198 + api: async () => {
  199 + const data = await getOrganizationList();
  200 + copyTransFun(data as any as any[]);
  201 + return data;
  202 + },
  203 + };
  204 + },
  205 + },
  206 + {
  207 + field: '3',
  208 + label: '描述',
  209 + colProps: { span: 24 },
  210 + component: 'InputTextArea',
  211 + componentProps: {
  212 + maxLength: 255,
  213 + placeholder: '请输入描述',
  214 + },
  215 + },
  216 + {
  217 + field: 'actionS',
  218 + component: 'RadioGroup',
  219 + label: '执行方式',
  220 + colProps: {
  221 + span: 24,
  222 + },
  223 + defaultValue: '1',
  224 + componentProps: {
  225 + placeholder: '请选择执行方式',
  226 + options: [
  227 + {
  228 + label: '立即执行',
  229 + value: '1',
  230 + },
  231 + {
  232 + label: '定时执行',
  233 + value: 'TIMING',
  234 + },
  235 + ],
  236 + },
  237 + },
  238 + {
  239 + field: 'timeWeek',
  240 + component: 'Select',
  241 + label: '周期',
  242 + required: true,
  243 + colProps: { span: 24 },
  244 + defaultValue: '1',
  245 + componentProps: {
  246 + placeholder: '请选择周期',
  247 + options: [
  248 + { label: '每日', value: 'day' },
  249 + { label: '每周', value: 'week' },
  250 + { label: '每月', value: 'month' },
  251 + ],
  252 + },
  253 + ifShow: ({ values }) => isTiming(values.actionS),
  254 + },
  255 + {
  256 + field: '5',
  257 + component: 'Select',
  258 + label: '每周',
  259 + required: true,
  260 + colProps: { span: 24 },
  261 + defaultValue: '1',
  262 + componentProps: {
  263 + placeholder: '请选择周期',
  264 + options: [
  265 + { label: '星期一', value: '1' },
  266 + { label: '星期二', value: '2' },
  267 + { label: '星期三', value: '3' },
  268 + { label: '星期四', value: '3' },
  269 + { label: '星期五', value: '3' },
  270 + ],
  271 + },
  272 + ifShow: ({ values }) => isWeek(values.timeWeek),
  273 + },
  274 + {
  275 + field: '5',
  276 + component: 'Select',
  277 + label: '每月',
  278 + required: true,
  279 + colProps: { span: 24 },
  280 + defaultValue: '1',
  281 + componentProps: {
  282 + placeholder: '请选择周期',
  283 + options: [
  284 + { label: '1日', value: '1' },
  285 + { label: '2日', value: '7' },
  286 + { label: '3日', value: '30' },
  287 + ],
  288 + },
  289 + ifShow: ({ values }) => isMonth(values.timeWeek),
  290 + },
  291 + {
  292 + field: '6',
  293 + component: 'Select',
  294 + label: '时间',
  295 + required: true,
  296 + colProps: { span: 24 },
  297 + defaultValue: '1',
  298 + componentProps: {
  299 + placeholder: '请选择时间',
  300 + options: [
  301 + { label: '00点', value: '1' },
  302 + { label: '01点', value: '2' },
  303 + { label: '02点', value: '3' },
  304 + ],
  305 + },
  306 + ifShow: ({ values }) => isTiming(values.actionS),
  307 + },
  308 + {
  309 + field: 'entityId',
  310 + label: '设备',
  311 + required: true,
  312 + component: 'Select',
  313 + componentProps: {
  314 + placeholder: '请选择设备',
  315 + mode: 'multiple',
  316 + },
  317 + colProps: { span: 24 },
  318 + },
  319 + {
  320 + field: '7',
  321 + component: 'RadioGroup',
  322 + label: '属性性质',
  323 + required: true,
  324 + colProps: {
  325 + span: 24,
  326 + },
  327 + defaultValue: '1',
  328 + componentProps: {
  329 + placeholder: '请选择属性性质',
  330 + options: [
  331 + {
  332 + label: '共有',
  333 + value: '1',
  334 + },
  335 + {
  336 + label: '全部',
  337 + value: '2',
  338 + },
  339 + ],
  340 + },
  341 + },
  342 + {
  343 + field: 'attr',
  344 + label: '设备属性',
  345 + required: true,
  346 + component: 'Select',
  347 + componentProps: {
  348 + placeholder: '请选择设备属性',
  349 + },
  350 + colProps: { span: 24 },
  351 + },
  352 + {
  353 + field: '9',
  354 + label: '数据类型',
  355 + required: true,
  356 + component: 'Select',
  357 + componentProps: {
  358 + placeholder: '请选择数据类型',
  359 + options: [
  360 + { label: '历史数据', value: '1' },
  361 + { label: '同比', value: '2' },
  362 + { label: '环比', value: '2' },
  363 + ],
  364 + },
  365 + colProps: { span: 24 },
  366 + },
  367 + {
  368 + field: '10',
  369 + label: '聚合条件',
  370 + required: true,
  371 + component: 'Select',
  372 + componentProps: {
  373 + placeholder: '请选择聚合条件',
  374 + options: [
  375 + {
  376 + label: '平均值',
  377 + value: AggregateDataEnum.AVG,
  378 + },
  379 + {
  380 + label: '总和',
  381 + value: AggregateDataEnum.SUM,
  382 + },
  383 + {
  384 + label: '最大值',
  385 + value: AggregateDataEnum.MAX,
  386 + },
  387 + {
  388 + label: '最小值',
  389 + value: AggregateDataEnum.MIN,
  390 + },
  391 + ],
  392 + },
  393 + colProps: { span: 24 },
  394 + },
  395 + {
  396 + field: '9',
  397 + label: '查询周期',
  398 + required: true,
  399 + component: 'Select',
  400 + componentProps: {
  401 + placeholder: '请选择查询周期',
  402 + options: [
  403 + { label: '1分钟', value: '60000' },
  404 + { label: '2分钟', value: '120000' },
  405 + { label: '3分钟', value: '180000' },
  406 + ],
  407 + },
  408 + colProps: { span: 24 },
  409 + },
  410 + {
  411 + field: '10',
  412 + label: '间隔时间',
  413 + required: true,
  414 + component: 'Select',
  415 + componentProps: {
  416 + placeholder: '请选择间隔时间',
  417 + options: [
  418 + { label: '1秒', value: '1000' },
  419 + { label: '5秒', value: '5000' },
  420 + { label: '10秒', value: '10000' },
  421 + { label: '15秒', value: '150000' },
  422 + ],
  423 + },
  424 + colProps: { span: 24 },
  425 + },
  426 +];
... ...
  1 +<template>
  2 + <div>
  3 + <BasicTable :clickToRowSelect="false" @register="registerTable" :searchInfo="searchInfo">
  4 + <template #toolbar>
  5 + <Authority value="api:yt:report:post">
  6 + <a-button type="primary" @click="handleCreateOrEdit(null)"> 新增报表 </a-button>
  7 + </Authority>
  8 + <Authority value="api:yt:report:get">
  9 + <a-button type="primary" @click="go('/report/export')"> 下载报表 </a-button>
  10 + </Authority>
  11 + <Authority value="api:yt:report:delete">
  12 + <Popconfirm
  13 + title="您确定要批量删除数据"
  14 + ok-text="确定"
  15 + cancel-text="取消"
  16 + @confirm="handleDeleteOrBatchDelete(null)"
  17 + >
  18 + <a-button type="primary" color="error" :disabled="hasBatchDelete"> 批量删除 </a-button>
  19 + </Popconfirm>
  20 + </Authority>
  21 + </template>
  22 + <template #doDeviceSlot="{ record }">
  23 + <a-button type="text" @click="handleDeviceView(record)">
  24 + <span style="color: #377dff">查看设备</span>
  25 + </a-button>
  26 + </template>
  27 + <template #action="{ record }">
  28 + <TableAction
  29 + :actions="[
  30 + {
  31 + label: '编辑',
  32 + icon: 'clarity:note-edit-line',
  33 + auth: 'api:yt:report:update',
  34 + onClick: handleCreateOrEdit.bind(null, record),
  35 + },
  36 + {
  37 + label: '删除',
  38 + icon: 'ant-design:delete-outlined',
  39 + auth: 'api:yt:report:delete',
  40 + color: 'error',
  41 + popConfirm: {
  42 + title: '是否确认删除',
  43 + confirm: handleDeleteOrBatchDelete.bind(null, record),
  44 + },
  45 + },
  46 + ]"
  47 + />
  48 + </template>
  49 + </BasicTable>
  50 + <ReportConfigDrawer @register="registerDrawer" @success="handleSuccess" />
  51 + <DevicePreviewModal @register="registerModal" />
  52 + </div>
  53 +</template>
  54 +
  55 +<script lang="ts" setup>
  56 + import { reactive, nextTick } from 'vue';
  57 + import { BasicTable, useTable, TableAction } from '/@/components/Table';
  58 + import { useDrawer } from '/@/components/Drawer';
  59 + import ReportConfigDrawer from './ReportConfigDrawer.vue';
  60 + import DevicePreviewModal from './DevicePreviewModal.vue';
  61 + import { cameraPage, deleteCameraManage } from '/@/api/camera/cameraManager';
  62 + import { searchFormSchema, columns } from './config.data';
  63 + import { Authority } from '/@/components/Authority';
  64 + import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
  65 + import { Popconfirm } from 'ant-design-vue';
  66 + import { useModal } from '/@/components/Modal';
  67 + import { useGo } from '/@/hooks/web/usePage';
  68 +
  69 + const searchInfo = reactive<Recordable>({});
  70 +
  71 + const [registerTable, { reload, setProps }] = useTable({
  72 + title: '报表列表',
  73 + api: cameraPage,
  74 + columns,
  75 + showIndexColumn: false,
  76 + clickToRowSelect: false,
  77 + formConfig: {
  78 + labelWidth: 120,
  79 + schemas: searchFormSchema,
  80 + },
  81 + useSearchForm: true,
  82 + showTableSetting: true,
  83 + bordered: true,
  84 + rowKey: 'id',
  85 + actionColumn: {
  86 + width: 200,
  87 + title: '操作',
  88 + dataIndex: 'action',
  89 + slots: { customRender: 'action' },
  90 + fixed: 'right',
  91 + },
  92 + });
  93 +
  94 + // 弹框
  95 + const [registerDrawer, { openDrawer }] = useDrawer();
  96 +
  97 + // 刷新
  98 + const handleSuccess = () => {
  99 + reload();
  100 + };
  101 +
  102 + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
  103 + deleteCameraManage,
  104 + handleSuccess,
  105 + setProps
  106 + );
  107 +
  108 + nextTick(() => {
  109 + setProps(selectionOptions);
  110 + });
  111 +
  112 + // 新增或编辑
  113 + const handleCreateOrEdit = (record: Recordable | null) => {
  114 + if (record) {
  115 + openDrawer(true, {
  116 + isUpdate: true,
  117 + record,
  118 + });
  119 + } else {
  120 + openDrawer(true, {
  121 + isUpdate: false,
  122 + });
  123 + }
  124 + };
  125 +
  126 + //查看设备
  127 + const [registerModal, { openModal }] = useModal();
  128 + const handleDeviceView = (record) => {
  129 + openModal(true, {
  130 + isUpdate: true,
  131 + record,
  132 + });
  133 + };
  134 + const go = useGo();
  135 +</script>
... ...
  1 +<template>
  2 + <div>
  3 + <BasicModal
  4 + v-bind="$attrs"
  5 + width="55rem"
  6 + :height="heightNum"
  7 + @register="register"
  8 + title="报表趋势图"
  9 + @cancel="handleCancel"
  10 + :showOkBtn="false"
  11 + >
  12 + <div ref="chartRef" :style="{ height, width }"></div>
  13 + </BasicModal>
  14 + </div>
  15 +</template>
  16 +<script setup lang="ts">
  17 + import { ref, PropType, Ref, nextTick } from 'vue';
  18 + import { BasicModal, useModalInner } from '/@/components/Modal';
  19 + import { useECharts } from '/@/hooks/web/useECharts';
  20 +
  21 + defineProps({
  22 + width: {
  23 + type: String as PropType<string>,
  24 + default: '100%',
  25 + },
  26 + height: {
  27 + type: String as PropType<string>,
  28 + default: 'calc(100vh - 378px)',
  29 + },
  30 + });
  31 + defineEmits(['register']);
  32 + const heightNum = ref(800);
  33 + const chartRef = ref<HTMLDivElement | null>(null);
  34 + const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
  35 + const [register] = useModalInner((data) => {
  36 + console.log(data);
  37 + nextTick(() => {
  38 + setOptions({
  39 + title: {
  40 + text: '报表趋势图',
  41 + },
  42 + tooltip: {
  43 + trigger: 'axis',
  44 + },
  45 + legend: {
  46 + data: ['CO', 'CO2'],
  47 + },
  48 + toolbox: {},
  49 + grid: {
  50 + left: '3%',
  51 + right: '4%',
  52 + bottom: '3%',
  53 + containLabel: true,
  54 + },
  55 + xAxis: {
  56 + type: 'category',
  57 + data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  58 + boundaryGap: false,
  59 + },
  60 + yAxis: {
  61 + type: 'value',
  62 + boundaryGap: false,
  63 + },
  64 + series: [
  65 + {
  66 + name: 'CO',
  67 + type: 'line',
  68 + stack: 'Total',
  69 + data: [150, 230, 224, 218, 135, 147, 260],
  70 + },
  71 + {
  72 + name: 'CO2',
  73 + type: 'line',
  74 + stack: 'Total',
  75 + data: [15, 23, 22, 28, 15, 17, 20],
  76 + },
  77 + ],
  78 + });
  79 + });
  80 + });
  81 +
  82 + const handleCancel = () => {};
  83 +</script>
  84 +<style>
  85 + .video-sty {
  86 + width: 100%;
  87 + display: flex;
  88 + align-items: center;
  89 + justify-content: center;
  90 + }
  91 +</style>
... ...
  1 +import { BasicColumn, FormSchema } from '/@/components/Table';
  2 +import moment from 'moment';
  3 +
  4 +// 表格配置
  5 +export const columns: BasicColumn[] = [
  6 + {
  7 + title: '配置名称',
  8 + dataIndex: '1',
  9 + width: 80,
  10 + },
  11 + {
  12 + title: '所属组织',
  13 + dataIndex: '2',
  14 + width: 120,
  15 + },
  16 + {
  17 + title: '数据类型',
  18 + dataIndex: '3',
  19 + width: 120,
  20 + },
  21 + {
  22 + title: '执行状态',
  23 + dataIndex: '4',
  24 + width: 120,
  25 + },
  26 + {
  27 + title: '执行日期',
  28 + dataIndex: '8',
  29 + width: 180,
  30 + },
  31 +];
  32 +
  33 +// 查询配置
  34 +export const searchFormSchema: FormSchema[] = [
  35 + {
  36 + field: '1',
  37 + label: '配置名称',
  38 + component: 'Input',
  39 + colProps: { span: 6 },
  40 + componentProps: {
  41 + maxLength: 36,
  42 + placeholder: '请输入配置名称',
  43 + },
  44 + },
  45 + {
  46 + field: '2',
  47 + label: '执行状态',
  48 + component: 'Select',
  49 + colProps: { span: 6 },
  50 + componentProps: {
  51 + options: [
  52 + {
  53 + label: '进行中',
  54 + value: 1,
  55 + },
  56 + {
  57 + label: '成功',
  58 + value: 0,
  59 + },
  60 + {
  61 + label: '失败',
  62 + value: 0,
  63 + },
  64 + ],
  65 + placeholder: '请选择执行状态',
  66 + },
  67 + },
  68 + {
  69 + field: '3',
  70 + label: '执行时间',
  71 + component: 'RangePicker',
  72 + componentProps: {
  73 + showTime: {
  74 + defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')],
  75 + },
  76 + },
  77 + colProps: { span: 6 },
  78 + },
  79 +];
... ...
  1 +<template>
  2 + <div>
  3 + <BasicTable :clickToRowSelect="false" @register="registerTable" :searchInfo="searchInfo">
  4 + <template #toolbar>
  5 + <Authority value="api:yt:reportExport:export">
  6 + <a-button type="primary" @click="exportCharts"> 导出报表 </a-button>
  7 + </Authority>
  8 + <Authority value="api:yt:reportExport:delete">
  9 + <Popconfirm
  10 + title="您确定要批量删除数据"
  11 + ok-text="确定"
  12 + cancel-text="取消"
  13 + @confirm="handleDeleteOrBatchDelete(null)"
  14 + >
  15 + <a-button type="primary" color="error" :disabled="hasBatchDelete"> 批量删除 </a-button>
  16 + </Popconfirm>
  17 + </Authority>
  18 + </template>
  19 + <template #action="{ record }">
  20 + <TableAction
  21 + :actions="[
  22 + {
  23 + label: '查看',
  24 + icon: 'clarity:note-edit-line',
  25 + auth: 'api:yt:reportExport:get',
  26 + onClick: handleView.bind(null, record),
  27 + },
  28 + {
  29 + label: '导出报表',
  30 + icon: 'clarity:note-edit-line',
  31 + auth: 'api:yt:reportExport:export',
  32 + },
  33 + {
  34 + label: '删除',
  35 + icon: 'ant-design:delete-outlined',
  36 + auth: 'api:yt:reportExport:delete',
  37 + color: 'error',
  38 + popConfirm: {
  39 + title: '是否确认删除',
  40 + confirm: handleDeleteOrBatchDelete.bind(null, record),
  41 + },
  42 + },
  43 + ]"
  44 + />
  45 + </template>
  46 + </BasicTable>
  47 + <ReportPreviewModal @register="registerModal" />
  48 + </div>
  49 +</template>
  50 +
  51 +<script lang="ts" setup>
  52 + import { reactive, nextTick } from 'vue';
  53 + import { BasicTable, useTable, TableAction } from '/@/components/Table';
  54 + import { cameraPage, deleteCameraManage } from '/@/api/camera/cameraManager';
  55 + import { searchFormSchema, columns } from './config.data';
  56 + import { Authority } from '/@/components/Authority';
  57 + import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
  58 + import { Popconfirm } from 'ant-design-vue';
  59 + import { useModal } from '/@/components/Modal';
  60 + import ReportPreviewModal from './ReportPreviewModal.vue';
  61 +
  62 + const searchInfo = reactive<Recordable>({});
  63 +
  64 + const [registerTable, { reload, setProps }] = useTable({
  65 + title: '报表导出列表',
  66 + api: cameraPage,
  67 + columns,
  68 + showIndexColumn: false,
  69 + clickToRowSelect: false,
  70 + formConfig: {
  71 + labelWidth: 120,
  72 + schemas: searchFormSchema,
  73 + },
  74 + useSearchForm: true,
  75 + showTableSetting: true,
  76 + bordered: true,
  77 + rowKey: 'id',
  78 + actionColumn: {
  79 + width: 200,
  80 + title: '操作',
  81 + dataIndex: 'action',
  82 + slots: { customRender: 'action' },
  83 + fixed: 'right',
  84 + },
  85 + });
  86 +
  87 + const handleSuccess = () => {
  88 + reload();
  89 + };
  90 +
  91 + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
  92 + deleteCameraManage,
  93 + handleSuccess,
  94 + setProps
  95 + );
  96 +
  97 + nextTick(() => {
  98 + setProps(selectionOptions);
  99 + });
  100 +
  101 + const [registerModal, { openModal }] = useModal();
  102 + const handleView = (_, record) => {
  103 + openModal(true, {
  104 + isUpdate: true,
  105 + record,
  106 + });
  107 + };
  108 + const exportCharts = () => {};
  109 +</script>
... ...