瀏覽代碼

视频库初版页面

pansl 2 年之前
父節點
當前提交
5c8719c6b2

+ 0 - 133
src/components/Upload/MultiUpload.vue

@@ -1,133 +0,0 @@
-<!--
-  多图上传组件
-  @author: youlaitech
-  @date 2022/11/20
--->
-
-<template>
-  <el-upload v-model:file-list="fileList" list-type="picture-card" :before-upload="handleBeforeUpload" :http-request="handleUpload" :on-remove="handleRemove" :on-preview="previewImg" :limit="props.limit">
-    <i-ep-plus />
-  </el-upload>
-
-  <el-dialog v-model="dialogVisible">
-    <img w-full :src="previewImgUrl" alt="Preview Image" />
-  </el-dialog>
-</template>
-
-<script setup lang="ts">
-import {
-  UploadRawFile,
-  UploadRequestOptions,
-  UploadUserFile,
-  UploadFile,
-  UploadProps
-} from 'element-plus';
-// import { uploadFileApi, deleteFileApi } from '@/api/file';
-
-const emit = defineEmits(['update:modelValue']);
-
-const props = defineProps({
-  /**
-   * 文件路径集合
-   */
-  modelValue: {
-    type: Array<string>,
-    default: [] as Array<string>
-  },
-  /**
-   * 文件上传数量限制
-   */
-  limit: {
-    type: Number,
-    default: 5
-  }
-});
-
-const previewImgUrl = ref('');
-const dialogVisible = ref(false);
-
-const fileList = ref([] as UploadUserFile[]);
-watch(
-  () => props.modelValue,
-  (newVal: string[]) => {
-    const filePaths = fileList.value.map(file => file.url);
-    // 监听modelValue文件集合值未变化时,跳过赋值
-    if (
-      filePaths.length > 0 &&
-      filePaths.length === newVal.length &&
-      filePaths.every(x => newVal.some(y => y === x)) &&
-      newVal.every(y => filePaths.some(x => x === y))
-    ) {
-      return;
-    }
-
-    fileList.value = newVal.map(filePath => {
-      return { url: filePath } as UploadUserFile;
-    });
-  },
-  { immediate: true }
-);
-
-/**
- * 自定义图片上传
- *
- * @param params
- */
-async function handleUpload(options: UploadRequestOptions): Promise<any> {
-  return;
-  // 上传API调用
-  const { data: fileInfo } = await uploadFileApi(options.file);
-
-  // 上传成功需手动替换文件路径为远程URL,否则图片地址为预览地址 blob:http://
-  const fileIndex = fileList.value.findIndex(
-    file => file.uid == (options.file as any).uid
-  );
-
-  fileList.value.splice(fileIndex, 1, {
-    name: fileInfo.name,
-    url: fileInfo.url
-  } as UploadUserFile);
-
-  emit(
-    'update:modelValue',
-    fileList.value.map(file => file.url)
-  );
-}
-
-/**
- * 删除图片
- */
-function handleRemove(removeFile: UploadFile) {
-  return;
-  const filePath = removeFile.url;
-
-  if (filePath) {
-    deleteFileApi(filePath).then(() => {
-      // 删除成功回调
-      emit(
-        'update:modelValue',
-        fileList.value.map(file => file.url)
-      );
-    });
-  }
-}
-
-/**
- * 限制用户上传文件的格式和大小
- */
-function handleBeforeUpload(file: UploadRawFile) {
-  if (file.size > 2 * 1048 * 1048) {
-    ElMessage.warning('上传图片不能大于2M');
-    return false;
-  }
-  return true;
-}
-
-/**
- * 预览图片
- */
-const previewImg: UploadProps['onPreview'] = uploadFile => {
-  previewImgUrl.value = uploadFile.url!;
-  dialogVisible.value = true;
-};
-</script>

+ 0 - 89
src/components/Upload/SingleUpload.vue

@@ -1,89 +0,0 @@
-<template>
-  <!-- 上传组件 -->
-  <el-upload class="single-uploader" v-model="imgUrl" :show-file-list="false" list-type="picture-card" :before-upload="handleBeforeUpload" :http-request="uploadFile">
-    <img v-if="imgUrl" :src="imgUrl" class="single" />
-    <el-icon v-else class="single-uploader-icon">
-      <Plus />
-    </el-icon>
-  </el-upload>
-</template>
-
-<script setup lang="ts">
-import { computed } from 'vue';
-import { Plus } from '@element-plus/icons-vue';
-import { UploadRawFile, UploadRequestOptions } from 'element-plus';
-// import { uploadFileApi } from '@/api/file';
-
-const emit = defineEmits(['update:modelValue']);
-
-const props = defineProps({
-  modelValue: {
-    type: String,
-    default: ''
-  }
-});
-
-const imgUrl = computed<string | undefined>({
-  get() {
-    return props.modelValue;
-  },
-  set(val) {
-    // imgUrl改变时触发修改父组件绑定的v-model的值
-    emit('update:modelValue', val);
-  }
-});
-
-/**
- * 自定义图片上传
- *
- * @param options
- */
-async function uploadFile(options: UploadRequestOptions): Promise<any> {
-  return;
-  const { data: fileInfo } = await uploadFileApi(options.file);
-  imgUrl.value = fileInfo.url;
-}
-
-/**
- * 限制用户上传文件的格式和大小
- */
-function handleBeforeUpload(file: UploadRawFile) {
-  return;
-  if (file.size > 2 * 1048 * 1048) {
-    ElMessage.warning('上传图片不能大于2M');
-    return false;
-  }
-  return true;
-}
-</script>
-
-<style scoped>
-.single-uploader .single {
-  width: 178px;
-  height: 178px;
-  display: block;
-}
-</style>
-
-<style>
-.single-uploader .el-upload {
-  border: 1px dashed var(--el-border-color);
-  border-radius: 6px;
-  cursor: pointer;
-  position: relative;
-  overflow: hidden;
-  transition: var(--el-transition-duration-fast);
-}
-
-.single-uploader .el-upload:hover {
-  border-color: var(--el-color-primary);
-}
-
-.el-icon.single-uploader-icon {
-  font-size: 28px;
-  color: #8c939d;
-  width: 178px;
-  height: 178px;
-  text-align: center;
-}
-</style>

+ 284 - 0
src/components/Upload/myUpload.vue

@@ -0,0 +1,284 @@
+<template>
+  <div class="upload_wrap">
+    <el-upload v-if="!props.isDisableUpload" class="w-auto upload" ref="uploadRef" :file-list="waitFileList"
+      :multiple="props.isMultiple" :limit="props.limitNum" :list-type="listType" :accept="props.acceptType"
+      :auto-upload="false" :show-file-list="false" :disabled="props.isDisableUpload" :on-change="handleChange">
+      <div class="el-upload__text" v-if="listType == 'text'">
+        <el-icon>
+          <Upload />
+        </el-icon>
+        <span>上传文件</span>
+      </div>
+      <div v-else>
+        <el-icon>
+          <Plus />
+        </el-icon>
+      </div>
+    </el-upload>
+    <div class="template_list">
+      <div class="template" v-for="(item, index) in waitFileList" :key="index">
+        <span>
+          <el-icon>
+            <Link />
+          </el-icon>
+        </span>
+        <span class="documentName">{{ item.name }}</span>
+        <span v-if="!props.isDisableUpload">
+          <el-icon color="#000000a6" size="16" @click="removeFile(item)">
+            <Close />
+          </el-icon>
+        </span>
+        <span v-if="isDownLoad" style="paddingleft: 5px">
+          <el-icon @click="handleDownLoad(item)">
+            <Download />
+          </el-icon>
+        </span>
+      </div>
+    </div>
+    <div class="tips" v-if="!props.isDisableUpload && isShowTips"><span>支持{{ acceptTypeDesc }};</span> <span
+        v-if="isLimitSize">文件大小不能超过{{
+          props.maxFileSize }}M</span> </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { ref, watch } from "vue";
+import { ElLoading, ElMessage } from "element-plus";
+import request from '@/api/http';
+import { Close, Upload, Download, Plus, Link } from "@element-plus/icons-vue";
+const emits = defineEmits(["fileSuccess", "fileRemove"]);
+interface Props {
+  acceptType?: string; // 上传文件类型
+  acceptTypeDesc?: string; // 描述 - 上传文件类型
+  isMultiple?: boolean; //   是否可批量上传
+  limitNum?: number; // 允许上传文件的最大数量
+  isDisableUpload?: boolean; // 是否禁用上传
+  maxFileSize?: number; // 文件大小
+  isLimitSize?: boolean;//是否限制大小
+  isShowTips?: boolean;
+  action?: string;
+  fileList?: any; // 回显的文件
+  isDownLoad?: boolean; // 是否可以下载
+  listType?: string;//文件上传样式类型
+}
+// 接收父组件传递过来的参数
+const props = withDefaults(defineProps<Props>(), {
+  acceptType: ".jpeg,.png",
+  acceptTypeDesc: ".png/.jpeg",
+  isMultiple: false,
+  limitNum: 10,
+  isDisableUpload: false,
+  maxFileSize: 0.3,
+  isShowTips: true,
+  isLimitSize: true,
+  action: "/activity/resource/uploadFile",
+  fileList: [],
+  isDownLoad: false,
+  listType: 'picture-card'
+});
+let waitFileList = ref<any[]>([]);
+
+waitFileList.value = props.fileList;
+waitFileList.value?.forEach((item: any) => {
+  item.name = item.original;
+});
+
+watch(
+  () => props.fileList,
+  () => {
+    console.log("props.fileList====>", props.fileList);
+    waitFileList.value = props.fileList;
+    waitFileList.value?.forEach((item: any) => {
+      item.name = item.original;
+    });
+  }
+);
+
+// 文件变化Handle 这里监听上传文件的变化是一个一个接收到变化的,所以文件也是一个一个上传到服务器上面的
+const handleChange = async (file: any, fileList: any[]) => {
+  // 防止多次执行change
+  const rawFile = file.raw;
+  const list = props.acceptTypeDesc.split("/");
+  let acceptTypeList = list.map((its: string) => {
+    return getType(its)
+  })
+  // 如果要检索的字符串值没有出现,则该方法返回 -1
+  const ars = acceptTypeList.filter((q: string) => {
+    return rawFile.type.indexOf(q) > -1
+  })
+  // 用于校验是否符合上传条件
+  const type = props.acceptTypeDesc.replace("/", ", ");
+  if (ars.length < 1) {
+    ElMessage.error(`仅支持格式为${type}的图片`);
+    return false;
+  } else if (rawFile.size / 1024 / 1024 > props.maxFileSize && isLimitSize) {
+    ElMessage.error(`文件大小不能超过${props.maxFileSize}MB!`);
+    const arr = [...waitFileList.value];
+    waitFileList.value = arr.filter((item: any) => {
+      return item.uid != rawFile.uid;
+    });
+    return false;
+  } else {
+    let formData = new FormData();
+    formData.append("file", rawFile);
+    formData.append("fileType", "2");
+    const loadingInstance = ElLoading.service({
+      text: "正在上传",
+      background: "rgba(0,0,0,.2)",
+    });
+    // 上传到服务器上面
+    const requestURL: string = props.action;
+    request("post", requestURL, formData, {
+      headers: { "Content-Type": "multipart/form-data" },
+    })
+      .then(async (res: any) => {
+        if (res.code == 0) {
+          loadingInstance.close();
+          let obj = {
+            ...res.data,
+            name: res.data.original,
+          };
+          emits("fileSuccess", obj);
+        } else {
+          loadingInstance.close();
+          ElMessage.warning(`文件上传失败`);
+        }
+      })
+      .catch(() => {
+        loadingInstance.close();
+        // ElMessage.warning(`文件上传失败`);
+      });
+  }
+  return true;
+};
+
+// 校验上传文件格式
+const getType = (acceptType: string) => {
+  let val = "";
+  switch (acceptType) {
+    case "xls":
+      val = "excel";
+      break;
+    case "doc":
+      val = "word";
+      break;
+    case "pdf":
+      val = "pdf";
+      break;
+    case "zip":
+      val = "zip";
+      break;
+    case "xlsx":
+      val = "sheet";
+      break;
+    case "pptx":
+      val = "presentation";
+      break;
+    case "docx":
+      val = "document";
+      break;
+    case "text":
+      val = "text";
+      break;
+    case "jpeg":
+      val = "jpeg";
+      break;
+    case "png":
+      val = "png";
+      break;
+    case "gif":
+      val = "gif";
+      break;
+    case "mp4":
+      val = "mp4";
+      break;
+    case "mp3":
+      val = "mp3";
+      break;
+  }
+  return val
+};
+
+// 移除文件
+const removeFile = (file: any) => {
+  const arr: any[] = [...waitFileList.value];
+  waitFileList.value = arr.filter((its: any) => {
+    return its.id != file.id;
+  });
+  emits("fileRemove", waitFileList.value);
+};
+
+const handleDownLoad = (row: { ossFile: string }) => {
+  const str = window.location.href.split("#")[0];
+  const herf = str.slice(0, str.length - 1);
+  window.location.href = herf + row.ossFile;
+};
+</script>
+
+<style lang="scss" scoped>
+.upload_wrap {
+  .upload {
+    width: auto;
+    padding-bottom: 10px;
+  }
+
+  .tips {
+    display: block;
+    font-size: 14px;
+    font-family: PingFangSC-Regular, PingFang SC;
+    font-weight: 400;
+    color: rgba(0, 0, 0, 0.65);
+  }
+}
+
+:deep().el-upload__text {
+  width: 106px;
+  height: 32px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: #ffffff;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+
+  img {
+    display: block;
+    width: 14px;
+    height: 14px;
+  }
+
+  span {
+    font-size: 14px;
+    padding-left: 6px;
+    font-family: PingFangSC-Regular, PingFang SC;
+    font-weight: 400;
+    color: rgba(0, 0, 0, 0.65);
+  }
+}
+
+.template_list {
+  padding-bottom: 4px;
+}
+
+.template {
+  display: flex;
+  align-items: center;
+  padding: 5px 0;
+
+  span {
+    line-height: 16px;
+  }
+
+  img {
+    margin-right: 8px;
+    width: 16px;
+    height: 16px;
+  }
+
+  .documentName {
+    margin-right: 12px;
+    font-size: 14px;
+    color: rgba(0, 0, 0, 0.65);
+  }
+}
+</style>
+

+ 1 - 1
src/router/modules/applet.ts

@@ -3,7 +3,7 @@ import { RouteRecordRaw } from 'vue-router';
 // @ts-ignore
 const router: RouteRecordRaw[] = [
   {
-    path: '/users',
+    path: '/applet',
     component: () => import('@/layout/index.vue'),
     meta: { title: '小程序管理', icon: 'user' },
     children: [

+ 2 - 2
src/router/modules/video.ts

@@ -8,8 +8,8 @@ const router: RouteRecordRaw[] = [
     meta: { title: '视频库管理', icon: 'user' },
     children: [
       {
-        path: 'applet',
-        name: 'applet-account',
+        path: 'video',
+        name: 'video-account',
         meta: { title: '视频库管理', icon: 'home' },
         component: () => import('@/views/videoManage/index.vue')
       }

+ 44 - 0
src/views/videoManage/detail.vue

@@ -0,0 +1,44 @@
+<template>
+  <div class="flex flex-col justify-between w-full sm:flex-row">
+    <div class="table-default">
+      <el-table :data="tableData" class="mt-3" v-loading="loading">
+        <el-table-column prop="id" label="章节名称" />
+        <el-table-column prop="email" label="是否付费">
+          <template #default="scope">
+            <el-tooltip placement="top" v-if="scope.row.remark">
+              <template #content> {{ scope.row.remark }}<br /> </template>
+              <span>{{ scope.row.email }}</span>
+            </el-tooltip>
+            <span v-else>{{ scope.row.email }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column prop="username" label="章节时长" />
+        <el-table-column label="操作" width="200">
+          <template #default="scope">
+            <el-button link type="primary" size="small">播放</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <Paginate />
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { computed, onMounted, ref } from 'vue';
+import Create from './create.vue';
+import { useGetList } from '@/hook/curd/useGetList';
+import { useOpen } from '@/hook/curd/useOpen';
+
+const statusapi = 'users';
+const applet = ref([{ id: 1, name: '微信', value: 'wx' }, { id: 2, name: '抖音', value: 'dy' }])
+const api = 'channel/advertiser/listAdvertiser';
+const { data, query, search, reset, loading } = useGetList(api);
+const { open, close, title, visible, id } = useOpen();
+
+const tableData = computed(() => data.value?.data);
+
+onMounted(() => {
+  search();
+});
+</script>

+ 0 - 16
src/views/videoManage/excelTitle.ts

@@ -1,16 +0,0 @@
-// 导出中文/字段
-export const titleObj = {
-  书名: 'name',
-  bid: 'id',
-  章节数: 'chapter_count',
-  字数: 'size',
-  状态: 'status_text',
-  作者: 'author',
-  类型: 'category_name',
-  所属cp方: 'cp_name',
-  合作模式: 'settlement_type_text',
-  保底金额: 'bottomline',
-  合作开始时间: 'start_date',
-  合作结束时间: 'end_date',
-  入库时间: 'created_at'
-};

+ 167 - 114
src/views/videoManage/form/create.vue

@@ -1,135 +1,185 @@
 <template>
-  <el-form :model="formDataForm" label-width="120px" ref="form" v-loading="loading" class="pr-4">
-    <el-form-item label="合作模式" prop="settlement_type"
-      :rules="[{ required: false, message: '请选择合作模式', trigger: 'change' }]">
-      <el-select v-model="formDataForm.settlement_type" filterable placeholder="选择合作模式">
-        <el-option v-for="(item, index) in cooperations" :key="index" :label="item.name" :value="item.value" />
-      </el-select>
-    </el-form-item>
-    <el-form-item v-if="formDataForm.settlement_type == 'bottomline'" label="保底金额" prop="bottomline"
-      :rules="[{ required: true, message: '保底金额必须填写' }]">
-      <el-input v-model="formDataForm.bottomline" name="bottomline" clearable />
-    </el-form-item>
-    <el-form-item label="合作期限" prop="time" :rules="[{ required: false, message: '请选择合作期限', trigger: 'change' }]">
-      <el-date-picker format="YYYY/MM/DD" value-format="YYYY-MM-DD" @change="timeChange" unlink-panels
-        v-model="formDataForm.time" type="daterange" :shortcuts="shortcuts" range-separator="To" start-placeholder="开始时间"
-        end-placeholder="结束时间" />
-    </el-form-item>
-    <el-form-item label="连载状态">
-      <el-radio-group v-model="formDataForm.status">
-        <el-radio :label="0">连载</el-radio>
-        <el-radio :label="1">完本</el-radio>
-      </el-radio-group>
-    </el-form-item>
-    <el-form-item label="分库权限" v-if="ismulSet">
-      <el-checkbox-group v-model="extraForm.distribution_privilege">
-        <el-checkbox :checked="Boolean(item.is_enabled)" @change="depotsChange($event, item)" :label="item"
-          v-for="item in dataObj" :key="item.channel_id">
-          {{ item.remark }}
-        </el-checkbox>
-      </el-checkbox-group>
-    </el-form-item>
+  <el-form :model="formData" label-width="120px" ref="ruleForm" :rules="rules" v-loading="loading" class="pr-4">
+    <div class="flex flex-row justify-between">
+      <div class="w-full">
+        <el-form-item label="短剧名称" prop="email">
+          <el-input v-model="formData.email" placeholder="请输入短剧名称" />
+        </el-form-item>
+        <el-form-item label="集数" prop="username">
+          <el-input v-model="formData.username" placeholder="请输入集数" />
+        </el-form-item>
+        <el-form-item label="完结状态" prop="miniProgramIds">
+          <el-select class="w-full" v-model="formData.miniProgramIds" remote filterable multiple
+            :remote-method="remoteMethod" clearable placeholder="选择类型">
+            <el-option v-for="item in cpList" :key="item.cp_id" :label="item.cp_name" :value="item.cp_name" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="频道" prop="miniProgramIds">
+          <el-select class="w-full" v-model="formData.miniProgramIds" remote filterable multiple
+            :remote-method="remoteMethod" clearable placeholder="选择类型">
+            <el-option v-for="item in cpList" :key="item.cp_id" :label="item.cp_name" :value="item.cp_name" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="上架" prop="status">
+          <el-radio-group v-model="formData.radio">
+            <el-radio :label="3">Option A</el-radio>
+            <el-radio :label="6">Option B</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="起始集" prop="password">
+          <el-input v-model="formData.password" clearable type="password" autocomplete="new-password" size="large"
+            placeholder="请输入起始集" show-password class="h-12 text-base" />
+        </el-form-item>
+        <el-form-item label="默认定价" prop="repassword">
+          <div class="flex items-center w-full">
+            <el-input v-model="formData.username" placeholder="请输入集数" />
+            <el-tooltip placement="top">
+              <template #content> multiple lines<br />second line </template>
+              <el-icon>
+                <InfoFilled />
+              </el-icon>
+            </el-tooltip>
+          </div>
+        </el-form-item>
+        <el-form-item label="所属CP方" prop="miniProgramIds">
+          <el-select class="w-full" v-model="formData.miniProgramIds" remote filterable multiple
+            :remote-method="remoteMethod" clearable placeholder="选择类型">
+            <el-option v-for="item in cpList" :key="item.cp_id" :label="item.cp_name" :value="item.cp_name" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="分成模式" prop="miniProgramIds">
+          <el-select class="w-full" v-model="formData.miniProgramIds" remote filterable multiple
+            :remote-method="remoteMethod" clearable placeholder="选择类型">
+            <el-option v-for="item in cpList" :key="item.cp_id" :label="item.cp_name" :value="item.cp_name" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="备注" prop="remark">
+          <my-upload></my-upload>
+          <el-input v-model="formData.remark" placeholder="请填写备注" type="textarea" />
+        </el-form-item>
+      </div>
+    </div>
     <div class="flex justify-end">
-      <el-button type="primary" @click="submitForm(form)">{{
-        $t('system.confirm')
-      }}</el-button>
+      <el-button type="primary" @click="submitForm(ruleForm)">{{ $t('system.confirm') }}</el-button>
     </div>
   </el-form>
 </template>
 
 <script lang="ts" setup>
+import { InfoFilled } from '@element-plus/icons-vue';
 import { useCreate } from '@/hook/curd/useCreate';
 import { useShow } from '@/hook/curd/useShow';
-
-import { onMounted } from 'vue';
-import { shortcuts } from '@/utils/shortcuts'
-import { bookSettlementypes, bookEditAuthor, bookDistribute, bookDistributeSave } from '@/api/bookManage/index';
-import { FormInstance } from 'element-plus';
-
+import { cpManageCpList, cpOptions } from '@/api/cp/index'
+import { advertiserGetAdvertiser, advertiserAdd, advertiserUpdateAdvertiser } from '@/api/advertiser/index'
+import type { FormInstance, FormRules } from 'element-plus'
+const ruleForm = ref<FormInstance>()
+import { onMounted, ref } from 'vue';
 const props = defineProps({
   primary: String | Number,
-  addapi: String,
-  eidapi: String,
-  ismulSet: Boolean
 });
+const formData = ref({ status: 2, miniProgramIds: [] })
+//自定义校验规则
+const validatePasswordConfirmation = (
+  rule: any,
+  value: any,
+  callback: any
+) => {
+  if (value === '') {
+    callback(new Error('请再次输入密码'));
+  } else if (value !== ruleForm.password) {
+    callback(new Error('两次密码不匹配'));
+  } else {
+    callback();
+  }
+};
+const rules = reactive({
+  miniProgramIds: [{ required: true, message: '请选择小程序' }],
+  email: [
+    {
+      required: true,
+      message: '请输入登录账号',
+      trigger: 'blur'
+    },
+    {
+      type: 'email',
+      message: '邮箱格式不正确',
+      trigger: 'blur'
+    }
+  ],
+  remark: [
+    {
+      required: true,
+      message: '请输入备注',
+      trigger: 'blur'
+    }
+  ],
+  username: [
+    {
+      required: true,
+      message: '请输入用户名',
+      trigger: 'blur'
+    }
+  ],
+  password: [
+    {
+      required: true,
+      message: '请输入密码',
+      trigger: 'blur'
+    },
+    {
+      pattern: /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,20}$/,
+      message:
+        '必须包含大小写字母和数字的组合,可以使用特殊字符,长度在6-20之间'
+    }
+  ],
+  repassword: [
+    {
+      required: true,
+      message: '请再次输入密码',
+      trigger: 'blur'
+    },
+    { validator: validatePasswordConfirmation, trigger: 'blur' }
+  ]
+});
+const loading = ref(false)
 
-const cooperations = ref([]);
-
-const formDataForm = ref({})
-const extraForm = ref({})
-const dataObj = ref([])
-
-const { formData, form, loading, close } = useCreate(
-  props.addapi,
-  props.primary,
-  true,
-  "post"
-);
-// 分库权限
-const depotsChange = (e, item) => {
-  console.log(e, item);
-  item.is_enabled = Number(e)
-}
-
-let ismulSet = ref(false)
-if (Array.isArray(props.primary)) {
-  ismulSet.value = true
-} else {
-  ismulSet.value = false
-}
-
-if (ismulSet.value) {
-  formDataForm.value = {}
-}
-
-const timeChange = (e) => {
-  const timeArr = toRaw(e);
-  // console.log(timeArr, 'timeArrtimeArrtimeArr');
-  if (Array.isArray(timeArr)) {
-    formDataForm.value.start_date = timeArr[0]
-    formDataForm.value.end_date = timeArr[1]
+const remoteMethod = (query: string) => {
+  if (query) {
+    initCpOtion({ cp_name: query })
   } else {
-    formDataForm.value.start_date = ''
-    formDataForm.value.end_date = ''
+    initCpOtion({})
   }
 }
 
-if (props.primary) {
-  const { afterShow } = useShow(props.eidapi, props.primary, formData);
-  if (!ismulSet.value) {
-    afterShow.value = formData => {
-      const data = unref(formData);
-      formDataForm.value = {
-        settlement_type: data.settlement_type,
-        bottomline: data.bottomline,
-        time: data.time,
-        status: data.status,
-        start_date: data.start_date,
-        end_date: data.end_date
-      }
-      formDataForm.value.bid = "" + props.primary
-      formDataForm.value.time = [data.start_date, data.end_date]
-    };
-  }
+const initCpOtion = (params: object) => {
+  cpOptions(params).then(res => {
+    cpList.value = res.data;
+  })
 }
-const emit = defineEmits(['close', 'mulSetclose']);
 
+const passwordRules = [
+  {
+    required: true,
+    message: '密码必须填写'
+  },
+  {
+    pattern: /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,20}$/,
+    message: '必须包含大小写字母和数字的组合,可以使用特殊字符,长度在6-20之间'
+  }
+];
 const submitForm = (formEl: FormInstance | undefined) => {
-  formDataForm.value.bid = "" + props.primary
-  // console.log(formEl,'formElformEl');
+  console.log(formData.value, 'formData.valueformData.value');
   if (!formEl) return;
   formEl
     .validate(valid => {
       if (valid) {
-        let channels = toRaw(dataObj.value).map(el => {
-          return {
-            channel_id: el.channel_id,
-            is_enabled: el.is_enabled
-          }
-        })
-        formDataForm.value.distribution_privilege = channels;
-        console.log({ ...formDataForm.value });
-        bookEditAuthor({ ...formDataForm.value }).then(res => {
+        let api;
+        if (props.primary) {
+          api = advertiserUpdateAdvertiser
+        } else {
+          api = advertiserAdd
+        }
+        api({ ...formData.value }).then(res => {
           console.log(res);
           ElMessage.success(res.message)
           emit('close')
@@ -141,13 +191,16 @@ const submitForm = (formEl: FormInstance | undefined) => {
     .then(() => { });
 }
 
-onMounted(async () => {
-  bookSettlementypes().then(res => {
-    cooperations.value = res.data
+if (props.primary) {
+  advertiserGetAdvertiser({ id: props.primary }).then(res => {
+    console.log(res, 'props.primary');
+    formData.value = res.data
   })
-  close(() => emit('close'));
+}
 
-  let { data } = await bookDistribute(-1);
-  dataObj.value = data
+const emit = defineEmits(['close']);
+const cpList = ref();
+onMounted(() => {
+  initCpOtion({})
 });
 </script>

+ 0 - 65
src/views/videoManage/form/depots.vue

@@ -1,65 +0,0 @@
-<template>
-  <el-checkbox-group v-model="depotsValue">
-    <el-checkbox :checked="Boolean(item.is_enabled)" @change="depotsChange($event, item)" :label="item"
-      v-for="item in dataObj" :key="item.channel_id">
-      {{ item.remark }}
-    </el-checkbox>
-  </el-checkbox-group>
-  <div class="wrapper">
-    <el-button type="primary" size="default" @click="doSave">提交</el-button>
-  </div>
-</template>
-
-<script lang="ts" setup>
-import { bookDistribute, bookDistributeSave } from '@/api/bookManage/index';
-
-const props = defineProps({
-  primary: Object,
-});
-const depotsValue = ref([])
-const dataObj = ref([])
-const emit = defineEmits(['close']);
-const depotsChange = (e, item) => {
-  console.log(e, item);
-  item.is_enabled = Number(e)
-}
-
-
-const doSave = () => {
-  let channels = toRaw(dataObj.value).map(el => {
-    return {
-      channel_id: el.channel_id,
-      is_enabled: el.is_enabled
-    }
-  })
-  console.log(channels);
-  bookDistributeSave(props.primary.id, { channels: channels }).then(res => {
-    console.log(res);
-    ElMessage.success(res.message)
-    emit('close', false)
-  })
-}
-
-
-onMounted(async () => {
-  let { data } = await bookDistribute(props.primary.id, {});
-  console.log(data);
-  dataObj.value = data
-})
-
-</script>
-
-<style lang="scss" scoped>
-::v-deep(.el-input__wrapper) {
-  display: flex;
-  width: 180px;
-  flex: none;
-}
-
-.wrapper {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  width: 100%;
-}
-</style>

+ 0 - 72
src/views/videoManage/form/depotsTransfer.vue

@@ -1,72 +0,0 @@
-<template>
-  <el-transfer v-model="depotsValue" :props="{
-    key: 'channel_id',
-    label: 'remark',
-  }" :titles="['未设平台', '已设平台']" filterable @right-check-change="transferChange" :filter-method="filterMethod"
-    filter-placeholder="搜索" :data="dataObj" />
-  <div class="wrapper">
-    <el-button type="primary" size="default" @click="doSave">提交</el-button>
-  </div>
-</template>
-
-<script lang="ts" setup>
-import { bookDistribute, bookDistributeSave } from '@/api/bookManage/index';
-
-const props = defineProps({
-  primary: Object,
-});
-const depotsValue = ref([])
-const dataObj = ref([])
-const channels = ref([])
-const emit = defineEmits(['close']);
-const transferChange = (e) => {
-  let arr = JSON.parse(JSON.stringify(dataObj.value))
-  const checkArr = arr.filter(el => e.includes(el.channel_id)).map(el => {
-    return {
-      channel_id: el.channel_id,
-      is_enabled: el.is_enabled
-    }
-  })
-  console.log(channels);
-  channels.value = checkArr
-
-}
-const filterMethod = (query, item) => {
-  return item.remark.includes(query)
-}
-const doSave = () => {
-  console.log(depotsValue.value, 'channels.value', toRaw(channels.value));
-  if (toRaw(channels.value).length <= 0) {
-    ElMessage.warning('请选择商户')
-  } else {
-    bookDistributeSave(props.primary.id, { channels: channels.value }).then(res => {
-      console.log(res);
-      ElMessage.success(res.message)
-      emit('close', false)
-    })
-  }
-}
-
-
-onMounted(async () => {
-  let { data } = await bookDistribute(props.primary.id, {});
-  console.log(data);
-  dataObj.value = data
-})
-
-</script>
-
-<style lang="scss" scoped>
-::v-deep(.el-input__wrapper) {
-  display: flex;
-  width: 180px;
-  flex: none;
-}
-
-.wrapper {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  width: 100%;
-}
-</style>

+ 175 - 0
src/views/videoManage/form/subscribeSet.vue

@@ -0,0 +1,175 @@
+<template>
+  <el-form :model="formData" label-width="120px" ref="ruleForm" :rules="rules" v-loading="loading" class="pr-4">
+    <div class="flex flex-row justify-between">
+      <div class="w-full">
+        <el-form-item label="收费模式" prop="email">
+          <el-radio-group v-model="formData.radio">
+            <el-radio :label="3">Option A</el-radio>
+            <el-radio :label="6">Option B</el-radio>
+            <el-radio :label="9">Option C</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="起始集" prop="miniProgramIds">
+          <el-select class="w-full" v-model="formData.miniProgramIds" remote filterable multiple
+            :remote-method="remoteMethod" clearable placeholder="选择类型">
+            <el-option v-for="item in cpList" :key="item.cp_id" :label="item.cp_name" :value="item.cp_name" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="单机定价" prop="repassword">
+          <div class="flex items-center w-full">
+            <el-input v-model="formData.username" placeholder="请输入集数" />
+            <el-tooltip placement="top">
+              <template #content> multiple lines<br />second line </template>
+              <el-icon>
+                <InfoFilled />
+              </el-icon>
+            </el-tooltip>
+          </div>
+        </el-form-item>
+      </div>
+    </div>
+    <div class="flex justify-end">
+      <el-button type="primary" @click="submitForm(ruleForm)">{{ $t('system.confirm') }}</el-button>
+    </div>
+  </el-form>
+</template>
+
+<script lang="ts" setup>
+import { InfoFilled } from '@element-plus/icons-vue';
+import { useCreate } from '@/hook/curd/useCreate';
+import { useShow } from '@/hook/curd/useShow';
+import { cpManageCpList, cpOptions } from '@/api/cp/index'
+import { advertiserGetAdvertiser, advertiserAdd, advertiserUpdateAdvertiser } from '@/api/advertiser/index'
+import type { FormInstance, FormRules } from 'element-plus'
+const ruleForm = ref<FormInstance>()
+import { onMounted, ref } from 'vue';
+const props = defineProps({
+  primary: String | Number,
+});
+const formData = ref({ status: 2, miniProgramIds: [] })
+//自定义校验规则
+const validatePasswordConfirmation = (
+  rule: any,
+  value: any,
+  callback: any
+) => {
+  if (value === '') {
+    callback(new Error('请再次输入密码'));
+  } else if (value !== ruleForm.password) {
+    callback(new Error('两次密码不匹配'));
+  } else {
+    callback();
+  }
+};
+const rules = reactive({
+  miniProgramIds: [{ required: true, message: '请选择小程序' }],
+  email: [
+    {
+      required: true,
+      message: '请输入登录账号',
+      trigger: 'blur'
+    },
+    {
+      type: 'email',
+      message: '邮箱格式不正确',
+      trigger: 'blur'
+    }
+  ],
+  remark: [
+    {
+      required: true,
+      message: '请输入备注',
+      trigger: 'blur'
+    }
+  ],
+  username: [
+    {
+      required: true,
+      message: '请输入用户名',
+      trigger: 'blur'
+    }
+  ],
+  password: [
+    {
+      required: true,
+      message: '请输入密码',
+      trigger: 'blur'
+    },
+    {
+      pattern: /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,20}$/,
+      message:
+        '必须包含大小写字母和数字的组合,可以使用特殊字符,长度在6-20之间'
+    }
+  ],
+  repassword: [
+    {
+      required: true,
+      message: '请再次输入密码',
+      trigger: 'blur'
+    },
+    { validator: validatePasswordConfirmation, trigger: 'blur' }
+  ]
+});
+const loading = ref(false)
+
+const remoteMethod = (query: string) => {
+  if (query) {
+    initCpOtion({ cp_name: query })
+  } else {
+    initCpOtion({})
+  }
+}
+
+const initCpOtion = (params: object) => {
+  cpOptions(params).then(res => {
+    cpList.value = res.data;
+  })
+}
+
+const passwordRules = [
+  {
+    required: true,
+    message: '密码必须填写'
+  },
+  {
+    pattern: /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,20}$/,
+    message: '必须包含大小写字母和数字的组合,可以使用特殊字符,长度在6-20之间'
+  }
+];
+const submitForm = (formEl: FormInstance | undefined) => {
+  console.log(formData.value, 'formData.valueformData.value');
+  if (!formEl) return;
+  formEl
+    .validate(valid => {
+      if (valid) {
+        let api;
+        if (props.primary) {
+          api = advertiserUpdateAdvertiser
+        } else {
+          api = advertiserAdd
+        }
+        api({ ...formData.value }).then(res => {
+          console.log(res);
+          ElMessage.success(res.message)
+          emit('close')
+        })
+      } else {
+        loading.value = false;
+      }
+    })
+    .then(() => { });
+}
+
+if (props.primary) {
+  advertiserGetAdvertiser({ id: props.primary }).then(res => {
+    console.log(res, 'props.primary');
+    formData.value = res.data
+  })
+}
+
+const emit = defineEmits(['close']);
+const cpList = ref();
+onMounted(() => {
+  initCpOtion({})
+});
+</script>

+ 18 - 54
src/views/videoManage/form/uploadBooks.vue

@@ -1,65 +1,29 @@
 <template>
   <el-form :model="formDataForm" label-width="120px" ref="form" v-loading="loading" class="pr-4">
-    <el-form-item label="书名" prop="book_name" :rules="[{ required: true, message: '书名必须填写' }]">
+    <el-form-item label="短剧名称" prop="book_name" :rules="[{ required: true, message: '书名必须填写' }]">
       <el-input v-model="formDataForm.book_name" name="name" clearable />
     </el-form-item>
-    <el-form-item label="作者" prop="author" :rules="[{ required: true, message: '作者必须填写' }]">
+    <el-form-item label="集数" prop="author" :rules="[{ required: true, message: '作者必须填写' }]">
       <el-input v-model="formDataForm.author" name="author" clearable />
     </el-form-item>
-    <el-form-item label="cp方" prop="cp" :rules="[{ required: true, message: '请选择cp方', trigger: 'change' }]">
-      <el-select v-model="formDataForm.cp" value-key="cp_id" filterable clearable remote :remote-method="remoteMethod"
-        placeholder="选择cp方">
-        <el-option v-for="item in cpoptions" :key="item.cp_id" :label="item.cp_nick" :value="item" />
-      </el-select>
-    </el-form-item>
-    <el-form-item label="类型" prop="channel" :rules="[{ required: true, message: '请选择类型', trigger: 'change' }]">
-      <el-radio-group v-model="formDataForm.channel">
-        <el-radio v-for="item in cooperations" :key="item.channel_id" :label="item.channel_id">
-          {{ item.channel_name }}
-        </el-radio>
-      </el-radio-group>
-    </el-form-item>
-    <el-form-item label="分类" prop="category" v-if="formDataForm.channel"
-      :rules="[{ required: true, message: '请选择分类', trigger: 'change' }]">
-      <el-select v-model="formDataForm.category" value-key="category_id" clearable filterable placeholder="选择分类">
-        <el-option v-for="item in categoryList" :key="item.category_id" :label="item.category_name" :value="item" />
-      </el-select>
-    </el-form-item>
-    <el-form-item label="连载状态" prop="status" :rules="[{ required: true, message: '请选择连载状态', trigger: 'change' }]">
-      <el-radio-group v-model="formDataForm.status">
-        <el-radio :label="0">连载</el-radio>
-        <el-radio :label="1">完本</el-radio>
-      </el-radio-group>
-    </el-form-item>
-    <el-form-item label="vip起始章节数" prop="vip_start"
-      :rules="[{ required: false, message: '请输入vip起始章节数', trigger: 'change' }]">
-      <el-input-number v-model="formDataForm.vip_start" :min="0" :step="1" step-strictly />
-    </el-form-item>
     <el-form-item label="上传" prop="path" :rules="[{ required: true, message: '请上传文件', trigger: 'change' }]">
-      <upload @success="uploadSuccess" @destory="uploadDestory" action="contentManage/book/import" class="w-full">
-        <template v-slot:default>
-          <el-button type="primary" size="default">点击上传</el-button>
-          <el-tooltip placement="top">
-            <template #content>
-              <h1 class="text-base font-medium text-light-600">上传TXT内容格式如下:</h1>
-              <div class="text-base font-medium">
-                ###章节标题
-              </div>
-              <div class="text-base font-medium">
-                正文正文正文
-              </div>
-            </template>
-            <el-icon size="20px" class="ml-5 cursor-pointer">
-              <InfoFilled />
-            </el-icon>
-          </el-tooltip>
-        </template>
-        <template v-slot:tip>
-          <div class="el-upload__tip text-red">
-            限制1个文件,新文件将覆盖旧文件
+      <div>支持MP4格式</div>
+      <el-tabs type="border-card" class="w-full">
+        <el-tab-pane label="默认剧集上传">
+          <div>默认剧集名称</div>
+          <div>
+            <my-upload :isShowTips="false" listType="text" acceptType=".mp4" acceptTypeDesc="mp4"
+              :isLimitSize="false"></my-upload>
+          </div>
+        </el-tab-pane>
+        <el-tab-pane label="自定义剧集上传">
+          <div class="flex items-start w-full">
+            <el-input v-model="formDataForm.video" class="w-full" placeholder="请输入剧集" size="normal" clearable></el-input>
+            <my-upload class="w-auto" :isShowTips="false" listType="text" acceptType=".mp4" acceptTypeDesc="mp4"
+              :isLimitSize="false"></my-upload>
           </div>
-        </template>
-      </upload>
+        </el-tab-pane>
+      </el-tabs>
     </el-form-item>
     <div class="flex justify-end">
       <el-button type="primary" @click="submitForm(form)">{{

+ 128 - 0
src/views/videoManage/form/videoDL.vue

@@ -0,0 +1,128 @@
+<template>
+  <div class="wrapper">
+    <video id="my-player" class="video-js" controls autoplay preload="auto" ref="myVideo" :poster="videoImg">
+      <source :src="videoUrl" type="video/mp4">
+    </video>
+    <!-- 视频名称列表布局 -->
+    <div class="video-wrapper">
+      <div class="flex items-center justify-between h-10">
+        <div>剧名</div>
+        <div v-if="videoChoose.length > 0"><el-button type="primary" size="default">下载</el-button></div>
+      </div>
+      <el-tabs>
+        <el-tab-pane :label="item.title" v-for="(item, i) in videoUrlList" :key="i">
+          <el-checkbox-group v-model="videoChoose" size="large" class="flex items-center">
+            <el-checkbox border class="video-item" @click="videoShow(source)" v-for="source in item.source"
+              :key="source.id" :label="source.ji">
+              {{ source.ji }}
+            </el-checkbox>
+          </el-checkbox-group>
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+  </div>
+</template>
+<script lang="ts" setup>
+import { ref } from 'vue'
+const myVideo = ref()
+const videoChoose = ref([])
+
+const videoImg = ref('https://img1.baidu.com/it/u=3406241258,3374807816&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1683651600&t=56bcf4002d6c1ebe1c05fcb9a82b793c')
+const videoUrlList = ref([
+  {
+    title: '1-100',
+    source: [{
+      id: 1,
+      ji: 1,
+      urlName: '视频1',
+      urlImg: 'https://img1.baidu.com/it/u=3406241258,3374807816&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1683651600&t=56bcf4002d6c1ebe1c05fcb9a82b793c',
+      urlMp4: 'https://vjs.zencdn.net/v/oceans.mp4'
+    }, {
+      id: 1,
+      ji: 2,
+      urlName: '视频1',
+      urlImg: 'https://cn.vuejs.org/images/logo.svg',
+      urlMp4: 'https://www.bilibili.com/video/BV1hV4y1G7i9?t=6.4'
+    },
+    {
+      id: 1,
+      ji: 3,
+      urlName: '视频1',
+      urlImg: 'https://cn.vuejs.org/images/logo.svg',
+      urlMp4: 'https://vjs.zencdn.net/v/oceans.mp4'
+    },
+    {
+      id: 1,
+      ji: 4,
+      urlName: '视频1',
+      urlImg: 'https://cn.vuejs.org/images/logo.svg',
+      urlMp4: 'https://vjs.zencdn.net/v/oceans.mp4'
+    },
+    {
+      id: 1,
+      ji: 5,
+      urlName: '视频1',
+      urlImg: 'https://cn.vuejs.org/images/logo.svg',
+      urlMp4: 'https://vjs.zencdn.net/v/oceans.mp4'
+    },
+    {
+      id: 1,
+      ji: 6,
+      urlName: '视频1',
+      urlImg: 'https://cn.vuejs.org/images/logo.svg',
+      urlMp4: 'https://vjs.zencdn.net/v/oceans.mp4'
+    }],
+  },
+  {
+    title: '100-101',
+    source: [{
+      id: 1,
+      ji: 101,
+      urlName: '视频1',
+      urlImg: 'https://cn.vuejs.org/images/logo.svg',
+      urlMp4: 'https://vjs.zencdn.net/v/oceans.mp4'
+    }],
+  }
+])
+const videoUrl = ref(videoUrlList.value[1].urlMp4)
+const videoShow = (source: object) => {
+  myVideo.value.src = source.urlMp4
+  videoImg.value = source.urlImg
+}
+</script>
+
+
+<style lang="scss" scoped>
+.wrapper {
+  padding-left: 40px;
+  margin-top: 30px;
+  display: flex;
+}
+
+//播放器样式
+video#my-player.video-js {
+  width: 30%;
+  height: 580px;
+  background-color: #000;
+}
+
+.video-wrapper {
+  margin-left: 40px;
+
+  .video-item {
+    margin: 6px;
+
+    :deep(.el-checkbox__input .el-checkbox__inner) {
+      display: none;
+    }
+  }
+
+  :deep(.el-checkbox-group .el-checkbox.is-checked) {
+    background-color: #2566ff;
+  }
+
+  :deep(.el-checkbox__input.is-checked + .el-checkbox__label) {
+    color: #fff
+  }
+}
+</style>

+ 45 - 51
src/views/videoManage/index.vue

@@ -2,52 +2,44 @@
   <div>
     <Search :search="search" :reset="reset">
       <template v-slot:body>
-        <el-form-item label="书名" prop="name">
-          <el-input v-model="query.name" name="name" clearable />
+        <el-form-item label="短剧" prop="name">
+          <el-input v-model="query.name" name="name" placeholder="请输入剧号/短剧名称" clearable />
         </el-form-item>
-        <el-form-item label="bid" prop="bid">
-          <el-input v-model="query.bid" name="bid" clearable />
-        </el-form-item>
-        <el-form-item label="作者" prop="author">
-          <el-input v-model="query.author" name="author" clearable />
-        </el-form-item>
-        <el-form-item label="cp方" prop="cp">
-          <el-select v-model="query.cp_id" filterable clearable remote :remote-method="remoteMethod" placeholder="选择版权方">
+        <el-form-item label="状态" prop="cp">
+          <el-select v-model="query.cp_id" filterable clearable remote :remote-method="remoteMethod" placeholder="请选择状态">
             <el-option v-for="item in cpoptions" :key="item.cp_id" :label="item.cp_nick" :value="item.cp_id" />
           </el-select>
         </el-form-item>
-        <el-form-item label="合作模式" prop="cp_company">
-          <el-select v-model="query.settlement_type" clearable filterable placeholder="选择合作模式">
+        <el-form-item label="频道" prop="cp_company">
+          <el-select v-model="query.settlement_type" clearable filterable placeholder="请选择频道">
             <el-option v-for="(item, index) in cooperations" :key="index" :label="item.name" :value="item.value" />
           </el-select>
         </el-form-item>
-        <el-form-item label="合作期限" prop="cooperate_date">
-          <el-date-picker unlink-panels format="YYYY/MM/DD" value-format="YYYY-MM-DD" v-model="query.cooperate_date"
-            type="datetimerange" @change="cooperateChange" :shortcuts="shortcuts" range-separator="To"
-            start-placeholder="开始时间" end-placeholder="结束时间" />
-        </el-form-item>
-        <!-- <el-form-item label="入库日期" prop="cp_company">
-          <el-date-picker unlink-panels format="YYYY/MM/DD hh:mm:ss" value-format="YYYY-MM-DD h:m:s" v-model="query.time"
-            type="datetimerange" @change="timeChange" :shortcuts="shortcuts" range-separator="To" start-placeholder="开始时间"
-            end-placeholder="结束时间" />
-        </el-form-item> -->
-      </template>
-      <template v-slot:extra_button>
-        <exportExcel api="contentManage/book/list" sheet_name="书籍列表" :title_obj="titleObj"
-          :extro_params="{ is_export: 1, ...query }">
-        </exportExcel>
       </template>
     </Search>
     <div class="table-default">
       <div class="set-warpper">
-        <el-button type="success" size="default" @click="openuploadBooksVisible"
-          v-action="'contentManage.book.createBook'">TXT导入小说</el-button>
         <el-button type="primary" @click="mulSet" size="default" v-action="'contentManage.book.mulSet'">批量操作</el-button>
       </div>
+      <Operate :show="open" />
       <el-table :data="tableData" class="mt-3" v-loading="loading" @selection-change="handleSelectionChange">
         <el-table-column type="selection" width="55" />
-        <el-table-column type="index" width="100" label="序号" />
-        <el-table-column label="书籍信息" width="200" show-overflow-tooltip>
+        <el-table-column type="index" width="100" label="剧号" />
+        <el-table-column label="封面" width="200" show-overflow-tooltip>
+          <template #default="scope">
+            <div class="book-wrapper">
+              <span class="book-label">书名:</span>
+              <span class="book-content">
+                {{ scope.row.name }}
+              </span>
+            </div>
+            <div class="book-wrapper">
+              <span class="book-label">bid:</span>
+              <span class="book-content">{{ scope.row.id }}</span>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="短剧名称" width="200" show-overflow-tooltip>
           <template #default="scope">
             <div class="book-wrapper">
               <span class="book-label">书名:</span>
@@ -73,18 +65,26 @@
             </div>
           </template>
         </el-table-column>
-        <el-table-column prop="author" label="作者" />
-        <el-table-column prop="category_name" label="分类" />
-        <el-table-column prop="channel_text" label="类型" />
-        <el-table-column prop="cp_name" label="所属cp方" />
-        <el-table-column prop="settlement_type_text" label="合作模式" />
-        <el-table-column prop="bottomline" label="保底金额" />
-        <el-table-column prop="created_at" label="合作期限">
+        <el-table-column prop="author" label="集数" />
+        <el-table-column prop="category_name" label="频道" />
+        <el-table-column prop="channel_text" label="上架状态" />
+        <el-table-column prop="cp_name" label="起始集" />
+        <el-table-column prop="settlement_type_text" label="定价">
+          <template #header>
+            <div class="flex items-center">
+              <span>定价</span>
+              <el-tooltip placement="top">
+                <template #content> multiple lines<br />second line </template>
+                <el-icon>
+                  <InfoFilled />
+                </el-icon>
+              </el-tooltip>
+            </div>
+          </template>
           <template #default="scope">
-            {{ `${scope.row.start_date} ~ ${scope.row.end_date}` }}
+            <span>{{ scope.row.price }}</span>
           </template>
         </el-table-column>
-        <el-table-column prop="created_at" label="入库时间" />
         <el-table-column label="操作">
           <template #default="scope">
             <el-button link type="primary" size="small" v-action="'contentManage.book.export'"
@@ -102,27 +102,21 @@
     <Dialog v-model="visible" :title="title" destroy-on-close>
       <Create @close="close(search)" :primary="id" :eidapi="addApi" :addapi="addApi" :ismulSet="ismulSet" />
     </Dialog>
-    <Dialog v-model="depotsVisible" title="平台设置" destroy-on-close>
-      <Depots @close="closeDeptos()" :primary="depotsData"></Depots>
-    </Dialog>
-    <!-- TXT导入小说 -->
-    <Dialog v-model="uploadBooksVisible" title="TXT导入小说" destroy-on-close>
-      <uploadBooks :primary="depotsData" @close="closeUpload"></uploadBooks>
+    <Dialog v-model="depotsVisible" width="50%" title="视频下载" destroy-on-close>
+      <videoDL @close="closeDeptos()" :primary="depotsData"></videoDL>
     </Dialog>
   </div>
 </template>
 
 <script lang="ts" setup>
+import { InfoFilled } from '@element-plus/icons-vue';
 import Create from './form/create.vue';
-import Depots from './form/depots.vue';
-import uploadBooks from './form/uploadBooks.vue';
+import videoDL from './form/videoDL.vue';
 import { useGetList } from '@/hook/curd/useGetList';
 import { useDestroy } from '@/hook/curd/useDestroy';
 import { useOpen } from '@/hook/curd/useOpen';
 import { shortcuts } from '@/utils/shortcuts';
 import { bookSettlementypes, bookList } from '@/api/bookManage/index';
-// import { exportExcel } from '@/utils/exportExcel';
-import { titleObj } from "./excelTitle"
 import moment from 'moment';
 import { cpOptions } from '@/api/cp/index';
 let ismulSet = ref(false)
@@ -131,7 +125,7 @@ const addApi = 'contentManage/book/edit_author';
 let multipleSelection = reactive([]);
 const { data, query, search, reset, loading } = useGetList(api);
 const { deleted } = useDestroy();
-const depotsVisible = ref(false)
+const depotsVisible = ref(true)
 const uploadBooksVisible = ref(false)
 const depotsData = ref({})
 const opendepots = (data) => {