Browse Source

合并分支

Shinohara Haruna 6 months ago
parent
commit
fa72e2e46e

+ 7 - 13
smsb-modules/smsb-source/src/main/java/com/inspur/source/service/impl/SmsbItemPushServiceImpl.java

@@ -61,16 +61,11 @@ import org.flowable.task.api.TaskQuery;
 import org.flowable.task.service.impl.persistence.entity.TaskEntity;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.cache.annotation.CachePut;
-import org.springframework.cache.annotation.Cacheable;
 import org.springframework.context.event.EventListener;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.time.Duration;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
+import java.time.*;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -368,13 +363,12 @@ public class SmsbItemPushServiceImpl implements ISmsbItemPushService {
     }
 
     private String getHourTimeStrByUTC(String utcTime) {
-        // 2025-03-20T16:00:00.000Z
-        // 解析UTC时间字符串
-        LocalDateTime localDateTime = LocalDateTime.parse(utcTime, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
-        // 将UTC时间转换为北京时间(UTC+8)
-        ZonedDateTime beijingTime = localDateTime.atZone(ZoneId.of("UTC+8"));
-        // 格式化时间为时分秒字符串
-        return beijingTime.format(DateTimeFormatter.ofPattern("HH:mm:ss"));
+        OffsetDateTime offsetDateTime = OffsetDateTime.parse(utcTime);
+        OffsetDateTime beijingTime = offsetDateTime.withOffsetSameInstant(ZoneOffset.of("+08:00"));
+        LocalTime localTime = beijingTime.toLocalTime();
+        // 使用DateTimeFormatter将LocalTime格式化为时分秒字符串
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
+        return localTime.format(formatter);
     }
 
     /**

+ 6 - 0
smsb-plus-ui/src/api/smsb/source/item_push_type.ts

@@ -35,6 +35,12 @@ export interface ItemPushVO {
   createUser: string;
 
   taskId: number;
+
+  deviceList ?: any;
+
+  resourceList ?: any;
+
+  timeList ?: any;
 }
 
 export interface PushTimeVO {

+ 6 - 0
smsb-plus-ui/src/router/index.ts

@@ -187,6 +187,12 @@ export const dynamicRoutes: RouteRecordRaw[] = [
         path: 'review',
         component: () => import('@/views/smsb/itemPush/review.vue'),
         name: 'review',
+        meta: { title: '审核详情', activeMenu: '/source/review', icon: '' }
+      },
+      {
+        path: 'approval',
+        component: () => import('@/views/smsb/itemPush/approval.vue'),
+        name: 'approval',
         meta: { title: '内容审核', activeMenu: '/source/review', icon: '' }
       }
     ]

+ 332 - 0
smsb-plus-ui/src/views/smsb/itemPush/approval.vue

@@ -0,0 +1,332 @@
+<template>
+  <div class="p-2">
+    <el-card shadow="always" style="height: 50px">
+      <div style="display: flex; justify-content: space-between">
+        <div>
+          <!--          <el-button v-if="submitButtonShow" :loading="buttonLoading" type="info" @click="submitForm('draft')">暂存</el-button>-->
+          <!--          <el-button v-if="submitButtonShow" :loading="buttonLoading" type="primary" @click="submitForm('submit')">提 交</el-button>-->
+          <el-button v-if="approvalButtonShow" :loading="buttonLoading" type="primary" @click="approvalVerifyOpen"> 审批
+          </el-button>
+          <el-button v-if="itemPushBase && itemPushBase.id && itemPushBase.status !== 'draft'" type="primary"
+                     @click="handleApprovalRecord">
+            流程进度
+          </el-button>
+        </div>
+        <div>
+          <el-button style="float: right" @click="goBack()">返回</el-button>
+        </div>
+      </div>
+    </el-card>
+    <!-- push base -->
+    <el-card shadow="always" class="custom-card">
+      <div v-if="loading" class="loading-text">数据加载中...</div>
+      <div v-else class="card-content">
+        <div class="info-item">
+          <strong>名称:</strong>
+          <el-text>{{ itemPushBase.name }}</el-text>
+        </div>
+        <div class="info-item">
+          <strong>类型:</strong>
+          <el-text v-for="dict in smsb_push_type" :key="dict.value" :label="dict.label" :value="dict.value">
+            <div v-if="parseInt(dict.value) === itemPushBase.itemType">
+              {{ dict.label }}
+            </div>
+          </el-text>
+        </div>
+        <div class="info-item">
+          <strong>优先级:</strong>
+          <el-text v-for="dict in smsb_push_level" :key="dict.value" :label="dict.label" :value="dict.value">
+            <div v-if="parseInt(dict.value) === itemPushBase.level">
+              {{ dict.label }}
+            </div>
+          </el-text>
+        </div>
+        <div class="info-item">
+          <strong>发布时间:</strong>
+          <el-text>{{ itemPushBase.createTime }}</el-text>
+        </div>
+        <div class="info-item">
+          <strong>发布人:</strong>
+          <el-text>{{ itemPushBase.createUser }}</el-text>
+        </div>
+        <div class="info-item">
+          <strong>状态:</strong>
+          <el-text v-for="dict in smsb_push_state" :key="dict.value" :label="dict.label" :value="dict.value">
+            <div v-if="dict.value === itemPushBase.status">
+              {{ dict.label }}
+            </div>
+          </el-text>
+        </div>
+      </div>
+    </el-card>
+    <!-- deviceList timeList sourceList -->
+    <el-card shadow="always" class="custom-card" style="height: 70vh; overflow-y: auto; margin-top: 10px">
+      <div class="card-section">
+        <!-- 第一部分 时间排期 -->
+        <div class="section-content">
+          <div v-for="(item, index) in timeList" :key="index">{{ item.start }} - {{ item.end }}</div>
+        </div>
+        <!-- 第二部分内容 -->
+        <div class="section-content">
+          <el-table v-loading="loading" :data="deviceList">
+            <el-table-column label="设备名称" align="left" prop="name" :show-overflow-tooltip="true"/>
+          </el-table>
+        </div>
+        <!-- 第三部分内容 -->
+        <div class="section-content">
+          <el-table v-loading="loading" :data="sourceList">
+            <el-table-column label="原名" align="left" prop="originalName" width="150" :show-overflow-tooltip="true"/>
+            <el-table-column label="类型" align="center" prop="type" width="80">
+              <template #default="scope">
+                <dict-tag :options="smsb_source_type" :value="scope.row.type"/>
+              </template>
+            </el-table-column>
+            <el-table-column label="大小" align="center" prop="size"/>
+            <el-table-column label="截图" align="center" prop="screenshot">
+              <template #default="scope">
+                <image-preview :src="scope.row.screenshot" style="width: 40px; height: 40px; cursor: pointer"/>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </div>
+    </el-card>
+    <!-- 提交组件 -->
+    <SubmitVerifySmsb ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback"/>
+    <!-- 审批记录 -->
+    <approvalRecordSmsb ref="approvalRecordRef"/>
+  </div>
+</template>
+
+<script setup name="Leave" lang="ts">
+import {addLeave, updateLeave} from '@/api/workflow/leave';
+import {LeaveVO} from '@/api/workflow/leave/types';
+import {startWorkFlow} from '@/api/workflow/task';
+import SubmitVerifySmsb from '@/views/smsb/itemReview/submitVerifySmsb.vue';
+import ApprovalRecordSmsb from '@/views/smsb/itemReview/approvalRecordSmsb.vue';
+import {AxiosResponse} from 'axios';
+import {StartProcessBo} from '@/api/workflow/workflowCommon/types';
+import {getItemPushReview} from '@/api/smsb/source/item_push';
+import {ItemPushForm, ItemPushQuery, ItemPushTimeRangeVO, ItemPushVO} from '@/api/smsb/source/item_push_type';
+import {DeviceVO} from '@/api/smsb/device/device_type';
+import {MinioDataVO} from '@/api/smsb/source/minioData_type';
+import {ElTable} from 'element-plus';
+
+const {proxy} = getCurrentInstance() as ComponentInternalInstance;
+const {smsb_push_type, smsb_push_level, smsb_push_state, smsb_source_type} = toRefs<any>(
+  proxy?.useDict('smsb_push_type', 'smsb_push_level', 'smsb_push_state', 'smsb_source_type')
+);
+const approvalButtonShow = ref(false);
+const buttonLoading = ref(false);
+const loading = ref(true);
+//路由参数
+const routeParams = ref<Record<string, any>>({});
+const itemPushBase = ref<ItemPushVO>();
+const deviceList = ref<DeviceVO[]>([]);
+const sourceList = ref<MinioDataVO[]>([]);
+const timeList = ref<ItemPushTimeRangeVO[]>([]);
+
+//提交组件
+const submitVerifyRef = ref<InstanceType<typeof SubmitVerifySmsb>>();
+//审批记录组件
+const approvalRecordRef = ref<InstanceType<typeof ApprovalRecordSmsb>>();
+
+const itemPushFormRef = ref<ElFormInstance>();
+
+const submitFormData = ref<StartProcessBo>({
+  businessKey: '',
+  tableName: '',
+  variables: {}
+});
+const taskVariables = ref<Record<string, any>>({});
+
+const initFormData: ItemPushForm = {
+  name: undefined,
+  level: undefined,
+  itemType: undefined,
+  deviceIds: undefined,
+  itemIds: undefined,
+  dateRange: undefined,
+  weekDays: ['1', '2', '3', '4', '5', '6', '7'],
+  timeRange: [],
+  status: undefined
+};
+const data = reactive<PageData<ItemPushForm, ItemPushQuery>>({
+  form: {...initFormData},
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10
+  },
+  rules: {}
+});
+
+const {form, rules} = toRefs(data);
+
+/** 表单重置 */
+const reset = () => {
+  form.value = {...initFormData}
+};
+
+/** 获取详情 */
+const getInfo = () => {
+  loading.value = true;
+  buttonLoading.value = false;
+  nextTick(async () => {
+    const res = await getItemPushReview(routeParams.value.id);
+    itemPushBase.value = res.data;
+    deviceList.value = res.data.deviceList;
+    sourceList.value = res.data.resourceList;
+    timeList.value = res.data.timeList;
+    loading.value = false;
+    buttonLoading.value = false;
+    if (itemPushBase.value.status && itemPushBase.value.status === 'waiting') {
+      approvalButtonShow.value = true;
+    } else {
+      approvalButtonShow.value = false;
+    }
+  });
+};
+
+/** 提交按钮 */
+const submitForm = (status: string) => {
+  try {
+    itemPushFormRef.value?.validate(async (valid: boolean) => {
+      if (valid) {
+        buttonLoading.value = true;
+        let res: AxiosResponse<LeaveVO>;
+        if (form.value.id) {
+          res = await updateLeave(form.value);
+        } else {
+          res = await addLeave(form.value);
+        }
+        form.value = res.data;
+        if (status === 'draft') {
+          buttonLoading.value = false;
+          proxy?.$modal.msgSuccess('暂存成功');
+          proxy.$tab.closePage(proxy.$route);
+          proxy.$router.go(-1);
+        } else {
+          await handleStartWorkFlow(res.data);
+        }
+      }
+    });
+  } finally {
+    buttonLoading.value = false;
+    goBack();
+  }
+};
+
+//提交申请
+const handleStartWorkFlow = async (data: LeaveVO) => {
+  try {
+    submitFormData.value.tableName = 'test_leave';
+    submitFormData.value.businessKey = data.id;
+    //流程变量
+    taskVariables.value = {
+      entity: data,
+      leaveDays: data.leaveDays,
+      userList: ['1', '3'],
+      userList2: ['1', '3']
+    };
+    submitFormData.value.variables = taskVariables.value;
+    const resp = await startWorkFlow(submitFormData.value);
+    if (submitVerifyRef.value) {
+      buttonLoading.value = false;
+      submitVerifyRef.value.openDialog(resp.data.taskId);
+    }
+  } finally {
+    buttonLoading.value = false;
+  }
+};
+//审批记录
+const handleApprovalRecord = () => {
+  approvalRecordRef.value.init(itemPushBase.value.id);
+};
+//提交回调
+const submitCallback = async () => {
+  await proxy.$tab.closePage(proxy.$route);
+  proxy.$router.go(-1);
+};
+
+//返回
+const goBack = () => {
+  proxy.$tab.closePage(proxy.$route);
+  proxy.$router.go(-1);
+};
+//审批
+const approvalVerifyOpen = async () => {
+  submitVerifyRef.value.openDialog(routeParams.value.taskId);
+};
+//校验提交按钮是否显示
+const submitButtonShow = computed(() => {
+  return (
+    routeParams.value.type === 'add' ||
+    (routeParams.value.type === 'update' &&
+      form.value.status &&
+      (form.value.status === 'draft' || form.value.status === 'cancel' || form.value.status === 'back'))
+  );
+});
+
+//校验审批按钮是否显示
+/*const approvalButtonShow = computed(() => {
+  return routeParams.value.type === 'approval';
+});*/
+
+onMounted(() => {
+  nextTick(async () => {
+    routeParams.value = proxy.$route.query;
+    reset();
+    loading.value = false;
+    if (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval') {
+      getInfo();
+    }
+  });
+});
+</script>
+
+<style scoped>
+.custom-card {
+  margin-top: 20px;
+  border-radius: 8px;
+}
+
+.card-content {
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: space-between;
+}
+
+.info-item {
+  flex: 1 1 16%; /* 每个项目至少占容器的16%,允许伸缩 */
+  margin: 5px 0;
+  box-sizing: border-box;
+  padding-right: 10px; /* 避免内容重叠 */
+}
+
+.info-item strong {
+  display: block; /* 将 strong 标签换行,以便内容更易读 */
+}
+
+.loading-text {
+  padding: 10px;
+  text-align: center;
+  font-size: 14px;
+  color: #909399;
+}
+
+.card-section {
+  display: flex;
+  flex: 1;
+  overflow-y: auto;
+}
+
+.section-content {
+  flex: 1;
+  padding: 10px;
+  border-right: 1px solid #ebeef5; /* 可选:添加分隔线 */
+}
+
+.section-content:last-child {
+  border-right: none; /* 移除最后一个元素的分隔线 */
+}
+</style>

+ 22 - 31
smsb-plus-ui/src/views/smsb/itemPush/index.vue

@@ -290,17 +290,25 @@
 </template>
 
 <script setup name="ItemPush" lang="ts">
-import { addItemPush, delItemPush, getItemPush, listItemPush, pushStatistics, reviewItemPush, updateItemPush } from '@/api/smsb/source/item_push';
-import { ItemPushForm, ItemPushQuery, ItemPushVO } from '@/api/smsb/source/item_push_type';
-import { DeviceQuery, DeviceVO } from '@/api/smsb/device/device_type';
-import { listDevice } from '@/api/smsb/device/device';
-import { ItemQuery, ItemVO } from '@/api/smsb/source/item_type';
-import { listItem } from '@/api/smsb/source/item';
-import { ItemPushDeviceVO } from '@/api/smsb/source/item_push_device_type';
-import { listItemPushDeviceV2, removeItemPushDevice } from '@/api/smsb/source/item_push_device';
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { smsb_push_state, smsb_push_device_state, smsb_push_type, smsb_push_level } = toRefs<any>(
+import {
+  addItemPush,
+  delItemPush,
+  getItemPush,
+  listItemPush,
+  pushStatistics,
+  reviewItemPush,
+  updateItemPush
+} from '@/api/smsb/source/item_push';
+import {ItemPushForm, ItemPushQuery, ItemPushVO} from '@/api/smsb/source/item_push_type';
+import {DeviceQuery, DeviceVO} from '@/api/smsb/device/device_type';
+import {listDevice} from '@/api/smsb/device/device';
+import {ItemQuery, ItemVO} from '@/api/smsb/source/item_type';
+import {listItem} from '@/api/smsb/source/item';
+import {ItemPushDeviceVO} from '@/api/smsb/source/item_push_device_type';
+import {listItemPushDeviceV2, removeItemPushDevice} from '@/api/smsb/source/item_push_device';
+
+const {proxy} = getCurrentInstance() as ComponentInternalInstance;
+const {smsb_push_state, smsb_push_device_state, smsb_push_type, smsb_push_level} = toRefs<any>(
   proxy?.useDict('smsb_push_state', 'smsb_push_device_state', 'smsb_push_type', 'smsb_push_level')
 );
 
@@ -346,8 +354,8 @@ const deviceDialog = reactive<DialogOption>({
 
 const initFormData: ItemPushForm = {
   name: undefined,
-  level: undefined,
-  itemType: 2, // "分屏组"类型
+  level: 200,
+  itemType: 1, // "分屏组"类型
   deviceIds: undefined,
   itemIds: undefined,
   dateRange: undefined,
@@ -568,24 +576,6 @@ const handleUpdate = async (row?: ItemPushVO) => {
 const submitForm = () => {
   itemPushFormRef.value?.validate(async (valid: boolean) => {
     if (valid) {
-      /*const options: Intl.DateTimeFormatOptions = {
-        timeZone: 'Asia/Shanghai',
-        year: 'numeric',
-        month: '2-digit',
-        day: '2-digit',
-        hour: '2-digit',
-        minute: '2-digit',
-        second: '2-digit'
-      };
-      const formatter = new Intl.DateTimeFormat('zh-CN', options);
-      let startDate = formatter.format(form.value.timeRange.start);
-      startDate = startDate.replace(/\//g, '-');
-      startDate = startDate.replace(/:/g, '-');
-      console.log("startDate : " + startDate);
-      let endDate = formatter.format(form.value.timeRange.end);
-      endDate = endDate.replace(/\//g, '-');
-      endDate = endDate.replace(/:/g, '-');
-      console.log("endDate : " + endDate)*/
       buttonLoading.value = true;
       if (form.value.id) {
         await updateItemPush(form.value).finally(() => (buttonLoading.value = false));
@@ -634,6 +624,7 @@ const handleExport = () => {
 onMounted(() => {
   getList();
   getStatistics();
+  getItemList();
 });
 </script>
 <style scoped>

+ 2 - 0
smsb-plus-ui/src/views/smsb/itemPush/review.vue

@@ -5,7 +5,9 @@
         <div>
           <!--          <el-button v-if="submitButtonShow" :loading="buttonLoading" type="info" @click="submitForm('draft')">暂存</el-button>-->
           <!--          <el-button v-if="submitButtonShow" :loading="buttonLoading" type="primary" @click="submitForm('submit')">提 交</el-button>-->
+<!--
           <el-button v-if="approvalButtonShow" :loading="buttonLoading" type="primary" @click="approvalVerifyOpen"> 审批 </el-button>
+-->
           <el-button v-if="itemPushBase && itemPushBase.id && itemPushBase.status !== 'draft'" type="primary" @click="handleApprovalRecord">
             流程进度
           </el-button>

+ 1 - 1
smsb-plus-ui/src/views/smsb/itemReview/index.vue

@@ -185,7 +185,7 @@ const handleApproval = (row?: ItemPushVO) => {
   const taskId = row.taskId;
   const status = row.status;
   // 跳转页面 /source/push/review?id=1898991996092481537&type=approval&taskId=1898992031169445891
-  proxy.$router.push('/source/push/review?id=' + id + '&type=approval&taskId=' + taskId);
+  proxy.$router.push('/source/push/approval?id=' + id + '&type=approval&taskId=' + taskId);
 };
 const handleClickTab = (tab: TabsPaneContext, event: Event) => {
   if (tab.props.name === 'need') {