Просмотр исходного кода

perf:【IoT 物联网】场景联动样式 unocss 化

puhui999 10 месяцев назад
Родитель
Сommit
751daf5fbb

+ 10 - 36
src/views/iot/rule/scene/components/configs/DeviceControlConfig.vue

@@ -1,7 +1,7 @@
 <!-- 设备控制配置组件 -->
 <!-- TODO @puhui999:貌似没生效~~~ -->
 <template>
-  <div class="device-control-config">
+  <div class="flex flex-col gap-16px">
     <!-- 产品和设备选择 -->
     <ProductDeviceSelector
       v-model:product-id="action.productId"
@@ -10,7 +10,7 @@
     />
 
     <!-- 控制参数配置 -->
-    <div v-if="action.productId && action.deviceId" class="control-params">
+    <div v-if="action.productId && action.deviceId" class="space-y-16px">
       <el-form-item label="控制参数" required>
         <el-input
           v-model="paramsJson"
@@ -22,14 +22,14 @@
       </el-form-item>
 
       <!-- 参数示例 -->
-      <div class="params-example">
+      <div class="mt-12px">
         <el-alert title="参数格式示例" type="info" :closable="false" show-icon>
           <template #default>
-            <div class="example-content">
-              <p>属性设置示例:</p>
-              <pre><code>{ "temperature": 25, "power": true }</code></pre>
-              <p>服务调用示例:</p>
-              <pre><code>{ "method": "restart", "params": { "delay": 5 } }</code></pre>
+            <div class="space-y-8px">
+              <p class="m-0 text-14px text-[var(--el-text-color-primary)]">属性设置示例:</p>
+              <pre class="m-0 p-8px bg-[var(--el-fill-color-light)] rounded-4px text-12px text-[var(--el-text-color-regular)] overflow-x-auto"><code>{ "temperature": 25, "power": true }</code></pre>
+              <p class="m-0 text-14px text-[var(--el-text-color-primary)]">服务调用示例:</p>
+              <pre class="m-0 p-8px bg-[var(--el-fill-color-light)] rounded-4px text-12px text-[var(--el-text-color-regular)] overflow-x-auto"><code>{ "method": "restart", "params": { "delay": 5 } }</code></pre>
             </div>
           </template>
         </el-alert>
@@ -37,7 +37,7 @@
     </div>
 
     <!-- 验证结果 -->
-    <div v-if="validationMessage" class="validation-result">
+    <div v-if="validationMessage" class="mt-16px">
       <el-alert
         :title="validationMessage"
         :type="isValid ? 'success' : 'error'"
@@ -140,34 +140,8 @@ watch(
 </script>
 
 <style scoped>
-.device-control-config {
-  display: flex;
-  flex-direction: column;
-  gap: 16px;
-}
-
-.control-params {
-  margin-top: 16px;
-}
-
-.params-example {
-  margin-top: 8px;
-}
-
-.example-content pre {
-  margin: 4px 0;
-  padding: 8px;
-  background: var(--el-fill-color-light);
-  border-radius: 4px;
-  font-size: 12px;
-}
-
-.example-content code {
+:deep(.example-content code) {
   font-family: 'Courier New', monospace;
   color: var(--el-color-primary);
 }
-
-.validation-result {
-  margin-top: 8px;
-}
 </style>

+ 9 - 80
src/views/iot/rule/scene/components/inputs/DescriptionInput.vue

@@ -1,6 +1,6 @@
 <!-- 场景描述输入组件 -->
 <template>
-  <div class="description-input">
+  <div class="relative w-full">
     <el-input
       ref="inputRef"
       v-model="localValue"
@@ -15,22 +15,22 @@
 
     <!-- 描述模板 -->
     <teleport to="body">
-      <div v-if="showTemplates" ref="templateDropdownRef" class="templates" :style="dropdownStyle">
-        <div class="templates-header">
-          <span class="templates-title">描述模板</span>
+      <div v-if="showTemplates" ref="templateDropdownRef" class="fixed z-1000 bg-white border border-[var(--el-border-color-light)] rounded-6px shadow-[var(--el-box-shadow)] min-w-300px max-w-400px" :style="dropdownStyle">
+        <div class="flex items-center justify-between p-12px border-b border-[var(--el-border-color-lighter)] bg-[var(--el-fill-color-light)]">
+          <span class="text-14px font-500 text-[var(--el-text-color-primary)]">描述模板</span>
           <el-button type="text" size="small" @click="showTemplates = false">
             <Icon icon="ep:close" />
           </el-button>
         </div>
-        <div class="templates-list">
+        <div class="max-h-300px overflow-y-auto">
           <div
             v-for="template in descriptionTemplates"
             :key="template.title"
-            class="template-item"
+            class="p-12px border-b border-[var(--el-border-color-lighter)] cursor-pointer transition-colors duration-200 hover:bg-[var(--el-fill-color-light)] last:border-b-0"
             @click="applyTemplate(template)"
           >
-            <div class="template-title">{{ template.title }}</div>
-            <div class="template-content">{{ template.content }}</div>
+            <div class="text-14px font-500 text-[var(--el-text-color-primary)] mb-4px">{{ template.title }}</div>
+            <div class="text-12px text-[var(--el-text-color-secondary)] leading-relaxed">{{ template.content }}</div>
           </div>
         </div>
       </div>
@@ -38,7 +38,7 @@
 
     <!-- TODO @puhui999:不用模版哈,简单点。。。 -->
     <!-- 模板按钮 -->
-    <div v-if="!localValue && !showTemplates" class="template-trigger">
+    <div v-if="!localValue && !showTemplates" class="absolute top-2px right-2px">
       <el-button type="text" size="small" @click="toggleTemplates">
         <Icon icon="ep:document" class="mr-1" />
         使用模板
@@ -175,75 +175,4 @@ onUnmounted(() => {
 })
 </script>
 
-<style scoped>
-.description-input {
-  position: relative;
-  width: 100%;
-}
-
-.templates {
-  position: fixed;
-  z-index: 9999;
-  background: white;
-  border: 1px solid var(--el-border-color-light);
-  border-radius: 6px;
-  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
-  min-width: 300px;
-  max-width: 400px;
-  max-height: 400px;
-  overflow: hidden;
-}
-
-.templates-header {
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  padding: 8px 12px;
-  border-bottom: 1px solid var(--el-border-color-lighter);
-  background: var(--el-fill-color-light);
-}
-
-.templates-title {
-  font-size: 12px;
-  color: var(--el-text-color-secondary);
-  font-weight: 500;
-}
-
-.templates-list {
-  max-height: 300px;
-  overflow-y: auto;
-}
-
-.template-item {
-  padding: 12px;
-  cursor: pointer;
-  transition: background-color 0.2s;
-  border-bottom: 1px solid var(--el-border-color-lighter);
-}
-
-.template-item:hover {
-  background: var(--el-fill-color-light);
-}
-
-.template-item:last-child {
-  border-bottom: none;
-}
 
-.template-title {
-  font-size: 14px;
-  font-weight: 500;
-  color: var(--el-text-color-primary);
-  margin-bottom: 4px;
-}
-
-.template-content {
-  font-size: 12px;
-  color: var(--el-text-color-secondary);
-  line-height: 1.4;
-}
-
-.template-trigger {
-  margin-top: 8px;
-  text-align: right;
-}
-</style>

+ 9 - 60
src/views/iot/rule/scene/components/previews/ActionPreview.vue

@@ -1,24 +1,24 @@
 <!-- 执行器预览组件 -->
 <template>
-  <div class="action-preview">
-    <div v-if="actions.length === 0" class="empty-preview">
+  <div class="w-full">
+    <div v-if="actions.length === 0" class="text-center py-20px">
       <el-text type="info" size="small">暂无执行器配置</el-text>
     </div>
-    <div v-else class="action-list">
+    <div v-else class="space-y-12px">
       <div
         v-for="(action, index) in actions"
         :key="index"
-        class="action-item"
+        class="p-12px border border-[var(--el-border-color-lighter)] rounded-6px bg-[var(--el-fill-color-blank)]"
       >
-        <div class="action-header">
-          <Icon icon="ep:setting" class="action-icon" />
-          <span class="action-title">执行器 {{ index + 1 }}</span>
+        <div class="flex items-center gap-8px mb-8px">
+          <Icon icon="ep:setting" class="text-[var(--el-color-success)] text-16px" />
+          <span class="text-14px font-500 text-[var(--el-text-color-primary)]">执行器 {{ index + 1 }}</span>
           <el-tag :type="getActionTypeTag(action.type)" size="small">
             {{ getActionTypeName(action.type) }}
           </el-tag>
         </div>
-        <div class="action-content">
-          <div class="action-summary">
+        <div class="pl-24px">
+          <div class="text-12px text-[var(--el-text-color-secondary)] leading-relaxed">
             {{ getActionSummary(action) }}
           </div>
         </div>
@@ -73,55 +73,4 @@ const getActionSummary = (action: ActionFormData) => {
 }
 </script>
 
-<style scoped>
-.action-preview {
-  width: 100%;
-}
-
-.empty-preview {
-  text-align: center;
-  padding: 20px 0;
-}
-
-.action-list {
-  display: flex;
-  flex-direction: column;
-  gap: 12px;
-}
-
-.action-item {
-  border: 1px solid var(--el-border-color-lighter);
-  border-radius: 4px;
-  background: var(--el-fill-color-blank);
-}
-
-.action-header {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-  padding: 8px 12px;
-  background: var(--el-fill-color-light);
-  border-bottom: 1px solid var(--el-border-color-lighter);
-}
-
-.action-icon {
-  color: var(--el-color-success);
-  font-size: 14px;
-}
-
-.action-title {
-  font-size: 12px;
-  font-weight: 500;
-  color: var(--el-text-color-primary);
-}
-
-.action-content {
-  padding: 8px 12px;
-}
 
-.action-summary {
-  font-size: 12px;
-  color: var(--el-text-color-secondary);
-  line-height: 1.4;
-}
-</style>

+ 18 - 121
src/views/iot/rule/scene/components/sections/ActionSection.vue

@@ -1,15 +1,15 @@
 <!-- 执行器配置组件 -->
 <!-- todo @puhui999:参考“触发器配置”,简化下。 -->
 <template>
-  <el-card class="action-section" shadow="never">
+  <el-card class="border border-[var(--el-border-color-light)] rounded-8px" shadow="never">
     <template #header>
-      <div class="section-header">
-        <div class="header-left">
-          <Icon icon="ep:setting" class="section-icon" />
-          <span class="section-title">执行器配置</span>
+      <div class="flex items-center justify-between">
+        <div class="flex items-center gap-8px">
+          <Icon icon="ep:setting" class="text-[var(--el-color-primary)] text-18px" />
+          <span class="text-16px font-600 text-[var(--el-text-color-primary)]">执行器配置</span>
           <el-tag size="small" type="info">{{ actions.length }}/{{ maxActions }}</el-tag>
         </div>
-        <div class="header-right">
+        <div class="flex items-center gap-8px">
           <el-button
             type="primary"
             size="small"
@@ -23,9 +23,9 @@
       </div>
     </template>
 
-    <div class="section-content">
+    <div class="p-0">
       <!-- 空状态 -->
-      <div v-if="actions.length === 0" class="empty-state">
+      <div v-if="actions.length === 0">
         <el-empty description="暂无执行器配置">
           <el-button type="primary" @click="addAction">
             <Icon icon="ep:plus" />
@@ -35,17 +35,17 @@
       </div>
 
       <!-- 执行器列表 -->
-      <div v-else class="actions-list">
-        <div v-for="(action, index) in actions" :key="`action-${index}`" class="action-item">
-          <div class="action-header">
-            <div class="action-title">
-              <Icon icon="ep:setting" class="action-icon" />
+      <div v-else class="space-y-16px">
+        <div v-for="(action, index) in actions" :key="`action-${index}`" class="p-16px border border-[var(--el-border-color-lighter)] rounded-6px bg-[var(--el-fill-color-blank)]">
+          <div class="flex items-center justify-between mb-16px">
+            <div class="flex items-center gap-8px">
+              <Icon icon="ep:setting" class="text-[var(--el-color-success)] text-16px" />
               <span>执行器 {{ index + 1 }}</span>
               <el-tag :type="getActionTypeTag(action.type)" size="small">
                 {{ getActionTypeName(action.type) }}
               </el-tag>
             </div>
-            <div class="action-actions">
+            <div>
               <el-button
                 type="danger"
                 size="small"
@@ -59,7 +59,7 @@
             </div>
           </div>
 
-          <div class="action-content">
+          <div class="space-y-16px">
             <!-- 执行类型选择 -->
             <ActionTypeSelector
               :model-value="action.type"
@@ -87,12 +87,12 @@
       </div>
 
       <!-- 添加提示 -->
-      <div v-if="actions.length > 0 && actions.length < maxActions" class="add-more">
-        <el-button type="primary" plain @click="addAction" class="add-more-btn">
+      <div v-if="actions.length > 0 && actions.length < maxActions" class="text-center py-16px">
+        <el-button type="primary" plain @click="addAction">
           <Icon icon="ep:plus" />
           继续添加执行器
         </el-button>
-        <span class="add-more-text"> 最多可添加 {{ maxActions }} 个执行器 </span>
+        <span class="block mt-8px text-12px text-[var(--el-text-color-secondary)]"> 最多可添加 {{ maxActions }} 个执行器 </span>
       </div>
 
       <!-- 验证结果 -->
@@ -266,107 +266,4 @@ watch(
 )
 </script>
 
-<style scoped>
-.action-section {
-  border: 1px solid var(--el-border-color-light);
-  border-radius: 8px;
-}
-
-.section-header {
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-}
-
-.header-left {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-}
-
-.section-icon {
-  color: var(--el-color-primary);
-  font-size: 18px;
-}
-
-.section-title {
-  font-size: 16px;
-  font-weight: 600;
-  color: var(--el-text-color-primary);
-}
-
-.header-right {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-}
-
-.section-content {
-  padding: 0;
-}
-
-.empty-state {
-  padding: 40px 0;
-  text-align: center;
-}
-
-.actions-list {
-  display: flex;
-  flex-direction: column;
-  gap: 16px;
-}
 
-.action-item {
-  border: 1px solid var(--el-border-color-lighter);
-  border-radius: 6px;
-  background: var(--el-fill-color-blank);
-}
-
-.action-header {
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  padding: 12px 16px;
-  background: var(--el-fill-color-light);
-  border-bottom: 1px solid var(--el-border-color-lighter);
-}
-
-.action-title {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-}
-
-.action-icon {
-  color: var(--el-color-success);
-  font-size: 16px;
-}
-
-.action-content {
-  padding: 16px;
-}
-
-.add-more {
-  display: flex;
-  align-items: center;
-  gap: 12px;
-  margin-top: 16px;
-  padding: 16px;
-  border: 1px dashed var(--el-border-color);
-  border-radius: 6px;
-  background: var(--el-fill-color-lighter);
-}
-
-.add-more-btn {
-  flex-shrink: 0;
-}
-
-.add-more-text {
-  font-size: 12px;
-  color: var(--el-text-color-secondary);
-}
-
-.validation-result {
-  margin-top: 16px;
-}
-</style>

+ 27 - 98
src/views/iot/rule/scene/components/sections/PreviewSection.vue

@@ -1,14 +1,14 @@
 <!-- 预览区域组件 -->
 <!-- TODO @puhui999:是不是不用这个哈? -->
 <template>
-  <el-card class="preview-section" shadow="never">
+  <el-card class="border border-[var(--el-border-color-light)] rounded-8px" shadow="never">
     <template #header>
-      <div class="section-header">
-        <div class="header-left">
-          <Icon icon="ep:view" class="section-icon" />
-          <span class="section-title">配置预览</span>
+      <div class="flex items-center justify-between">
+        <div class="flex items-center gap-8px">
+          <Icon icon="ep:view" class="text-[var(--el-color-primary)] text-18px" />
+          <span class="text-16px font-600 text-[var(--el-text-color-primary)]">配置预览</span>
         </div>
-        <div class="header-right">
+        <div class="flex items-center gap-8px">
           <el-button type="primary" size="small" @click="handleValidate" :loading="validating">
             <Icon icon="ep:check" />
             验证配置
@@ -17,49 +17,49 @@
       </div>
     </template>
 
-    <div class="section-content">
+    <div class="p-0">
       <!-- 基础信息预览 -->
-      <div class="preview-group">
-        <div class="group-header">
-          <Icon icon="ep:info-filled" class="group-icon" />
-          <span class="group-title">基础信息</span>
+      <div class="mb-20px">
+        <div class="flex items-center gap-8px mb-12px">
+          <Icon icon="ep:info-filled" class="text-[var(--el-color-info)] text-16px" />
+          <span class="text-14px font-500 text-[var(--el-text-color-primary)]">基础信息</span>
         </div>
-        <div class="group-content">
+        <div class="p-12px bg-[var(--el-fill-color-light)] rounded-6px">
           <ConfigPreview :form-data="formData" />
         </div>
       </div>
 
       <!-- 触发器预览 -->
-      <div class="preview-group">
-        <div class="group-header">
-          <Icon icon="ep:lightning" class="group-icon" />
-          <span class="group-title">触发器配置</span>
+      <div class="mb-20px">
+        <div class="flex items-center gap-8px mb-12px">
+          <Icon icon="ep:lightning" class="text-[var(--el-color-warning)] text-16px" />
+          <span class="text-14px font-500 text-[var(--el-text-color-primary)]">触发器配置</span>
           <el-tag size="small" type="primary">{{ formData.triggers.length }}</el-tag>
         </div>
-        <div class="group-content">
+        <div class="p-12px bg-[var(--el-fill-color-light)] rounded-6px">
           <TriggerPreview :triggers="formData.triggers" />
         </div>
       </div>
 
       <!-- 执行器预览 -->
-      <div class="preview-group">
-        <div class="group-header">
-          <Icon icon="ep:setting" class="group-icon" />
-          <span class="group-title">执行器配置</span>
+      <div class="mb-20px">
+        <div class="flex items-center gap-8px mb-12px">
+          <Icon icon="ep:setting" class="text-[var(--el-color-success)] text-16px" />
+          <span class="text-14px font-500 text-[var(--el-text-color-primary)]">执行器配置</span>
           <el-tag size="small" type="success">{{ formData.actions.length }}</el-tag>
         </div>
-        <div class="group-content">
+        <div class="p-12px bg-[var(--el-fill-color-light)] rounded-6px">
           <ActionPreview :actions="formData.actions" />
         </div>
       </div>
 
       <!-- 验证结果 -->
-      <div class="preview-group">
-        <div class="group-header">
-          <Icon icon="ep:circle-check" class="group-icon" />
-          <span class="group-title">验证结果</span>
+      <div class="mb-20px">
+        <div class="flex items-center gap-8px mb-12px">
+          <Icon icon="ep:circle-check" class="text-[var(--el-color-primary)] text-16px" />
+          <span class="text-14px font-500 text-[var(--el-text-color-primary)]">验证结果</span>
         </div>
-        <div class="group-content">
+        <div class="p-12px bg-[var(--el-fill-color-light)] rounded-6px">
           <ValidationResult :validation-result="validationResult" />
         </div>
       </div>
@@ -105,75 +105,4 @@ const handleValidate = async () => {
 }
 </script>
 
-<style scoped>
-.preview-section {
-  border: 1px solid var(--el-border-color-light);
-  border-radius: 8px;
-}
-
-.section-header {
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-}
-
-.header-left {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-}
-
-.section-icon {
-  color: var(--el-color-primary);
-  font-size: 18px;
-}
-
-.section-title {
-  font-size: 16px;
-  font-weight: 600;
-  color: var(--el-text-color-primary);
-}
-
-.header-right {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-}
 
-.section-content {
-  padding: 0;
-  display: flex;
-  flex-direction: column;
-  gap: 16px;
-}
-
-.preview-group {
-  border: 1px solid var(--el-border-color-lighter);
-  border-radius: 6px;
-  background: var(--el-fill-color-blank);
-}
-
-.group-header {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-  padding: 12px 16px;
-  background: var(--el-fill-color-light);
-  border-bottom: 1px solid var(--el-border-color-lighter);
-}
-
-.group-icon {
-  color: var(--el-color-primary);
-  font-size: 16px;
-}
-
-.group-title {
-  font-size: 14px;
-  font-weight: 500;
-  color: var(--el-text-color-primary);
-}
-
-.group-content {
-  padding: 16px;
-}
-</style>