Răsfoiți Sursa

✨ refactor(item): restructure reactive data and add onActivated hook

Shinohara Haruna 6 luni în urmă
părinte
comite
ac6c3bd91d

+ 55 - 48
smsb-plus-ui/src/views/smsb/item/index.vue

@@ -140,29 +140,35 @@
         <div class="selected-container">
           <!-- 自定义表头 -->
           <div class="draggable-header"
-            style="display: flex; align-items: center; background: #fafafa; border-bottom: 1px solid #eee; min-height: 48px; font-weight: bold;">
-            <span style="width:80px; text-align:center;">排序</span>
-            <span style="flex:1;">文件名</span>
-            <span style="width:120px; margin-left:8px;">播放时长</span>
+            style="display: flex; align-items: center; background: #fafafa; border-bottom: 1px solid #eee; min-height: 48px; font-weight: bold">
+            <span style="width: 80px; text-align: center">排序</span>
+            <span style="flex: 1">文件名</span>
+            <span style="width: 120px; margin-left: 8px">播放时长</span>
           </div>
           <!-- 拖拽列表体 -->
           <draggable v-model="selectedFiles" item-key="id" @end="onSelectedFilesDragEnd" :animation="200" tag="div">
             <template #item="{ element, index }">
               <div class="draggable-row" :draggable="true"
-                style="display: flex; align-items: center; border-bottom: 1px solid #eee; min-height: 48px; cursor: move;">
-                <span class="order-number" style="width:80px; text-align:center;">{{ element.order }}</span>
+                style="display: flex; align-items: center; border-bottom: 1px solid #eee; min-height: 48px; cursor: move">
+                <span class="order-number" style="width: 80px; text-align: center">{{ element.order }}</span>
                 <el-tooltip effect="dark" :content="element.name" placement="top">
-                  <span
-                    style="flex:1; max-width:240px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; display:inline-block; vertical-align:middle;">{{
-                    element.name }}</span>
+                  <span style="
+                      flex: 1;
+                      max-width: 240px;
+                      overflow: hidden;
+                      text-overflow: ellipsis;
+                      white-space: nowrap;
+                      display: inline-block;
+                      vertical-align: middle;
+                    ">{{ element.name }}</span>
                 </el-tooltip>
                 <el-input-number :disabled="element.type !== 1" v-model="element.duration" :min="1" :max="300"
-                  style="width:120px; margin-left:8px;" />
+                  style="width: 120px; margin-left: 8px" />
               </div>
             </template>
           </draggable>
           <!-- 空数据提示 -->
-          <div v-if="selectedFiles.length === 0" style="text-align:center; color:#999; padding: 16px 0;">暂无数据</div>
+          <div v-if="selectedFiles.length === 0" style="text-align: center; color: #999; padding: 16px 0">暂无数据</div>
         </div>
       </div>
       <template #footer>
@@ -235,7 +241,7 @@
                 <el-form-item label="跑马灯" prop="hasPmd">
                   <el-radio-group v-model="form.hasPmd">
                     <el-radio v-for="dict in smsb_yes_no" :key="dict.value" :value="parseInt(dict.value)">{{ dict.label
-                    }}
+                      }}
                     </el-radio>
                   </el-radio-group>
                 </el-form-item>
@@ -257,7 +263,7 @@
                 <el-form-item label="天气" prop="hasWeather">
                   <el-radio-group v-model="form.hasWeather">
                     <el-radio v-for="dict in smsb_yes_no" :key="dict.value" :value="parseInt(dict.value)">{{ dict.label
-                    }}
+                      }}
                     </el-radio>
                   </el-radio-group>
                 </el-form-item>
@@ -266,7 +272,7 @@
                 <el-form-item label="时间" prop="hasTime">
                   <el-radio-group v-model="form.hasTime">
                     <el-radio v-for="dict in smsb_yes_no" :key="dict.value" :value="parseInt(dict.value)">{{ dict.label
-                    }}
+                      }}
                     </el-radio>
                   </el-radio-group>
                 </el-form-item>
@@ -287,6 +293,7 @@
 
 <script setup name="Item" lang="ts">
 import draggable from 'vuedraggable';
+import { onActivated } from 'vue';
 import { listItem, getItem, delItem, addItem, updateItem, itemStatistics } from '@/api/smsb/source/item';
 import { ItemVO, ItemQuery, ItemForm } from '@/api/smsb/source/item_type';
 import { MinioDataQuery, MinioDataVO } from '@/api/smsb/source/minioData_type';
@@ -349,40 +356,35 @@ const initFormData: ItemForm = {
   hasWeather: 0,
   hasTime: 0
 };
-const data = reactive<PageData<ItemForm, ItemQuery>>({
-  form: { ...initFormData },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    itemName: undefined,
-    itemType: undefined,
-    splitScreen: undefined,
-    createUser: undefined,
-    params: {}
-  },
-  rules: {
-    itemName: [{ required: true, message: '请输入名称', trigger: 'blur' }],
-    itemType: [{ required: true, message: '请选择类型', trigger: 'change' }]
-    // 可按需补充其它字段校验
-  }
+const queryParams = ref({
+  pageNum: 1,
+  pageSize: 10,
+  itemName: undefined,
+  itemType: undefined,
+  splitScreen: undefined,
+  createUser: undefined,
+  params: {}
 });
 
-const dialogData = reactive<DialogPageData<MinioDataQuery>>({
-  dialogQueryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    params: {}
-  }
-});
+const form = ref({ ...initFormData });
+const rules = {
+  itemName: [{ required: true, message: '请输入名称', trigger: 'blur' }],
+  itemType: [{ required: true, message: '请选择类型', trigger: 'change' }]
+  // 可按需补充其它字段校验
+};
 
-const { queryParams, form, rules } = toRefs(data);
-const { dialogQueryParams } = toRefs(dialogData);
+const dialogQueryParams = ref({
+  pageNum: 1,
+  pageSize: 10,
+  params: {}
+});
 
 /** 查询节目管理列表 */
 const getList = async () => {
   loading.value = true;
   try {
     const res = await listItem(proxy?.addDateRange(queryParams.value, dateRangeCreateTime.value, 'CreateTime'));
+    console.log('getList result:', res);
     itemList.value = res.rows;
     total.value = res.total;
   } catch (e: any) {
@@ -404,8 +406,8 @@ const getFileList = async () => {
     // After data loads, restore selections
     nextTick(() => {
       if (selectedFiles.value?.length) {
-        const selectedIds = new Set(selectedFiles.value.map(f => f.id));
-        minioDataList.value.forEach(row => {
+        const selectedIds = new Set(selectedFiles.value.map((f) => f.id));
+        minioDataList.value.forEach((row) => {
           if (selectedIds.has(row.id)) {
             fileTable.value?.toggleRowSelection(row, true);
           }
@@ -420,8 +422,8 @@ const getFileList = async () => {
 /** 多选框选中文件数据 */
 // selection-change 只做新增
 const handleSelectionFile = (selection: MinioDataVO[]) => {
-  selection.forEach(item => {
-    if (!selectedFiles.value.some(f => String(f.id) === String(item.id))) {
+  selection.forEach((item) => {
+    if (!selectedFiles.value.some((f) => String(f.id) === String(item.id))) {
       selectedFiles.value.push({
         id: item.id,
         name: item.originalName,
@@ -437,17 +439,17 @@ const handleSelectionFile = (selection: MinioDataVO[]) => {
 
 // 取消单个选中
 const handleSelect = (selection: MinioDataVO[], row: MinioDataVO) => {
-  if (!selection.some(item => String(item.id) === String(row.id))) {
-    selectedFiles.value = selectedFiles.value.filter(f => String(f.id) !== String(row.id));
+  if (!selection.some((item) => String(item.id) === String(row.id))) {
+    selectedFiles.value = selectedFiles.value.filter((f) => String(f.id) !== String(row.id));
     selectedFiles.value = selectedFiles.value.map((f, idx) => ({ ...f, order: idx + 1 }));
   }
 };
 
 // 取消全选
 const handleSelectAll = (selection: MinioDataVO[]) => {
-  const currentPageIds = new Set(minioDataList.value.map(item => String(item.id)));
-  const selectedIds = new Set(selection.map(item => String(item.id)));
-  selectedFiles.value = selectedFiles.value.filter(f => !currentPageIds.has(String(f.id)) || selectedIds.has(String(f.id)));
+  const currentPageIds = new Set(minioDataList.value.map((item) => String(item.id)));
+  const selectedIds = new Set(selection.map((item) => String(item.id)));
+  selectedFiles.value = selectedFiles.value.filter((f) => !currentPageIds.has(String(f.id)) || selectedIds.has(String(f.id)));
   selectedFiles.value = selectedFiles.value.map((f, idx) => ({ ...f, order: idx + 1 }));
 };
 
@@ -640,6 +642,11 @@ onMounted(() => {
   getList();
   getItemStatistics();
 });
+
+onActivated(() => {
+  getList();
+  getItemStatistics();
+});
 </script>
 <style scoped>
 .dialog-container {

+ 118 - 111
smsb-plus-ui/src/views/smsb/item/split.vue

@@ -1,123 +1,130 @@
 <template>
-  <div class="p-2 flex">
-    <!--    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">-->
-    <!--      <div v-show="showSearch" class="mb-[10px]"></div>-->
-    <!-- 左侧示意图 -->
-    <div class="w-1/3 p-2 border-r">示意图</div>
-    <!-- 中间 Table -->
-    <div class="w-1/3 p-2 border-r table-container">
-      <el-radio-group v-model="screenNum" @change="screenChange">
-        <el-radio-button label="第一屏" value="1" v-if="splitScreen !== 4" />
-        <el-radio-button label="第二屏" value="2" v-if="splitScreen !== 4" />
-        <el-radio-button label="第三屏" value="3" v-if="splitScreen === 3" />
-        <el-radio-button label="播放框" value="4" v-if="splitScreen === 4" />
-      </el-radio-group>
-      <el-table :data="minioDataList" ref="minioTable" @selection-change="handleSelectionFile" style="margin-top: 20px">
-        <el-table-column type="selection" width="55" align="center" />
-        <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="duration" />
-        <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>
-      <pagination v-show="fileTotal > 0" :total="fileTotal" v-model:page="dialogQueryParams.pageNum"
-        v-model:limit="dialogQueryParams.pageSize" @pagination="getFileList" />
-    </div>
-    <!-- 右侧内容 -->
-    <div class="w-1/3 p-2">
-      <div v-if="screenNum === '1'" class="table-container">
-        <el-table ref="selectedTable" :data="selectedFiles1" border>
-          <!-- 显示排序数字 -->
-          <el-table-column label="排序" width="80">
-            <template #default="{ row }">
-              <span class="order-number">{{ row.order }}</span>
-            </template>
-          </el-table-column>
-          <el-table-column label="文件名">
-            <template #default="{ row }">
-              <span>{{ row.name }}</span>
+  <div class="split-root">
+    <div class="p-2 flex">
+      <!--    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">-->
+      <!--      <div v-show="showSearch" class="mb-[10px]"></div>-->
+      <!-- 左侧示意图 -->
+      <div class="w-1/3 p-2 border-r">示意图</div>
+      <!-- 中间 Table -->
+      <div class="w-1/3 p-2 border-r table-container">
+        <el-radio-group v-model="screenNum" @change="screenChange">
+          <el-radio-button label="第一屏" value="1" v-if="splitScreen !== 4" />
+          <el-radio-button label="第二屏" value="2" v-if="splitScreen !== 4" />
+          <el-radio-button label="第三屏" value="3" v-if="splitScreen === 3" />
+          <el-radio-button label="播放框" value="4" v-if="splitScreen === 4" />
+        </el-radio-group>
+        <el-table :data="minioDataList" ref="minioTable" @selection-change="handleSelectionFile"
+          style="margin-top: 20px">
+          <el-table-column type="selection" width="55" align="center" />
+          <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="播放时长">
-            <template #default="{ row }">
-              <el-input-number v-model="row.duration" :min="1" :max="300"></el-input-number>
+          <el-table-column label="大小" align="center" prop="size" />
+          <el-table-column label="时长" align="center" prop="duration" />
+          <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>
+        <pagination v-show="fileTotal > 0" :total="fileTotal" v-model:page="dialogQueryParams.pageNum"
+          v-model:limit="dialogQueryParams.pageSize" @pagination="getFileList" />
       </div>
-      <div v-if="screenNum === '2'" class="table-container">
-        <el-table ref="selectedTable" :data="selectedFiles2" border>
-          <!-- 显示排序数字 -->
-          <el-table-column label="排序" width="80">
-            <template #default="{ row }">
-              <span class="order-number">{{ row.order }}</span>
-            </template>
-          </el-table-column>
-          <el-table-column label="文件名">
-            <template #default="{ row }">
-              <span>{{ row.name }}</span>
-            </template>
-          </el-table-column>
-          <el-table-column label="播放时长">
-            <template #default="{ row }">
-              <el-input-number v-model="row.duration" :min="1" :max="300"></el-input-number>
-            </template>
-          </el-table-column>
-        </el-table>
-      </div>
-      <div v-if="screenNum === '3'" class="table-container">
-        <el-table ref="selectedTable" :data="selectedFiles3" border>
-          <!-- 显示排序数字 -->
-          <el-table-column label="排序" width="80">
-            <template #default="{ row }">
-              <span class="order-number">{{ row.order }}</span>
-            </template>
-          </el-table-column>
-          <el-table-column label="文件名">
-            <template #default="{ row }">
-              <span>{{ row.name }}</span>
-            </template>
-          </el-table-column>
-          <el-table-column label="播放时长">
-            <template #default="{ row }">
-              <el-input-number v-model="row.duration" :min="1" :max="300"></el-input-number>
-            </template>
-          </el-table-column>
-        </el-table>
-      </div>
-      <div v-if="screenNum === '4'" class="table-container">
-        <el-table ref="selectedTable" :data="selectedFiles4" border>
-          <!-- 显示排序数字 -->
-          <el-table-column label="排序" width="80">
-            <template #default="{ row }">
-              <span class="order-number">{{ row.order }}</span>
-            </template>
-          </el-table-column>
-          <el-table-column label="文件名">
-            <template #default="{ row }">
-              <span>{{ row.name }}</span>
-            </template>
-          </el-table-column>
-          <el-table-column label="播放时长">
-            <template #default="{ row }">
-              <el-input-number v-model="row.duration" :min="1" :max="300"></el-input-number>
-            </template>
-          </el-table-column>
-        </el-table>
+      <!-- 右侧内容 -->
+      <div class="w-1/3 p-2">
+        <div v-if="screenNum === '1'" class="table-container">
+          <el-table ref="selectedTable" :data="selectedFiles1" border>
+            <!-- 显示排序数字 -->
+            <el-table-column label="排序" width="80">
+              <template #default="{ row }">
+                <span class="order-number">{{ row.order }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="文件名">
+              <template #default="{ row }">
+                <span>{{ row.name }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="播放时长">
+              <template #default="{ row }">
+                <el-input-number v-model="row.duration" :min="1" :max="300"></el-input-number>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+        <div v-if="screenNum === '2'" class="table-container">
+          <el-table ref="selectedTable" :data="selectedFiles2" border>
+            <!-- 显示排序数字 -->
+            <el-table-column label="排序" width="80">
+              <template #default="{ row }">
+                <span class="order-number">{{ row.order }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="文件名">
+              <template #default="{ row }">
+                <span>{{ row.name }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="播放时长">
+              <template #default="{ row }">
+                <el-input-number v-model="row.duration" :min="1" :max="300"></el-input-number>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+        <div v-if="screenNum === '3'" class="table-container">
+          <el-table ref="selectedTable" :data="selectedFiles3" border>
+            <!-- 显示排序数字 -->
+            <el-table-column label="排序" width="80">
+              <template #default="{ row }">
+                <span class="order-number">{{ row.order }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="文件名">
+              <template #default="{ row }">
+                <span>{{ row.name }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="播放时长">
+              <template #default="{ row }">
+                <el-input-number v-model="row.duration" :min="1" :max="300"></el-input-number>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+        <div v-if="screenNum === '4'" class="table-container">
+          <el-table ref="selectedTable" :data="selectedFiles4" border>
+            <!-- 显示排序数字 -->
+            <el-table-column label="排序" width="80">
+              <template #default="{ row }">
+                <span class="order-number">{{ row.order }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="文件名">
+              <template #default="{ row }">
+                <span>{{ row.name }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column label="播放时长">
+              <template #default="{ row }">
+                <el-input-number v-model="row.duration" :min="1" :max="300"></el-input-number>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
       </div>
     </div>
-  </div>
-  <div class="button-container">
-    <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
-    <el-button @click="cancel">关 闭</el-button>
+    <div class="button-container">
+      <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
+      <el-button @click="cancel">关 闭</el-button>
+    </div>
+    <div class="button-container">
+      <el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
+      <el-button @click="cancel">关 闭</el-button>
+    </div>
   </div>
 </template>