فهرست منبع

Merge branch 'master' of 121.36.198.49:zy_duanju/zhiyu_duanju_distribution_manage_front into js

zqwang 1 سال پیش
والد
کامیت
7d19959d9f

+ 22 - 13
src/api/pageLayout/channelPage/index.ts

@@ -1,26 +1,35 @@
 import http from '@/api/http';
 /**
- * 首页列表-列表
+ * 频道管理-列表
  */
-export function operationManageFirstPageList(params?: object) {
-  return http.get('/operationManage/firstPage/list', params);
+export function operationChannelList(params?: object) {
+  return http.get('/operation/channel/list', params);
 }
 
 /**
- * 首页列表-开启状态
+ * 频道管理-开启状态
  */
-export function operationManageFirstPageEnableStatus(params: object) {
-  return http.post('/operationManage/firstPage/enableStatus', params);
+export function operationChannelEnableStatus(
+  id: number | string,
+  params?: object
+) {
+  return http.post(`/operation/channel/enableStatus/${id}`, params);
 }
 /**
- * 首页列表-添加
+ * 频道管理-添加
  */
-export function operationManageFirstPageAdd(params: object) {
-  return http.post(`/operationManage/firstPage/add`, params);
+export function operationChannelAdd(params: object) {
+  return http.post(`/operation/channel/add`, params);
 }
 /**
- * 首页列表-配置
+ * 频道管理-配置
  */
-export function operationManageFirstPageSetConfig(params: object) {
-  return http.post(`/operationManage/firstPage/setConfig`, params);
-}
+export function operationChannelSetConfig(id: number | string, params: object) {
+  return http.post(`/operation/channel/setting/${id}`, params);
+}
+/**
+ * 频道管理-删除
+ */
+export function operationChannelDel(id: number | string, params?: object) {
+  return http.post(`/operation/channel/del/${id}`, params);
+}

+ 6 - 0
src/api/pageLayout/homePage/index.ts

@@ -23,4 +23,10 @@ export function operationManageFirstPageAdd(params: object) {
  */
 export function operationManageFirstPageSetConfig(params: object) {
   return http.post(`/operationManage/firstPage/setConfig`, params);
+}
+/**
+ * 首页列表-删除
+ */
+export function operationManageFirstPageDelete(params: object) {
+  return http.post(`/operationManage/firstPage/delete`, params);
 }

+ 4 - 4
src/views/appletManage/miniProgramList/index.vue

@@ -36,7 +36,7 @@
                     <span class="text-base">app id:</span>
                     <span class="text-base font-bold">{{ scope.row.appid }}</span>
                   </div>
-                  <div>
+                  <div v-if="isShowSecret">
                     <span class="text-base">app 密匙:</span>
                     <span class="text-base font-bold">{{ scope.row.appsecret }}</span>
                   </div>
@@ -48,7 +48,7 @@
                   <span class="text-base">app id:</span>
                   <span class="text-base font-bold">{{ scope.row.appid }}</span>
                 </div>
-                <div>
+                <div v-if="isShowSecret">
                   <span class="text-base">app 密匙:</span>
                   <span class="text-base font-bold">{{ scope.row.appsecret }}</span>
                 </div>
@@ -98,9 +98,9 @@ const miniprogramTypelist = ref([])
 
 const { data, query, search, reset, loading } = useGetList(api);
 const { open, close, title, visible, id } = useOpen();
-
+const rolesIdentify = inject('rolesIdentify')
 const tableData = computed(() => data.value?.data);
-
+const isShowSecret = computed(() => !rolesIdentify.value.includes('company') && !rolesIdentify.value.includes('optimizer'))
 
 const opendepots = (data) => {
   depotsVisible.value = true

+ 55 - 12
src/views/pageLayout/channelPageManage/form/config.vue

@@ -1,18 +1,20 @@
 <template>
   <el-form :model="formCallback" label-width="120px" ref="form" v-loading="loading" class="pr-4">
-    <el-form-item label="列表名称" prop="ids" :rules="[{ required: false, message: '巨量账户ID必须填写' }]" label-width="120px">
-      <el-input v-model="props.primary.type_str" disabled size="default" clearable></el-input>
+    <el-form-item label="频道名称" prop="ids" :rules="[{ required: false, message: '频道名称必须填写' }]" label-width="120px">
+      <el-input v-model="props.primary.type_txt" disabled size="default" clearable></el-input>
     </el-form-item>
     <el-form-item label="短剧" prop="duanjus" :rules="[{ required: true, message: '选择短剧' }]">
       <div>
         <div class="flex flex-wrap mb-5" v-if="formCallback.duanjus.length > 0">
-          <div v-for="item in formCallback.duanjus" :key="item.id" class="mt-3 mr-3">
-            <el-input v-model="item.name" disabled placeholder="短剧名称" style="width:300px;" class="input-with-select">
-              <template #prepend>
-                <el-input type="number" min="1" disabled v-model.number="item.sort" placeholder="排序" size="default"
-                  clearable style="width: 115px"></el-input>
-              </template>
+          <div v-for="(item, index) in formCallback.duanjus" :key="item.id" class="mt-3 mr-3">
+            <el-input type="number" :disabled="false" min="1" v-model.number="sortValues[index]" placeholder="排序"
+              size="default" style="width: 115px;"></el-input>
+            <el-input v-model="item.name" :disabled="true" placeholder="短剧名称" style="width:300px;"
+              class="input-with-select">
             </el-input>
+            <el-icon class="ml-3 cursor-pointer" @click="chooseDel(item, index)">
+              <Delete />
+            </el-icon>
           </div>
         </div>
         <div>
@@ -33,13 +35,14 @@
 
 <script lang="ts" setup>
 import videoList from './videoList.vue';
-import { Close } from '@element-plus/icons-vue';
+import { Close, Delete } from '@element-plus/icons-vue';
 import { FormInstance } from 'element-plus';
-import { operationManageFirstPageSetConfig } from '@/api/pageLayout/homePage/index';
+import { operationChannelSetConfig } from '@/api/pageLayout/channelPage/index'
 import { useRouter, useRoute } from 'vue-router'
 const props = defineProps({
   primary: Object,
 });
+const sortValues = ref([])
 const router = useRouter()
 const route = useRoute()
 const emit = defineEmits(['close']);
@@ -55,20 +58,57 @@ const formCallback = ref({
 const chooseShort = () => {
   videoVisible.value = true
 }
+const validateData = () => {
+  const sortSet = new Set();
+  const nameSet = new Set();
 
+  for (const item of formCallback.value.duanjus) {
+    if (item.sort === null || item.sort === undefined) {
+      ElMessage.error(`${item.name}的排序不能为空`)
+      return false;
+    }
+    if (sortSet.has(item.sort)) {
+      ElMessage.error(`${item.name}的排序重复`)
+      return false;
+    }
+    sortSet.add(item.sort);
+    if (nameSet.has(item.name)) {
+      ElMessage.error(`${item.name}的排序重复`)
+      return false;
+    }
+
+    nameSet.add(item.name);
+  }
+
+  return true;
+};
 const confirm = (e) => {
   formCallback.value.duanjus = e
+  if (formCallback.value.duanjus.length > 0) {
+    sortValues.value = formCallback.value.duanjus.map(el => el.sort)
+  }
   videoVisible.value = false
 }
+const chooseDel = (row: object, idx: number) => {
+  formCallback.value.duanjus.splice(idx, 1);
+}
 // 提交回传配置
 const submitForm = (formEl: FormInstance | undefined) => {
+  formCallback.value.duanjus = formCallback.value.duanjus.map((el, index) => {
+    return {
+      id: el.id,
+      sort: sortValues.value[index],
+      name: el.name
+    }
+  })
   console.log(formCallback.value, 'formCallbackformCallback');
   if (!formEl) return;
+  if (!validateData()) return
   loading.value = true;
   formEl
     .validate(valid => {
       if (valid) {
-        operationManageFirstPageSetConfig(formCallback.value).then(res => {
+        operationChannelSetConfig(formCallback.value.id, formCallback.value).then(res => {
           ElMessage.success(res.message)
           emit('close')
         })
@@ -83,7 +123,10 @@ const submitForm = (formEl: FormInstance | undefined) => {
 if (props.primary) {
   console.log(props.primary, 'props.primaryprops.primary');
   formCallback.value.id = props.primary.id
-  formCallback.value.duanjus = props.primary.duanjus
+  formCallback.value.duanjus = JSON.parse(JSON.stringify(props.primary.duanjus))
+  if (formCallback.value.duanjus.length > 0) {
+    sortValues.value = formCallback.value.duanjus.map(el => el.sort)
+  }
 }
 onMounted(() => {
 });

+ 5 - 5
src/views/pageLayout/channelPageManage/form/create.vue

@@ -6,8 +6,8 @@
         <el-option v-for="(item, index) in miniprogramTypelist" :key="index" :label="item.label" :value="item.value" />
       </el-select>
     </el-form-item>
-    <el-form-item label="列表名称" prop="type" :rules="[{ required: true, message: '选择列表名称' }]" label-width="120px">
-      <el-select v-model="formCallback.type" clearable filterable placeholder="请选择支付方式">
+    <el-form-item label="频道名称" prop="type" :rules="[{ required: true, message: '选择频道名称' }]" label-width="120px">
+      <el-select v-model="formCallback.type" clearable filterable placeholder="请选择频道名称">
         <el-option v-for="(item, index) in typeList" :key="index" :label="item.name" :value="item.value" />
       </el-select>
     </el-form-item>
@@ -25,7 +25,7 @@
 <script lang="ts" setup>
 import { Close } from '@element-plus/icons-vue';
 import { FormInstance } from 'element-plus';
-import { operationManageFirstPageAdd } from '@/api/pageLayout/homePage/index'
+import { operationChannelAdd } from '@/api/pageLayout/channelPage/index'
 const emit = defineEmits(['close']);
 const loading = ref(false)
 const form = ref()
@@ -35,7 +35,7 @@ const formCallback = ref({
   status: 0,
 })
 
-const typeList = ref([{ name: '本周精选', value: 1 }, { name: '优选好剧', value: 2 }])
+const typeList = ref([{ name: '排行榜', value: 1 }, { name: '最新', value: 2 }])
 const miniprogramTypelist = ref([])
 const init = () => {
   optionsCommonParams().then(res => {
@@ -51,7 +51,7 @@ const submitForm = (formEl: FormInstance | undefined) => {
   formEl
     .validate(valid => {
       if (valid) {
-        operationManageFirstPageAdd(formCallback.value).then(res => {
+        operationChannelAdd(formCallback.value).then(res => {
           ElMessage.success(res.message)
           emit('close')
         })

+ 28 - 15
src/views/pageLayout/channelPageManage/form/videoList.vue

@@ -10,10 +10,13 @@
         <el-form-item label="" class="font-bold">
           <div v-for="(item, index) in multipleSelection" :key="item.id" class="mb-3 mr-3">
             <el-input type="number" :disabled="false" min="1" v-model.number="sortValues[index]" placeholder="排序"
-              size="default" clearable style="width: 115px;"></el-input>
+              size="default" style="width: 115px;"></el-input>
             <el-input v-model="item.name" :disabled="true" placeholder="短剧名称" style="width:300px;"
               class="input-with-select">
             </el-input>
+            <el-icon class="ml-3 cursor-pointer" @click="chooseDel(item, index)">
+              <Delete />
+            </el-icon>
           </div>
         </el-form-item>
       </div>
@@ -33,7 +36,7 @@
             @change="handleCascaderChange" />
         </el-form-item>
         <el-form-item label="微信审核状态" prop="wechatPass">
-          <el-select v-model="query.wechatPass" disabled filterable clearable placeholder="请选择微信审核状态">
+          <el-select v-model="query.wechatPass" filterable clearable placeholder="请选择微信审核状态">
             <el-option v-for="item in wxstatusOptions" :key="item.value" :label="item.label" :value="item.value" />
           </el-select>
         </el-form-item>
@@ -123,14 +126,14 @@
 
 <script lang="ts" setup>
 import { downloadImage } from '@/utils/index'
-import { InfoFilled } from '@element-plus/icons-vue';
+import { InfoFilled, Delete } from '@element-plus/icons-vue';
 import { provide } from 'vue'
 import { useGetList } from '@/hook/curd/useGetList';
 import { useDestroy } from '@/hook/curd/useDestroy';
 import { useOpen } from '@/hook/curd/useOpen';
 import { videoStockVideoCategoryList, videoStockVideoList } from '@/api/video/index'
 const api = 'videoStock/video/list';
-const multipleTableRef = ref()
+const multipleTableRef = ref(null); // 初始化为 null
 const multipleSelection = ref([]);
 const { data, query, search, reset, loading } = useGetList(api);
 const selectType = ref([])
@@ -156,7 +159,7 @@ const handleCascaderChange = (val: any) => {
 }
 
 const resetQuery = () => {
-  query.value = Object.assign({ page: query.value.page, limit: query.value.limit, shelfType: 2, wechatPass: 1 });
+  query.value = Object.assign({ page: query.value.page, limit: query.value.limit, shelfType: 2 });
   search()
   selectType.value = []
 }
@@ -197,8 +200,16 @@ const validateData = () => {
 };
 
 const tableData = computed(() => data.value?.data);
+const chooseDel = (row: object, idx: number) => {
+  console.log(row, idx, 'row: object, idx: number', multipleSelection.value[idx]);
+  multipleSelection.value.splice(idx, 1);
+  // multipleTableRef.value.toggleRowSelection(row, false);//第一次回显的时候没有效果 改成下面那种方式
+  setRowSelected()
+  search()
+}
 
 const handleSelectionChange = (val: []) => {
+  console.log(val, 'handleSelectionChangehandleSelectionChange');
   if (rowSelectFlag.value) return
   multipleSelection.value = val;
 };
@@ -221,27 +232,30 @@ const confirm = () => {
 
 if (props.primary) {
   // console.log(props.primary, 'props.primaryprops.primary');
-  multipleSelection.value = props.primary || []
+  multipleSelection.value = JSON.parse(JSON.stringify(props.primary)) || []
   if (multipleSelection.value.length > 0) {
+    // 初始化 sortValues 数组长度,保持与 multipleSelection 数组一致
     sortValues.value = multipleSelection.value.map(el => el.sort)
-    console.log(sortValues.value, 'sortValues.valuesortValues.value');
   }
 }
 
-const setRowSelected = () => {
+const setRowSelected = (status: boolean = true) => {
   rowSelectFlag.value = true
-  Object.keys(multipleSelection.value).forEach(key => {
-    multipleSelection.value[key] && multipleTableRef.value.toggleRowSelection(multipleSelection.value[key], true)
-  })
+  if (multipleTableRef.value) { // 确保 multipleTableRef 有有效的值
+    multipleTableRef.value.clearSelection(); // 清除之前的选中状态
+    multipleSelection.value.forEach((item) => {
+      multipleTableRef.value.toggleRowSelection(item, status);
+    });
+  } else {
+    ElMessage.error('表格实例未找到');
+  }
   rowSelectFlag.value = false
 }
 onMounted(() => {
-  // 初始化 sortValues 数组长度,保持与 multipleSelection 数组一致
-  // sortValues.value = new Array(multipleSelection.value.length);
   query.value = Object.assign({ page: query.value.page, limit: query.value.limit, shelfType: 2, wechatPass: 1 });
-  setRowSelected()
   initType()
   search();
+  setRowSelected()
 });
 </script>
 
@@ -252,7 +266,6 @@ onMounted(() => {
   overflow: auto;
 }
 
-
 .table-default {
   .set-warpper {
     height: 60px;

+ 90 - 30
src/views/pageLayout/channelPageManage/index.vue

@@ -1,31 +1,60 @@
 <template>
-  <div class="table-default">
-    <div class="pt-5 pl-2" v-action="'operation.FirstPage.add'">
-      <el-button type="primary" size="default" @click="openForm(null)">新增</el-button>
-    </div>
-    <el-table :data="tableData" class="mt-3" v-loading="loading">
-      <el-table-column label="频道ID" prop="id"></el-table-column>
-      <el-table-column label="频道名称" prop="type_str">
-      </el-table-column>
-      <el-table-column label="添加时间" prop="created_at">
-      </el-table-column>
-      <el-table-column label="状态" v-action="'operation.FirstPage.enableStatus'">
-        <template #default="scope">
-          <div>
-            <el-switch v-model="scope.row.status" :disabled="Boolean(scope.row.status)" @change="switchStatus(scope.row)"
-              :active-value="1" :inactive-value="0">
-            </el-switch>
-          </div>
-        </template>
-      </el-table-column>
-      <el-table-column label="操作">
-        <template #default="scope">
-          <el-button link type="primary" size="small" @click="handleConfigure(scope.row)"
-            v-action="'operation.FirstPage.setConfig'">配置</el-button>
+  <div class="flex flex-col justify-between w-full sm:flex-row">
+    <div class="w-full">
+      <Search :search="search" :reset="reset">
+        <template v-slot:body>
+          <el-form-item label="频道名称">
+            <el-select v-model="query.type" clearable filterable placeholder="请选择频道名称">
+              <el-option v-for="(item, index) in typeList" :key="index" :label="item.name" :value="item.value" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="小程序类型">
+            <el-select v-model="query.miniprogram_type" clearable filterable placeholder="请选择小程序类型">
+              <el-option v-for="(item, index) in miniprogramTypelist" :key="index" :label="item.label"
+                :value="item.value" />
+            </el-select>
+          </el-form-item>
         </template>
-      </el-table-column>
-    </el-table>
-    <Paginate />
+      </Search>
+      <el-card shadow="always" class="mt-3" :body-style="{ padding: '20px' }">
+        <div class="m-3">
+          <el-alert title="启用状态后,最新开启的记录排序在上面" type="warning" :closable="false" />
+        </div>
+        <div class="table-default">
+          <div class="pt-5 pl-2" v-action="'operation.Channel.add'">
+            <el-button type="primary" size="default" @click="openForm(null)">新增</el-button>
+          </div>
+          <el-table :data="tableData" class="mt-3" v-loading="loading">
+            <el-table-column label="频道ID" prop="id"></el-table-column>
+            <el-table-column label="频道名称" prop="type_txt">
+            </el-table-column>
+            <el-table-column label="添加时间" prop="created_at">
+            </el-table-column>
+            <el-table-column label="小程序类型" prop="miniprogram_type_text">
+            </el-table-column>
+            <el-table-column label="状态" v-action="'operation.Channel.enableStatus'">
+              <template #default="scope">
+                <div>
+                  <el-switch v-model="scope.row.status" :disabled="Boolean(scope.row.status)"
+                    @change="switchStatus(scope.row)" :active-value="1" :inactive-value="0">
+                  </el-switch>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="操作">
+              <template #default="scope">
+                <el-button link type="primary" size="small" @click="handleConfigure(scope.row)"
+                  v-action="'operation.Channel.setting'">配置</el-button>
+                <br />
+                <el-button link type="primary" size="small" @click="handleDel(scope.row)" v-if="!scope.row.status"
+                  v-action="'operation.Channel.del'">删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+          <Paginate />
+        </div>
+      </el-card>
+    </div>
   </div>
   <Dialog v-model="configVisible" title="配置" width="50%" destroy-on-close>
     <config @close="closeType('configVisible')" :primary="currentConfig"></config>
@@ -42,16 +71,44 @@ import { computed, onMounted, ref } from 'vue';
 import create from './form/create.vue';
 import config from './form/config.vue';
 import { useGetList } from '@/hook/curd/useGetList';
-import { operationManageFirstPageEnableStatus } from '@/api/pageLayout/homePage/index'
-
-const api = 'operationManage/firstPage/list';
+import { operationChannelEnableStatus, operationChannelDel } from '@/api/pageLayout/channelPage/index'
+import { optionsCommonParams } from '@/api/common/index'
 
+const api = 'operation/channel/list';
+const typeList = ref([{ name: '排行榜', value: 1 }, { name: '最新', value: 2 }])
+const miniprogramTypelist = ref([])
 const { data, query, search, reset, loading } = useGetList(api, true);
 const tableData = computed(() => data.value?.data);
 const addVisible = ref(false)
 const currentConfig = ref({})
 const configVisible = ref(false) //设置回传弹窗
+const init = () => {
+  optionsCommonParams().then(res => {
+    console.log(res, 'optionsCommonParams');
+    miniprogramTypelist.value = res.data.miniprogramType
+  })
+}
 
+const handleDel = (row: object) => {
+  ElMessageBox.confirm(
+    `确认删除此列表吗?`,
+    '提示',
+    {
+      confirmButtonText: '确定',
+      cancelButtonText: '取消',
+      type: 'warning',
+    }
+  )
+    .then(() => {
+      operationChannelDel(row.id).then(res => {
+        ElMessage.success(res.message)
+        search()
+      })
+    })
+    .catch(() => {
+      search()
+    })
+}
 const closeType = (type: string) => {
   switch (type) {
     case 'configVisible':
@@ -65,9 +122,11 @@ const closeType = (type: string) => {
 }
 
 const switchStatus = (data: object) => {
-  operationManageFirstPageEnableStatus({ id: data.id }).then(res => {
+  operationChannelEnableStatus(data.id).then(res => {
     ElMessage.success(res.message)
     search()
+  }).catch(e => {
+    search()
   })
 }
 
@@ -81,6 +140,7 @@ const handleConfigure = (data: object) => {
 };
 onMounted(() => {
   search();
+  init()
 });
 </script>
 <style  lang='scss' scoped></style>

+ 52 - 9
src/views/pageLayout/homePageManage/form/config.vue

@@ -1,18 +1,20 @@
 <template>
   <el-form :model="formCallback" label-width="120px" ref="form" v-loading="loading" class="pr-4">
-    <el-form-item label="列表名称" prop="ids" :rules="[{ required: false, message: '巨量账户ID必须填写' }]" label-width="120px">
+    <el-form-item label="列表名称" prop="ids" :rules="[{ required: false, message: '列表名称必须填写' }]" label-width="120px">
       <el-input v-model="props.primary.type_str" disabled size="default" clearable></el-input>
     </el-form-item>
     <el-form-item label="短剧" prop="duanjus" :rules="[{ required: true, message: '选择短剧' }]">
       <div>
         <div class="flex flex-wrap mb-5" v-if="formCallback.duanjus.length > 0">
-          <div v-for="item in formCallback.duanjus" :key="item.id" class="mt-3 mr-3">
-            <el-input v-model="item.name" disabled placeholder="短剧名称" style="width:300px;" class="input-with-select">
-              <template #prepend>
-                <el-input type="number" min="1" disabled v-model.number="item.sort" placeholder="排序" size="default"
-                  clearable style="width: 115px"></el-input>
-              </template>
+          <div v-for="(item, index) in formCallback.duanjus" :key="item.id" class="mt-3 mr-3">
+            <el-input type="number" :disabled="false" min="1" v-model.number="sortValues[index]" placeholder="排序"
+              size="default" style="width: 115px;"></el-input>
+            <el-input v-model="item.name" :disabled="true" placeholder="短剧名称" style="width:300px;"
+              class="input-with-select">
             </el-input>
+            <el-icon class="ml-3 cursor-pointer" @click="chooseDel(item, index)">
+              <Delete />
+            </el-icon>
           </div>
         </div>
         <div>
@@ -33,13 +35,14 @@
 
 <script lang="ts" setup>
 import videoList from './videoList.vue';
-import { Close } from '@element-plus/icons-vue';
+import { Close, Delete } from '@element-plus/icons-vue';
 import { FormInstance } from 'element-plus';
 import { operationManageFirstPageSetConfig } from '@/api/pageLayout/homePage/index';
 import { useRouter, useRoute } from 'vue-router'
 const props = defineProps({
   primary: Object,
 });
+const sortValues = ref([])
 const router = useRouter()
 const route = useRoute()
 const emit = defineEmits(['close']);
@@ -55,15 +58,52 @@ const formCallback = ref({
 const chooseShort = () => {
   videoVisible.value = true
 }
+const validateData = () => {
+  const sortSet = new Set();
+  const nameSet = new Set();
 
+  for (const item of formCallback.value.duanjus) {
+    if (item.sort === null || item.sort === undefined) {
+      ElMessage.error(`${item.name}的排序不能为空`)
+      return false;
+    }
+    if (sortSet.has(item.sort)) {
+      ElMessage.error(`${item.name}的排序重复`)
+      return false;
+    }
+    sortSet.add(item.sort);
+    if (nameSet.has(item.name)) {
+      ElMessage.error(`${item.name}的排序重复`)
+      return false;
+    }
+
+    nameSet.add(item.name);
+  }
+
+  return true;
+};
 const confirm = (e) => {
   formCallback.value.duanjus = e
+  if (formCallback.value.duanjus.length > 0) {
+    sortValues.value = formCallback.value.duanjus.map(el => el.sort)
+  }
   videoVisible.value = false
 }
+const chooseDel = (row: object, idx: number) => {
+  formCallback.value.duanjus.splice(idx, 1);
+}
 // 提交回传配置
 const submitForm = (formEl: FormInstance | undefined) => {
   console.log(formCallback.value, 'formCallbackformCallback');
+  formCallback.value.duanjus = formCallback.value.duanjus.map((el, index) => {
+    return {
+      id: el.id,
+      sort: sortValues.value[index],
+      name: el.name
+    }
+  })
   if (!formEl) return;
+  if (!validateData()) return
   loading.value = true;
   formEl
     .validate(valid => {
@@ -83,7 +123,10 @@ const submitForm = (formEl: FormInstance | undefined) => {
 if (props.primary) {
   console.log(props.primary, 'props.primaryprops.primary');
   formCallback.value.id = props.primary.id
-  formCallback.value.duanjus = props.primary.duanjus
+  formCallback.value.duanjus = JSON.parse(JSON.stringify(props.primary.duanjus))
+  if (formCallback.value.duanjus.length > 0) {
+    sortValues.value = formCallback.value.duanjus.map(el => el.sort)
+  }
 }
 onMounted(() => {
 });

+ 1 - 1
src/views/pageLayout/homePageManage/form/create.vue

@@ -7,7 +7,7 @@
       </el-select>
     </el-form-item>
     <el-form-item label="列表名称" prop="type" :rules="[{ required: true, message: '选择列表名称' }]" label-width="120px">
-      <el-select v-model="formCallback.type" clearable filterable placeholder="请选择支付方式">
+      <el-select v-model="formCallback.type" clearable filterable placeholder="请选择列表名称">
         <el-option v-for="(item, index) in typeList" :key="index" :label="item.name" :value="item.value" />
       </el-select>
     </el-form-item>

+ 27 - 13
src/views/pageLayout/homePageManage/form/videoList.vue

@@ -10,10 +10,13 @@
         <el-form-item label="" class="font-bold">
           <div v-for="(item, index) in multipleSelection" :key="item.id" class="mb-3 mr-3">
             <el-input type="number" :disabled="false" min="1" v-model.number="sortValues[index]" placeholder="排序"
-              size="default" clearable style="width: 115px;"></el-input>
+              size="default" style="width: 115px;"></el-input>
             <el-input v-model="item.name" :disabled="true" placeholder="短剧名称" style="width:300px;"
               class="input-with-select">
             </el-input>
+            <el-icon class="ml-3 cursor-pointer" @click="chooseDel(item, index)">
+              <Delete />
+            </el-icon>
           </div>
         </el-form-item>
       </div>
@@ -123,14 +126,14 @@
 
 <script lang="ts" setup>
 import { downloadImage } from '@/utils/index'
-import { InfoFilled } from '@element-plus/icons-vue';
+import { InfoFilled, Delete } from '@element-plus/icons-vue';
 import { provide } from 'vue'
 import { useGetList } from '@/hook/curd/useGetList';
 import { useDestroy } from '@/hook/curd/useDestroy';
 import { useOpen } from '@/hook/curd/useOpen';
 import { videoStockVideoCategoryList, videoStockVideoList } from '@/api/video/index'
 const api = 'videoStock/video/list';
-const multipleTableRef = ref()
+const multipleTableRef = ref(null); // 初始化为 null
 const multipleSelection = ref([]);
 const { data, query, search, reset, loading } = useGetList(api);
 const selectType = ref([])
@@ -156,7 +159,7 @@ const handleCascaderChange = (val: any) => {
 }
 
 const resetQuery = () => {
-  query.value = Object.assign({ page: query.value.page, limit: query.value.limit, shelfType: 2, wechatPass: 1 });
+  query.value = Object.assign({ page: query.value.page, limit: query.value.limit, shelfType: 2 });
   search()
   selectType.value = []
 }
@@ -197,8 +200,16 @@ const validateData = () => {
 };
 
 const tableData = computed(() => data.value?.data);
+const chooseDel = (row: object, idx: number) => {
+  console.log(row, idx, 'row: object, idx: number', multipleSelection.value[idx]);
+  multipleSelection.value.splice(idx, 1);
+  // multipleTableRef.value.toggleRowSelection(row, false);//第一次回显的时候没有效果 改成下面那种方式
+  setRowSelected()
+  search()
+}
 
 const handleSelectionChange = (val: []) => {
+  console.log(val, 'handleSelectionChangehandleSelectionChange');
   if (rowSelectFlag.value) return
   multipleSelection.value = val;
 };
@@ -221,27 +232,30 @@ const confirm = () => {
 
 if (props.primary) {
   // console.log(props.primary, 'props.primaryprops.primary');
-  multipleSelection.value = props.primary || []
+  multipleSelection.value = JSON.parse(JSON.stringify(props.primary)) || []
   if (multipleSelection.value.length > 0) {
+    // 初始化 sortValues 数组长度,保持与 multipleSelection 数组一致
     sortValues.value = multipleSelection.value.map(el => el.sort)
-    console.log(sortValues.value, 'sortValues.valuesortValues.value');
   }
 }
 
-const setRowSelected = () => {
+const setRowSelected = (status: boolean = true) => {
   rowSelectFlag.value = true
-  Object.keys(multipleSelection.value).forEach(key => {
-    multipleSelection.value[key] && multipleTableRef.value.toggleRowSelection(multipleSelection.value[key], true)
-  })
+  if (multipleTableRef.value) { // 确保 multipleTableRef 有有效的值
+    multipleTableRef.value.clearSelection(); // 清除之前的选中状态
+    multipleSelection.value.forEach((item) => {
+      multipleTableRef.value.toggleRowSelection(item, status);
+    });
+  } else {
+    ElMessage.error('表格实例未找到');
+  }
   rowSelectFlag.value = false
 }
 onMounted(() => {
-  // 初始化 sortValues 数组长度,保持与 multipleSelection 数组一致
-  // sortValues.value = new Array(multipleSelection.value.length);
   query.value = Object.assign({ page: query.value.page, limit: query.value.limit, shelfType: 2, wechatPass: 1 });
-  setRowSelected()
   initType()
   search();
+  setRowSelected()
 });
 </script>
 

+ 88 - 31
src/views/pageLayout/homePageManage/index.vue

@@ -1,33 +1,60 @@
 <template>
-  <div class="table-default">
-    <div class="pt-5 pl-2" v-action="'operation.FirstPage.add'">
-      <el-button type="primary" size="default" @click="openForm(null)">新增</el-button>
-    </div>
-    <el-table :data="tableData" class="mt-3" v-loading="loading">
-      <el-table-column label="ID" prop="id"></el-table-column>
-      <el-table-column label="列表名称" prop="type_str">
-      </el-table-column>
-      <el-table-column label="添加时间" prop="created_at">
-      </el-table-column>
-      <el-table-column label="小程序类型" prop="miniprogram_type_str">
-      </el-table-column>
-      <el-table-column label="状态" v-action="'operation.FirstPage.enableStatus'">
-        <template #default="scope">
-          <div>
-            <el-switch v-model="scope.row.status" :disabled="Boolean(scope.row.status)" @change="switchStatus(scope.row)"
-              :active-value="1" :inactive-value="0">
-            </el-switch>
-          </div>
-        </template>
-      </el-table-column>
-      <el-table-column label="操作">
-        <template #default="scope">
-          <el-button link type="primary" size="default" @click="handleConfigure(scope.row)"
-            v-action="'operation.FirstPage.setConfig'">配置</el-button>
+  <div class="flex flex-col justify-between w-full sm:flex-row">
+    <div class="w-full">
+      <Search :search="search" :reset="reset">
+        <template v-slot:body>
+          <el-form-item label="列表名称">
+            <el-select v-model="query.type" clearable filterable placeholder="请选择列表名称">
+              <el-option v-for="(item, index) in typeList" :key="index" :label="item.name" :value="item.value" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="小程序类型">
+            <el-select v-model="query.miniprogram_type" clearable filterable placeholder="请选择小程序类型">
+              <el-option v-for="(item, index) in miniprogramTypelist" :key="index" :label="item.label"
+                :value="item.value" />
+            </el-select>
+          </el-form-item>
         </template>
-      </el-table-column>
-    </el-table>
-    <Paginate />
+      </Search>
+      <el-card shadow="always" class="mt-3" :body-style="{ padding: '20px' }">
+        <div class="m-3">
+          <el-alert title="启用状态后,最新开启的记录排序在上面" type="warning" :closable="false" />
+        </div>
+        <div class="table-default">
+          <div class="pt-5 pl-2" v-action="'operation.FirstPage.add'">
+            <el-button type="primary" size="default" @click="openForm(null)">新增</el-button>
+          </div>
+          <el-table :data="tableData" class="mt-3" v-loading="loading">
+            <el-table-column label="ID" prop="id"></el-table-column>
+            <el-table-column label="列表名称" prop="type_str">
+            </el-table-column>
+            <el-table-column label="添加时间" prop="created_at">
+            </el-table-column>
+            <el-table-column label="小程序类型" prop="miniprogram_type_str">
+            </el-table-column>
+            <el-table-column label="状态" v-action="'operation.FirstPage.enableStatus'">
+              <template #default="scope">
+                <div>
+                  <el-switch v-model="scope.row.status" :disabled="Boolean(scope.row.status)"
+                    @change="switchStatus(scope.row)" :active-value="1" :inactive-value="0">
+                  </el-switch>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="操作">
+              <template #default="scope">
+                <el-button link type="primary" size="small" @click="handleConfigure(scope.row)"
+                  v-action="'operation.FirstPage.setConfig'">配置</el-button>
+                <br />
+                <el-button link type="primary" size="small" @click="handleDel(scope.row)" v-if="!scope.row.status"
+                  v-action="'operation.FirstPage.delete'">删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+          <Paginate />
+        </div>
+      </el-card>
+    </div>
   </div>
   <Dialog v-model="configVisible" title="配置" width="50%" destroy-on-close>
     <config @close="closeType('configVisible')" :primary="currentConfig"></config>
@@ -44,16 +71,23 @@ import { computed, onMounted, ref } from 'vue';
 import create from './form/create.vue';
 import config from './form/config.vue';
 import { useGetList } from '@/hook/curd/useGetList';
-import { operationManageFirstPageEnableStatus } from '@/api/pageLayout/homePage/index'
+import { operationManageFirstPageEnableStatus, operationManageFirstPageDelete } from '@/api/pageLayout/homePage/index'
+import { optionsCommonParams } from '@/api/common/index'
 
 const api = 'operationManage/firstPage/list';
-
+const typeList = ref([{ name: '本周精选', value: 1 }, { name: '优选好剧', value: 2 }])
+const miniprogramTypelist = ref([])
 const { data, query, search, reset, loading } = useGetList(api, true);
 const tableData = computed(() => data.value?.data);
 const addVisible = ref(false)
 const currentConfig = ref({})
 const configVisible = ref(false) //设置回传弹窗
-
+const init = () => {
+  optionsCommonParams().then(res => {
+    console.log(res, 'optionsCommonParams');
+    miniprogramTypelist.value = res.data.miniprogramType
+  })
+}
 const closeType = (type: string) => {
   switch (type) {
     case 'configVisible':
@@ -65,11 +99,33 @@ const closeType = (type: string) => {
   }
   search()
 }
+const handleDel = (row: object) => {
+  ElMessageBox.confirm(
+    `确认删除此列表吗?`,
+    '提示',
+    {
+      confirmButtonText: '确定',
+      cancelButtonText: '取消',
+      type: 'warning',
+    }
+  )
+    .then(() => {
+      operationManageFirstPageDelete({ id: row.id }).then(res => {
+        ElMessage.success(res.message)
+        search()
+      })
+    })
+    .catch(() => {
+      search()
+    })
+}
 
 const switchStatus = (data: object) => {
   operationManageFirstPageEnableStatus({ id: data.id }).then(res => {
     ElMessage.success(res.message)
     search()
+  }).catch(e => {
+    search()
   })
 }
 
@@ -83,6 +139,7 @@ const handleConfigure = (data: object) => {
 };
 onMounted(() => {
   search();
+  init()
 });
 </script>
 <style  lang='scss' scoped></style>

+ 15 - 7
src/views/pageLayout/viewpagerPageManage/form/create.vue

@@ -16,12 +16,15 @@
       <my-upload acceptType=".png,.jpg,.jpeg" :isCheckMM="true" :isMultiple="true" @fileRemove="fileRemove"
         @fileSuccess="fileSuccess" :fileList="formCallback.fileList" action="/qiniu/upload/image"></my-upload>
     </el-form-item>
-    <el-form-item label="链接短剧信息" prop="duanjus" :rules="[{ required: true, message: '选择链接短剧信息' }]">
+    <el-form-item label="链接短剧信息" prop="duanjus" :rules="[{ required: false, message: '选择链接短剧信息', trigger: 'change' }]">
       <div>
-        <div class="flex flex-wrap mb-5" v-if="formCallback?.duanjus?.name">
+        <div class="flex flex-wrap items-center mb-5" v-if="formCallback?.duanjus?.name">
           <el-input v-model="formCallback.duanjus.name" disabled placeholder="短剧名称" style="width:200px;"
             class="input-with-select">
           </el-input>
+          <el-icon class="ml-3 cursor-pointer" @click="chooseDel">
+            <Delete />
+          </el-icon>
         </div>
         <div>
           <el-button type="primary" size="default" @click="chooseShort">选择短剧</el-button>
@@ -44,7 +47,7 @@
 
 <script lang="ts" setup>
 import videoList from './videoList.vue';
-import { Close } from '@element-plus/icons-vue';
+import { Close, Delete } from '@element-plus/icons-vue';
 import { FormInstance } from 'element-plus';
 import {
   operationBannerEdit,
@@ -71,6 +74,9 @@ const init = () => {
   })
 }
 
+const chooseDel = () => {
+  formCallback.value.duanjus = ''
+}
 const fileSuccess = (e) => {
   console.log(e);
   formCallback.value.img_url = e;
@@ -97,13 +103,13 @@ const submitForm = (formEl: FormInstance | undefined) => {
       if (valid) {
         const params = {
           title: formCallback.value.title,
-          video_id: formCallback.value.duanjus.id,
+          video_id: formCallback.value.duanjus?.id,
           miniprogram_type: formCallback.value.miniprogram_type,
           sort: formCallback.value.sort,
           img_url: formCallback.value.img_url,
           status: formCallback.value.status,
         }
-        if (props.primary.id) {
+        if (props.primary?.id) {
           operationBannerEdit(formCallback.value.id, params).then(res => {
             ElMessage.success(res.message)
             emit('close')
@@ -113,8 +119,8 @@ const submitForm = (formEl: FormInstance | undefined) => {
             ElMessage.success(res.message)
             emit('close')
           })
-          loading.value = false;
         }
+        loading.value = false;
       } else {
         loading.value = false;
       }
@@ -125,8 +131,10 @@ const submitForm = (formEl: FormInstance | undefined) => {
 if (props.primary.id) {
   console.log(props.primary, 'props.primaryprops.primary');
   formCallback.value = JSON.parse(JSON.stringify(props.primary))
-  formCallback.value.duanjus = props.primary.videoInfo
+  formCallback.value.duanjus = JSON.parse(JSON.stringify(props.primary.videoInfo))
   formCallback.value.fileList = [{ uid: props.primary.id, url: props.primary.img_url }]
+} else {
+  formCallback.value.fileList = []
 }
 onMounted(() => {
   init()

+ 13 - 6
src/views/pageLayout/viewpagerPageManage/form/videoList.vue

@@ -11,6 +11,9 @@
           <el-input v-model="multipleSelection.name" :disabled="true" placeholder="短剧名称" style="width:300px;"
             class="input-with-select">
           </el-input>
+          <el-icon class="ml-3 cursor-pointer" @click="chooseDel">
+            <Delete />
+          </el-icon>
         </el-form-item>
       </div>
     </el-card>
@@ -29,15 +32,15 @@
             @change="handleCascaderChange" />
         </el-form-item>
         <el-form-item label="微信审核状态" prop="wechatPass">
-          <el-select v-model="query.wechatPass" disabled filterable clearable placeholder="请选择微信审核状态">
+          <el-select v-model="query.wechatPass" filterable clearable placeholder="请选择微信审核状态">
             <el-option v-for="item in wxstatusOptions" :key="item.value" :label="item.label" :value="item.value" />
           </el-select>
         </el-form-item>
       </template>
     </Search>
     <div class="table-default">
-      <el-table :data="tableData" ref="multipleTableRef" height="380px" highlight-current-row class="mt-3"
-        v-loading="loading" row-key="id" @current-change="handleCurrentChange">
+      <el-table :data="tableData" ref="multipleTableRef" height="380px" class="mt-3" v-loading="loading" row-key="id"
+        @current-change="handleCurrentChange">
         <el-table-column>
           <template #default="scope">
             <el-radio class="radio" v-model="selVal" :label="scope.row.id"><span></span></el-radio>
@@ -123,7 +126,7 @@
 
 <script lang="ts" setup>
 import { downloadImage } from '@/utils/index'
-import { InfoFilled } from '@element-plus/icons-vue';
+import { InfoFilled, Delete } from '@element-plus/icons-vue';
 import { provide } from 'vue'
 import { useGetList } from '@/hook/curd/useGetList';
 import { useDestroy } from '@/hook/curd/useDestroy';
@@ -173,6 +176,10 @@ const dowload = (e: object) => {
 
 const tableData = computed(() => data.value?.data);
 
+const chooseDel = () => {
+  multipleSelection.value = ''
+  selVal.value = ''
+}
 const handleCurrentChange = (val: any) => {
   if (rowSelectFlag.value) return
   multipleSelection.value = val;
@@ -185,12 +192,12 @@ const confirm = () => {
 
 if (props.primary) {
   // console.log(props.primary, 'props.primaryprops.primary');
-  multipleSelection.value = props.primary || {}
+  multipleSelection.value = JSON.parse(JSON.stringify(props.primary)) || {}
   selVal.value = props.primary.id
 }
 
 onMounted(() => {
-  query.value = Object.assign({ page: query.value.page, limit: query.value.limit, shelfType: 2 });
+  query.value = Object.assign({ page: query.value.page, limit: query.value.limit, shelfType: 2, wechatPass: 1 });
   initType()
   search();
 });

+ 71 - 42
src/views/pageLayout/viewpagerPageManage/index.vue

@@ -1,44 +1,62 @@
 <template>
-  <div class="table-default">
-    <div class="pt-5 pl-2" v-action="'operation.FirstPage.add'">
-      <el-button type="primary" size="default" @click="openForm(null)">新增</el-button>
-    </div>
-    <el-table :data="tableData" class="mt-3" v-loading="loading">
-      <el-table-column label="轮播图ID" prop="id"></el-table-column>
-      <el-table-column label="轮播图名称" prop="title">
-      </el-table-column>
-      <el-table-column label="封面" prop="img_url">
-        <template #default="scope">
-          <el-image :src="scope.row.img_url" fit="fill" :lazy="true"></el-image>
-        </template>
-      </el-table-column>
-      <el-table-column label="排序" prop="sort">
-      </el-table-column>
-      <el-table-column label="添加时间" prop="created_at">
-      </el-table-column>
-      <el-table-column label="小程序类型" prop="miniprogram_type_text">
-      </el-table-column>
-      <el-table-column label="状态" v-action="'operation.FirstPage.enableStatus'">
-        <template #default="scope">
-          <div>
-            <el-switch v-model="scope.row.status" @change="switchStatus(scope.row)" :active-value="1" :inactive-value="0">
-            </el-switch>
-          </div>
-        </template>
-      </el-table-column>
-      <el-table-column label="操作">
-        <template #default="scope">
-          <el-button link type="primary" size="small" @click="handleEdit(scope.row)"
-            v-action="'operation.FirstPage.setConfig'">编辑</el-button>
-          <br />
-          <el-button link type="primary" size="small" @click="handleDel(scope.row)"
-            v-action="'operation.FirstPage.setConfig'">删除</el-button>
+  <div class="flex flex-col justify-between w-full sm:flex-row">
+    <div class="w-full">
+      <Search :search="search" :reset="reset">
+        <template v-slot:body>
+          <el-form-item label="轮播图名称">
+            <el-input v-model="query.title" size="default" placeholder="请输入轮播图名称" clearable></el-input>
+          </el-form-item>
+          <el-form-item label="小程序类型">
+            <el-select v-model="query.miniprogram_type" clearable filterable placeholder="请选择小程序类型">
+              <el-option v-for="(item, index) in miniprogramTypelist" :key="index" :label="item.label"
+                :value="item.value" />
+            </el-select>
+          </el-form-item>
         </template>
-      </el-table-column>
-    </el-table>
-    <Paginate />
+      </Search>
+      <div class="table-default">
+        <div class="pt-5 pl-2" v-action="'operation.Banner.add'">
+          <el-button type="primary" size="default" @click="openForm(null)">新增</el-button>
+        </div>
+        <el-table :data="tableData" class="mt-3" v-loading="loading">
+          <el-table-column label="轮播图ID" prop="id"></el-table-column>
+          <el-table-column label="轮播图名称" prop="title">
+          </el-table-column>
+          <el-table-column label="封面" prop="img_url">
+            <template #default="scope">
+              <el-image :src="scope.row.img_url" fit="fill" :lazy="true"></el-image>
+            </template>
+          </el-table-column>
+          <el-table-column label="排序" prop="sort">
+          </el-table-column>
+          <el-table-column label="添加时间" prop="created_at">
+          </el-table-column>
+          <el-table-column label="小程序类型" prop="miniprogram_type_text">
+          </el-table-column>
+          <el-table-column label="状态" v-action="'operation.Banner.updateStatus'">
+            <template #default="scope">
+              <div>
+                <el-switch v-model="scope.row.status" @change="switchStatus(scope.row)" :active-value="1"
+                  :inactive-value="0">
+                </el-switch>
+              </div>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作">
+            <template #default="scope">
+              <el-button link type="primary" size="small" @click="handleEdit(scope.row)"
+                v-action="'operation.Banner.edit'">编辑</el-button>
+              <br />
+              <el-button link type="primary" size="small" @click="handleDel(scope.row)"
+                v-action="'operation.Banner.del'">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+        <Paginate />
+      </div>
+    </div>
   </div>
-  <Dialog v-model="addVisible" title="新增" width="30%" destroy-on-close>
+  <Dialog v-model="addVisible" :title="title" width="30%" destroy-on-close>
     <create @close="closeType('addVisible')" :primary="currentConfig"></create>
   </Dialog>
 </template>
@@ -53,15 +71,21 @@ import {
   operationBannerEditStatus,
   operationBannerDel
 } from '@/api/pageLayout/viewpagerPage/index';
-
+import { optionsCommonParams } from '@/api/common/index'
 const api = 'operation/banner/list';
-
+const miniprogramTypelist = ref([])
 const { data, query, search, reset, loading } = useGetList(api, true);
 const tableData = computed(() => data.value?.data);
 const addVisible = ref(false)
 const currentConfig = ref({})
+const title = ref('')
 const configVisible = ref(false) //设置回传弹窗
-
+const init = () => {
+  optionsCommonParams().then(res => {
+    console.log(res, 'optionsCommonParams');
+    miniprogramTypelist.value = res.data.miniprogramType
+  })
+}
 const closeType = (type: string) => {
   switch (type) {
     case 'configVisible':
@@ -77,8 +101,10 @@ const closeType = (type: string) => {
 const switchStatus = (data: object) => {
   operationBannerEditStatus(data.id, { status: data.status }).then(res => {
     ElMessage.success(res.message)
+    search()
+  }).catch(e => {
+    search()
   })
-  search()
 }
 
 const handleDel = (row: object) => {
@@ -103,15 +129,18 @@ const handleDel = (row: object) => {
 }
 
 const openForm = (data: any) => {
+  title.value = '新增'
   currentConfig.value = {}
   addVisible.value = true
 };
 const handleEdit = (data: object) => {
+  title.value = '编辑'
   currentConfig.value = data
   addVisible.value = true
 };
 onMounted(() => {
   search();
+  init()
 });
 </script>
 <style  lang='scss' scoped></style>