Browse Source

优化属性面板展示

Shinohara Haruna 5 months ago
parent
commit
2fed2e772d
1 changed files with 109 additions and 47 deletions
  1. 109 47
      smsb-plus-ui/src/views/smsb/itemProgram/EditProgram.vue

+ 109 - 47
smsb-plus-ui/src/views/smsb/itemProgram/EditProgram.vue

@@ -106,51 +106,56 @@
     <div class="property-panel">
     <div class="property-panel">
       <div class="property-title">属性</div>
       <div class="property-title">属性</div>
       <div class="property-form-area">
       <div class="property-form-area">
-        <el-form label-width="80px">
-          <el-form-item label="节目ID">
-            <el-input v-model="id" disabled />
-          </el-form-item>
-          <!-- 动态显示选中组件的可编辑属性 -->
-          <template v-if="selectedComponent">
-            <div style="margin-bottom: 8px; font-weight: bold">组件属性</div>
-            <template v-for="[key, value] in Object.entries(selectedComponent || {})" :key="key">
-              <el-form-item v-if="showEditableProp(key)" :label="getPropLabel(key)">
-                <template v-if="selectedComponent.type === 'live' && key === 'playAudio'">
-                  <el-switch v-model="selectedComponent[key]" active-text="开" inactive-text="关" />
-                </template>
-                <template v-else>
-                  <el-input v-model="selectedComponent[key]" />
-                </template>
-              </el-form-item>
-            </template>
+        <div class="property-info">
+          <div class="property-info-row">
+            <span class="property-info-label">节目名称:</span>
+            <span>{{ programName }}</span>
+          </div>
+          <div class="property-info-row">
+            <span class="property-info-label">分辨率:</span>
+            <span>{{ programResolution }}</span>
+          </div>
+        </div>
+        <!-- 动态显示选中组件的可编辑属性 -->
+        <template v-if="selectedComponent">
+          <div style="margin-bottom: 8px; font-weight: bold">组件属性</div>
+          <template v-for="[key, value] in Object.entries(selectedComponent || {})" :key="key">
+            <el-form-item v-if="showEditableProp(key)" :label="getPropLabel(key)">
+              <template v-if="selectedComponent.type === 'live' && key === 'playAudio'">
+                <el-switch v-model="selectedComponent[key]" active-text="开" inactive-text="关" />
+              </template>
+              <template v-else>
+                <el-input v-model="selectedComponent[key]" />
+              </template>
+            </el-form-item>
+          </template>
 
 
-            <!-- 对齐尺寸操作区 -->
-            <div style="margin: 12px 0">
-              <div style="font-weight: bold; margin-bottom: 4px">对齐尺寸</div>
-              <div style="display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px">
-                <el-button size="small" @click="alignComponent('left')">水平靠左</el-button>
-                <el-button size="small" @click="alignComponent('right')">水平靠右</el-button>
-                <el-button size="small" @click="alignComponent('top')">垂直靠上</el-button>
-                <el-button size="small" @click="alignComponent('bottom')">垂直靠下</el-button>
-              </div>
-              <div style="display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px">
-                <el-button size="small" @click="alignComponent('width-full')">宽铺满</el-button>
-                <el-button size="small" @click="alignComponent('width-half')">宽半屏</el-button>
-                <el-button size="small" @click="alignComponent('width-third')">宽1/3屏</el-button>
-                <el-button size="small" @click="alignComponent('width-quarter')">宽1/4屏</el-button>
-              </div>
-              <div style="display: flex; flex-wrap: wrap; gap: 4px">
-                <el-button size="small" @click="alignComponent('height-full')">高铺满</el-button>
-                <el-button size="small" @click="alignComponent('height-half')">高半屏</el-button>
-                <el-button size="small" @click="alignComponent('height-third')">高1/3屏</el-button>
-                <el-button size="small" @click="alignComponent('height-quarter')">高1/4屏</el-button>
-              </div>
+          <!-- 对齐尺寸操作区 -->
+          <div style="margin: 12px 0">
+            <div style="font-weight: bold; margin-bottom: 4px">对齐尺寸</div>
+            <div style="display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px">
+              <el-button size="small" @click="alignComponent('left')">水平靠左</el-button>
+              <el-button size="small" @click="alignComponent('right')">水平靠右</el-button>
+              <el-button size="small" @click="alignComponent('top')">垂直靠上</el-button>
+              <el-button size="small" @click="alignComponent('bottom')">垂直靠下</el-button>
             </div>
             </div>
-          </template>
-          <template v-else>
-            <div style="color: #bbb">请点击编辑区中的组件以编辑属性</div>
-          </template>
-        </el-form>
+            <div style="display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px">
+              <el-button size="small" @click="alignComponent('width-full')">宽铺满</el-button>
+              <el-button size="small" @click="alignComponent('width-half')">宽半屏</el-button>
+              <el-button size="small" @click="alignComponent('width-third')">宽1/3屏</el-button>
+              <el-button size="small" @click="alignComponent('width-quarter')">宽1/4屏</el-button>
+            </div>
+            <div style="display: flex; flex-wrap: wrap; gap: 4px">
+              <el-button size="small" @click="alignComponent('height-full')">高铺满</el-button>
+              <el-button size="small" @click="alignComponent('height-half')">高半屏</el-button>
+              <el-button size="small" @click="alignComponent('height-third')">高1/3屏</el-button>
+              <el-button size="small" @click="alignComponent('height-quarter')">高1/4屏</el-button>
+            </div>
+          </div>
+        </template>
+        <template v-else>
+          <div style="color: #bbb">请点击编辑区中的组件以编辑属性</div>
+        </template>
       </div>
       </div>
       <hr class="property-divider" />
       <hr class="property-divider" />
       <div class="json-debug-title">当前JSON</div>
       <div class="json-debug-title">当前JSON</div>
@@ -322,7 +327,9 @@ function getPropLabel(key: string) {
 }
 }
 
 
 const router = useRouter();
 const router = useRouter();
-const id = ref(route.params.id);
+// 自动修正 id 类型,确保为 string 或 number
+const rawId = route.params.id;
+const id = ref<string | number>(Array.isArray(rawId) ? rawId[0] : rawId);
 
 
 // 自动填充画布分辨率
 // 自动填充画布分辨率
 onMounted(async () => {
 onMounted(async () => {
@@ -403,12 +410,17 @@ function ensureCanvasAndDepth(elements, resolutionRatio?: string) {
   return elements;
   return elements;
 }
 }
 
 
-const editorContent = ref({ elements: [] });
+interface EditorContent {
+  name?: string;
+  resolutionRatio?: string;
+  elements: any[];
+  [key: string]: any;
+}
+const editorContent = ref<EditorContent>({ elements: [] });
 
 
 // editor-canvas 缩放逻辑
 // editor-canvas 缩放逻辑
 const editorCanvasRef = ref<HTMLElement | null>(null);
 const editorCanvasRef = ref<HTMLElement | null>(null);
 const containerSize = ref({ width: 0, height: 0 });
 const containerSize = ref({ width: 0, height: 0 });
-const dragComponentType = ref<string | null>(null);
 
 
 const draggingId = ref<number | null>(null);
 const draggingId = ref<number | null>(null);
 let dragStart = { x: 0, y: 0, offsetX: 0, offsetY: 0 };
 let dragStart = { x: 0, y: 0, offsetX: 0, offsetY: 0 };
@@ -531,9 +543,32 @@ function updateContainerSize() {
   }
   }
 }
 }
 
 
-onMounted(() => {
+onMounted(async () => {
   nextTick(updateContainerSize);
   nextTick(updateContainerSize);
   window.addEventListener('resize', updateContainerSize);
   window.addEventListener('resize', updateContainerSize);
+  // 获取节目详细信息并补充到 editorContent
+  try {
+    const res = await getItemProgram(id.value);
+    if (res.data) {
+      // itemJsonStr 是画布内容
+      let content = {};
+      try {
+        content = res.data.itemJsonStr ? JSON.parse(res.data.itemJsonStr) : {};
+      } catch (e) {
+        content = {};
+      }
+      // 合并 name、resolutionRatio 等基础字段
+      editorContent.value = {
+        ...content,
+        name: res.data.name,
+        resolutionRatio: res.data.resolutionRatio,
+        elements: content.elements || []
+      };
+    }
+  } catch (e) {
+    // 错误处理
+    editorContent.value = { elements: [] };
+  }
 });
 });
 
 
 const canvas = computed(() => editorContent.value.elements.find((el: any) => el.type === 'canvas'));
 const canvas = computed(() => editorContent.value.elements.find((el: any) => el.type === 'canvas'));
@@ -551,6 +586,17 @@ const canvasScale = computed(() => {
 // 修复:为模板提供 canvasItem 变量
 // 修复:为模板提供 canvasItem 变量
 const canvasItem = computed(() => editorContent.value.elements.find((el: any) => el.type === 'canvas'));
 const canvasItem = computed(() => editorContent.value.elements.find((el: any) => el.type === 'canvas'));
 
 
+// 右侧属性栏:节目名称和分辨率
+console.log(editorContent.value);
+const programName = computed(() => editorContent.value.name || '-');
+const programResolution = computed(() => {
+  // 优先取 editorContent.value.resolutionRatio,其次 canvas 宽高
+  if (editorContent.value.resolutionRatio) return editorContent.value.resolutionRatio;
+  const canvas = editorContent.value.elements?.find((el: any) => el.type === 'canvas');
+  if (canvas && canvas.width && canvas.height) return `${canvas.width}x${canvas.height}`;
+  return '-';
+});
+
 const saveLoading = ref(false);
 const saveLoading = ref(false);
 const handleSave = async () => {
 const handleSave = async () => {
   saveLoading.value = true;
   saveLoading.value = true;
@@ -733,6 +779,22 @@ const goBack = () => {
   margin-right: auto;
   margin-right: auto;
 }
 }
 
 
+.property-info {
+  margin-bottom: 18px;
+}
+
+.property-info-row {
+  display: flex;
+  align-items: center;
+  margin-bottom: 6px;
+}
+
+.property-info-label {
+  color: #888;
+  min-width: 72px;
+  font-weight: 500;
+}
+
 .property-panel {
 .property-panel {
   width: 260px;
   width: 260px;
   background: #fff;
   background: #fff;