Przeglądaj źródła

feat(components):新增箭头组件

HMY 7 miesięcy temu
rodzic
commit
f7dff67294

+ 1 - 0
admin/src/main/java/com/dcs/hnyz/service/impl/ConfigurationPageServiceImpl.java

@@ -124,6 +124,7 @@ public class ConfigurationPageServiceImpl implements IConfigurationPageService {
 
                     if (ext.getEquipmentId() != null) {
                         Equipment eq = equipmentMap.get(ext.getEquipmentId());
+                        if (eq == null) throw new CustomException("设备库数据缺少");
                         vo.setEquipmentName(eq.getEquipmentName());
                         vo.setCode(eq.getCode());
                         vo.setTitle(eq.getTitle());

+ 171 - 0
ui/src/components/GeneralComponents/Arrow2Component.vue

@@ -0,0 +1,171 @@
+<template>
+  <div class="arrow-container" :style="containerStyle" @click="handleClick" ref="containerRef">
+    <div class="arrow-wrapper" :style="wrapperStyle">
+      <!-- 长方形文本区域 -->
+      <div class="rectangle" :style="rectangleStyle" ref="rectangleRef">
+        <span class="arrowText" :style="arrowTextStyle" :class="{ 'vertical-text': isVerticalRotation }">{{
+          props.arrowText }}</span>
+      </div>
+      <!-- 三角形箭头 -->
+      <div class="triangle" :style="triangleStyle"></div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useRouter } from 'vue-router'
+import { computed, ref, watchEffect } from 'vue'
+
+const router = useRouter()
+const rectangleRef = ref(null)
+const rectangleHeight = ref(0)
+const rectangleWidth = ref(0)
+
+// 动态获取长方形尺寸
+watchEffect(() => {
+  if (rectangleRef.value) {
+    // 使用requestAnimationFrame确保DOM已更新
+    requestAnimationFrame(() => {
+      rectangleHeight.value = rectangleRef.value.offsetHeight
+      rectangleWidth.value = rectangleRef.value.offsetWidth
+    })
+  }
+})
+
+const props = defineProps({
+  arrowText: {
+    type: String,
+    default: ''
+  },
+  iconSize: {
+    type: Number,
+    default: 16
+  },
+  bgColor: {
+    type: String,
+    default: '#ff6200'
+  },
+  linkUrl: {
+    type: String,
+    default: ''
+  },
+  specialCondition: {
+    type: Object,
+    default: () => ({})
+  }
+})
+
+// 使用 specialCondition 中的配置
+const realBgColor = computed(() => props.specialCondition.bgColor || props.bgColor)
+const realLinkUrl = computed(() => props.specialCondition.linkUrl || props.linkUrl)
+const arrowRotate = computed(() => props.specialCondition.arrowRotate || 0)
+
+// 判断是否为竖直旋转状态(90度或270度)
+const isVerticalRotation = computed(() => {
+  const normalizedRotate = ((arrowRotate.value % 360) + 360) % 360; // 标准化角度为0-360度
+  return normalizedRotate === 90 || normalizedRotate === 270;
+})
+
+// 容器样式
+const containerStyle = computed(() => ({
+  display: 'inline-block',
+  cursor: realLinkUrl.value ? 'pointer' : 'default',
+  userSelect: 'none'
+}))
+
+// 整个箭头的旋转(不包含文字)
+const wrapperStyle = computed(() => ({
+  display: 'inline-flex',
+  alignItems: 'center',
+  transform: `rotate(${arrowRotate.value}deg)`,
+  transformOrigin: 'center center'
+}))
+
+// 长方形样式
+const rectangleStyle = computed(() => ({
+  backgroundColor: realBgColor.value,
+  padding: isVerticalRotation.value ? '8px 6px' : '6px 12px',
+  borderRadius: '4px',
+  display: 'flex',
+  alignItems: 'center',
+  justifyContent: 'center',
+  // 竖直旋转时允许文字换行
+  whiteSpace: isVerticalRotation.value ? 'normal' : 'nowrap'
+}))
+
+// 文字样式 - 反向旋转抵消容器的旋转效果
+const arrowTextStyle = computed(() => ({
+  color: '#fff',
+  fontSize: `${props.iconSize * 0.25}px`,
+  lineHeight: '1.2', // 增加行高便于多行显示
+  // 反向旋转使文字保持正常方向
+  transform: `rotate(${(arrowRotate.value > 90 && arrowRotate.value < 270 ? 180 : 0)}deg)`,
+  transformOrigin: 'center center',
+  // 竖直状态下限制最大宽度以便换行
+  maxWidth: isVerticalRotation.value ? `${props.iconSize * 2}px` : 'auto'
+}))
+
+// 三角形箭头样式 - 与长方形高度一致且随旋转改变指向
+const triangleStyle = computed(() => {
+  const color = realBgColor.value;
+
+  // 三角形高度与长方形高度完全一致
+  // 三角形宽度为高度的40%,保持合适比例
+  const height = rectangleHeight.value;
+  const width = height * 0.4;
+
+  const baseArrowStyle = {
+    width: 0,
+    height: 0,
+    borderTop: `${height / 2}px solid transparent`,
+    borderBottom: `${height / 2}px solid transparent`,
+    borderLeft: `${width}px solid ${color}`,
+    flexShrink: 0,
+    marginLeft: '-1px'
+  };
+  return { ...baseArrowStyle }
+})
+
+// 点击跳转
+const handleClick = () => {
+  if (realLinkUrl.value) {
+    router.push(realLinkUrl.value)
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.arrow-container {
+
+  .rectangle {
+    min-width: 100px;
+  }
+
+  .rectangle,
+  .triangle {
+    transition: all 0.2s ease;
+  }
+
+  &:hover {
+
+    .rectangle,
+    .triangle {
+      filter: brightness(1.1);
+    }
+  }
+
+  &:active {
+
+    .rectangle,
+    .triangle {
+      filter: brightness(0.9);
+    }
+  }
+}
+
+// 竖直排布文字的特殊样式
+.vertical-text {
+  text-align: center;
+  word-break: break-word; // 允许在单词内换行
+}
+</style>

+ 1 - 0
ui/src/hooks/useComponentHelper.js

@@ -37,6 +37,7 @@ const componentMap = {
     HeatExchangeWaterTank: lazyComponent(() => import('@/components/GeneralComponents/HeatExchangeWaterTankComponent.vue')),
     ButterflyValve: lazyComponent(() => import('@/components/GeneralComponents/ButterflyValveComponent.vue')),//蝶阀
     BeltFilter: lazyComponent(() => import('@/components/GeneralComponents/BeltFilterComponent.vue')),//平真空带式过滤器
+    Arrow2 : lazyComponent(() => import('@/components/GeneralComponents/Arrow2Component.vue')),//箭头2
 };
 
 export function useComponentHelper(modelMapRef) {

+ 32 - 7
ui/src/views/dcsForm2/equipmentExtension/index.vue

@@ -130,23 +130,43 @@
         <el-form-item label="特殊条件" prop="specialCondition">
           <div v-for="(item, index) in keyValueList" :key="index" style="margin-bottom: 8px;">
             <el-row :gutter="8" align="middle">
+              <!-- key 选择 -->
               <el-col :span="10">
                 <el-select v-model="item.key" placeholder="Key" filterable allow-create style="width: 130px;">
                   <el-option v-for="key in keyOptions" :key="key" :label="key" :value="key" />
                 </el-select>
               </el-col>
+
+              <!-- value 根据 key 类型切换 -->
               <el-col :span="10">
-                <el-select v-model="item.value" placeholder="Value" filterable allow-create style="width: 130px;">
-                  <el-option v-for="val in valueOptions" :key="val" :label="val" :value="val" />
-                </el-select>
+                <!-- 颜色选择器 -->
+                <template v-if="item.key === 'bgColor'">
+                  <el-color-picker v-model="item.value" show-alpha
+                    :predefine="['#c69f03','#409EFF', '#67C23A', '#ff6200', '#F56C6C','#cdcdcd']" />
+                </template>
+
+                <!-- 数字输入框 -->
+                <template v-else-if="item.key === 'arrowRotate'">
+                  <el-input-number v-model="item.value" :min="0" :max="360" />
+                </template>
+
+                <!-- 默认下拉选择 -->
+                <template v-else>
+                  <el-select v-model="item.value" placeholder="Value" filterable allow-create style="width: 130px;">
+                    <el-option v-for="val in valueOptions" :key="val" :label="val" :value="val" />
+                  </el-select>
+                </template>
               </el-col>
+
+              <!-- 删除按钮 -->
               <el-col :span="4">
                 <el-button type="danger" @click="removeItem(index)">删除</el-button>
               </el-col>
             </el-row>
           </div>
 
-          <el-row>
+          <!-- 添加条件 -->
+          <el-row class="add_condition">
             <el-col :span="24">
               <el-button type="primary" plain @click="addItem">添加条件</el-button>
             </el-col>
@@ -154,6 +174,7 @@
         </el-form-item>
 
 
+
         <el-form-item label="备注" prop="remark">
           <el-input v-model="form.remark" placeholder="请输入备注" />
         </el-form-item>
@@ -255,7 +276,7 @@ const data = reactive({
     pageSize: 10,
     equipmentId: null,
     equipmentName: null,
-    pageId: 19,
+    pageId: 23,
     pageName: null,
     status: null,
   },
@@ -279,7 +300,7 @@ const { queryParams, form, rules } = toRefs(data);
 
 const keyValueList = ref([{ key: '', value: '' }])
 //TODO linkUrl改为路由和url
-const keyOptions = ['flexDir', 'iconFirst', 'arrowRotate', 'linkUrl']
+const keyOptions = ['flexDir', 'iconFirst', 'arrowRotate', 'linkUrl', 'bgColor']
 const valueOptions = ['row', 'column', 'true', 'false']
 watch(
   keyValueList,
@@ -322,7 +343,7 @@ function reset() {
   form.value = {
     id: null,
     equipmentId: null,
-    pageId: 18,
+    pageId: 23,
     rotate: 0,
     x: 20,
     y: 20,
@@ -470,4 +491,8 @@ function formatNumber(val) {
 ::v-deep(.sizeInput .el-input__inner) {
   text-align: left;
 }
+
+.add_condition {
+  width: -webkit-fill-available;
+}
 </style>

+ 10 - 8
ui/src/views/dcsForm2/flow/index.vue

@@ -9,10 +9,8 @@
           <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
         </el-select>
       </el-form-item>
-      <el-form-item label="流程种类" prop="flowType">
-        <el-select v-model="queryParams.flowType" placeholder="流程种类" clearable style="width: 240px">
-          <el-option v-for="dict in flow_type" :key="dict.value" :label="dict.label" :value="dict.value" />
-        </el-select>
+      <el-form-item label="流程归属" prop="flowAttribution">
+        <el-input v-model="queryParams.flowAttribution" placeholder="请输入流程归属" clearable @keyup.enter="handleQuery" />
       </el-form-item>
       <el-form-item>
         <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
@@ -43,6 +41,7 @@
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="流程id" align="center" prop="flowId" />
       <el-table-column label="流程名称" align="center" prop="flowName" />
+      <el-table-column label="流程标识" align="center" prop="flowCode" />
       <el-table-column label="流程顺序" align="center" prop="sort" />
       <el-table-column label="启用状态" align="center" width="100">
         <template #default="scope">
@@ -70,12 +69,15 @@
         <el-form-item label="流程名称" prop="flowName">
           <el-input v-model="form.flowName" placeholder="请输入流程名称" />
         </el-form-item>
+        <el-form-item label="流程标识" prop="flowCode">
+          <el-input v-model="form.flowCode" placeholder="请输入流程标识" />
+        </el-form-item>
         <el-form-item label="流程顺序" prop="sort">
           <el-input v-model="form.sort" placeholder="请输入流程顺序" type="number" />
         </el-form-item>
-        <el-form-item label="流程种类" prop="flowType">
-          <el-select v-model="form.flowType" placeholder="请选择流程种类">
-            <el-option v-for="dict in flow_type" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
+        <el-form-item label="流程归属" prop="flowAttribution">
+          <el-select v-model="form.flowAttribution" placeholder="请选择流程归属">
+            <el-option v-for="dict in flow_attribution" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
           </el-select>
         </el-form-item>
         <el-form-item label="备注" prop="remark">
@@ -102,7 +104,7 @@
 import { changeStatus, listFlow, getFlow, delFlow, addFlow, updateFlow } from "@/api/hnyz/flow";
 const { proxy } = getCurrentInstance();
 const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
-const { flow_type } = proxy.useDict("flow_type")
+const { flow_attribution } = proxy.useDict("flow_attribution")
 const flowList = ref([]);
 const open = ref(false);
 const loading = ref(true);