Przeglądaj źródła

推荐管理重构

DESKTOP-2S67K1S\31396 2 lat temu
rodzic
commit
61cd5248b0

+ 43 - 55
src/api/operation/recommend.js

@@ -1,114 +1,102 @@
 import request from '@/utils/request'
 
 // 标签页分类
-export function listAll() {
+export function tabList() {
   return request({
-    url: `/recommendCategory/listAll`,
+    url: `/recommend/type/module/listAll`,
     method: 'get'
   })
 }
 
-// 标签页分类内容
-export function recommendList(query) {
+// 模板列表 
+export function typeList() {
   return request({
-    url: `/admin/recommendContentModule/allContentList`,
-    method: 'get',
-    params: query
+    url: `/recommend/type/getList`,
+    method: 'get'
   })
 }
 
-// 内容列表
-export function contentList(query) {
+// 二级列表
+export function list(id) {
   return request({
-    url: `/admin/recommendContentModule/list`,
-    method: 'get',
-    params: query
+    url: `/recommend/type/getSecondRecommend/${id}`,
+    method: 'get'
   })
 }
 
-// 保存分类下的某个模块
+// 新增 编辑 二级列表
 export function submit(data) {
   return request({
-    url: `/admin/recommendContentModule/save`,
+    url: `/recommend/type/module/second/saveOrUpdate`,
     method: 'post',
     data
   })
 }
 
-// 修改列表模块
-export function moduleDetail(query) {
-  return request({
-    url: `/recommendCategoryModule/detail`,
-    method: 'get',
-    params: query
-  })
-}
-
-
-// 音频内容列表
-export function radioList(query) {
+// 二级详情
+export function listDetail(id) {
   return request({
-    url: `/commonRadio/page`,
-    method: 'get',
-    params: query
+    url: `/recommend/type/getSecondRecommend/get/${id}`,
+    method: 'get'
   })
 }
 
-// 修改标题模块
-export function moduleContent(data){
+// 历史记录
+export function history(data) {
   return request({
-    url: `/recommendCategoryModule/update`,
+    url: `/recommend/type/history/list`,
     method: 'post',
     data
   })
 }
 
-// 上下架
-export function upOrDown(id, status){
+// 删除
+export function remove(lv, id) {
   return request({
-    url: `/admin/recommendContentModule/highOrSold/${id}/${status}`,
-    method: 'get' 
+    url: `/recommend/type/recmmend/delete/${lv}/${id}`,
+    method: 'get'
   })
 }
 
-// 新增时间段
-export function submitTime(data) {
+// 三级详情
+export function detail(id) {
   return request({
-    url: `/admin/appTime/addOrUpdate`,
-    method: 'post',
-    data
+    url: `/recommend/type/getThreeRecommend/get/${id}`,
+    method: 'get'
   })
 }
 
-// 查询时间段列表
-export function timeList() {
+// 查询模块
+export function moduleList(id) {
   return request({
-    url: `/admin/appTime/list`,
+    url: `/recommend/type/get/${id}`,
     method: 'get'
   })
 }
 
-// 删除 / 上下架时间段
-export function changeTime(ids, status) {
+// 音频内容列表
+export function radioList(query) {
   return request({
-    url: `/admin/appTime/hitOrSold/${ids}/${status}`,
-    method: 'get'
+    url: `/commonRadio/page`,
+    method: 'get',
+    params: query
   })
 }
 
-// 精选电台提交
-export function expandSave(data){
+// 新增 编辑 三级
+export function submitThree(data) {
   return request({
-    url: `/admin/recommendContentModule/expand/save`,
+    url: `/recommend/type/three/saveOrUpdate`,
     method: 'post',
     data
   })
 }
 
-// 删除精选电台
-export function removeList(ids, status){
+// 有效时间
+export function timeChange(data) {
   return request({
-    url: `/admin/recommendContentModule/highOrSold/${ids}/${status}`,
-    method: 'get'
+    url: `/recommend/type/time/saveOrUpdate`,
+    method: 'post',
+    data
   })
 }

+ 411 - 142
src/views/operation/recommend/detail.vue

@@ -1,193 +1,287 @@
 <template>
   <div class="app-container">
-    <el-button type="primary" icon="el-icon-plus" size="mini" @click="dialogVisible = true">新增</el-button>
-    <el-button size="mini" @click="close">返回</el-button>
+    <el-button type="primary" icon="el-icon-plus" size="mini" @click="getPush">新增</el-button>
     <!-- 模块 -->
-    <el-form class="form" v-for="(item, index) in list" :key="item.id" label-width="auto">
-      <el-form-item class="sort" :label="(index + 1).toString()">
-        <el-link icon="el-icon-close" :underline="false" />
-      </el-form-item>
-      <el-form-item v-if="'title' in item" label="标题:">
-        <el-input v-model="item.title" placeholder="请输入内容标题" />
-      </el-form-item>
-      <el-form-item v-if="'model' in item" label="模式:">
-        <el-select v-model="item.model" placeholder="请选择模式">
-          <el-option v-for="item in modelOptions" :key="item.value" :label="item.label" :value="item.value" />
-        </el-select>
-      </el-form-item>
-      <el-form-item v-if="'description' in item" label="简介:">
-        <el-input v-model="item.description" type="textarea" rows="4" placeholder="请输入简介" />
-      </el-form-item>
-      <el-form-item v-if="'contentName' in item" label="内容:">
-        <el-input v-model="item.contentName" prefix-icon="el-icon-search" placeholder="选择内容" />
-      </el-form-item>
-      <el-form-item v-if="'forwardType' in item" label="跳转方式:">
-        <el-select v-model="item.forwardType" placeholder="请选择跳转方式" @change="changeForwardType($event, index)">
-          <el-option v-for="item in forwardTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
-        </el-select>
-      </el-form-item>
-      <el-form-item v-if="'forwardUrl' in item" label="跳转地址:">
-        <el-input v-model="item.forwardUrl" placeholder="请输入跳转地址" />
-      </el-form-item>
-      <el-form-item v-if="'contentId' in item" label="专区页面:">
-        <el-select v-model="item.contentId" placeholder="请选择跳转专区">
-          <el-option v-for="item in sceneOptions" :key="item.value" :value="item.value" :label="item.label" />
-        </el-select>
-      </el-form-item>
-      <el-form-item v-if="'isCustom' in item" label="封面模式:">
-        <el-select v-model="item.isCustom" placeholder="选择封面模式">
-          <el-option v-for="item in coverOptions" :key="item.value" :label="item.label" :value="Number(item.value)" />
-        </el-select>
-      </el-form-item>
-      <el-form-item v-if="'pic' in item" label="图片:">
-        <Upload listType="picture-card" :url="item.pic" />
-      </el-form-item>
-      <el-form-item v-if="'sort' in item" label="排序:">
-        <el-input-number v-model="item.sort" />
-      </el-form-item>
-      <el-form-item v-if="'list' in item" label="列表:">
-        <el-table>
-          <el-table-column></el-table-column>
-        </el-table>
-      </el-form-item>
-      <el-form-item>
-        <el-button>清空</el-button>
-        <el-button type="primary" @click="getSubmit">提交</el-button>
-        <el-button type="primary" plain>上架</el-button>
-      </el-form-item>
-    </el-form>
+    <div style="display: flex; flex-wrap: wrap;">
+      <el-form class="form" v-for="(item, index) in form" :key="item.id" label-width="auto" :disabled="isRead">
+        <el-form-item class="sort" :label="(index + 1).toString()">
+          <el-link icon="el-icon-close" :underline="false" @click="getDelete(index)" />
+        </el-form-item>
+        <el-form-item v-if="'title' in item" label="标题:">
+          <el-input v-model="item.title" placeholder="请输入内容标题" />
+        </el-form-item>
+        <el-form-item v-if="'description' in item" label="简介:">
+          <el-input v-model="item.description" type="textarea" :autosize="{ minRows: 5, maxRows: 10 }"
+            placeholder="请输入简介" />
+        </el-form-item>
+        <el-form-item v-if="'contentName' in item" label="内容:">
+          <el-input v-model="item.contentName" prefix-icon="el-icon-search" placeholder="选择内容"
+            @focus="getDialog(item, index, false)" />
+        </el-form-item>
+        <el-form-item v-if="'forwardType' in item" label="跳转方式:">
+          <el-select v-model="item.forwardType" placeholder="请选择跳转方式" @change="forwardTypeChange(item)">
+            <el-option v-for="item in forwardTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
+          </el-select>
+        </el-form-item>
+        <el-form-item v-if="'forwardUrl' in item" label="跳转地址:">
+          <el-input v-model="item.forwardUrl" placeholder="请输入跳转地址" />
+        </el-form-item>
+        <el-form-item v-if="'contentId' in item" label="专区页面:">
+          <el-select v-model="item.contentId" placeholder="请选择跳转专区" @change="contentIdChange(item)">
+            <el-option v-for="item in sceneOptions" :key="item.value" :value="item.value" :label="item.label" />
+          </el-select>
+        </el-form-item>
+        <el-form-item v-if="'isCustom' in item" label="封面模式:">
+          <el-select v-model="item.isCustom" placeholder="选择封面模式" @change="isCustomChange(item, index)">
+            <el-option v-for="item in coverOptions" :key="item.value" :label="item.label" :value="Number(item.value)" />
+          </el-select>
+        </el-form-item>
+        <el-form-item v-if="'pic' in item" label="图片:">
+          <Upload listType="picture-card" :url="item.pic" @upload="upload($event, item)" :disabled="isRead" />
+        </el-form-item>
+        <el-form-item v-if="'sort' in item" label="排序:">
+          <el-input-number v-model="item.sort" />
+        </el-form-item>
+        <el-form-item v-if="'childList' in item" label="列表:">
+          <el-button type="primary" @click="getDialog(item, index, true)">添加内容</el-button>
+          <el-table :data="item.childList">
+            <el-table-column label="电台名称" prop="contentName" align="center" show-overflow-tooltip />
+            <el-table-column label="当前状态" prop="status" align="center" :formatter="statusFormatter" />
+            <el-table-column label="操作" align="center">
+              <template slot-scope="scope">
+                <el-button type="delete" @click="getRemove(scope.row, index)">删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-form-item>
+        <el-form-item label="当前状态:">
+          <el-select v-model="item.status" placeholder="请选择当前状态">
+            <el-option v-for="item in disabledOptions" :key="item.value" :value="item.value" :label="item.label" />
+          </el-select>
+        </el-form-item>
+        <el-form-item style="float: right">
+          <el-button type="info">清空</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+
+    <!-- 提交 返回按钮 -->
+    <div class="btn">
+      <el-button @click="cancel">取消</el-button>
+      <el-button v-if="!isRead" type="primary" @click="getSubmit">确定</el-button>
+    </div>
+
     <!-- 弹窗 -->
-    <el-dialog :visible.sync="dialogVisible" title="新增" width="500px">
-      <el-form label-width="100px">
-        <el-form-item label="模块选择:">
-          <el-select v-model="mouldList" multiple placeholder="请选择所需模块">
-            <el-option v-for="item in mouldOptions" :key="item.value" :value="item.value" :label="item.label" />
+    <el-dialog :visible.sync="dialogVisible" title="添加内容" width="1000px">
+      <el-form inline size="mini">
+        <el-form-item label="音频类型:">
+          <el-select v-model="dialogForm.audioType" placeholder="请选择类型" :disabled="disabled">
+            <el-option v-for="item in audioOptions" :key="item.value" :label="item.label" :value="Number(item.value)" />
           </el-select>
         </el-form-item>
+        <el-form-item label="资源平台:">
+          <el-select v-model="dialogForm.platformId" placeholder="请选择平台">
+            <el-option v-for="item in platformOptions" :key="item.value" :label="item.label" :value="item.value" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="内容:">
+          <el-input v-model="dialogForm.keyword" placeholder="请输入内容关键词" clearable />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" icon="el-icon-search" @click="getSearch">搜索</el-button>
+        </el-form-item>
       </el-form>
-      <div slot="footer">
-        <el-button>取消</el-button>
-        <el-button type="primary" @click="getPush">确定</el-button>
-      </div>
+      <el-table :data="dialogTableData" ref="dialogTableData" :row-key="rowKey" @selection-change="handleSelectionChange"
+        v-loading="loading">
+        <el-table-column v-if="isSelection" type="selection" align="center" reserve-selection key="selection" />
+        <el-table-column v-else label="操作" align="center" key="change">
+          <template slot-scope="scope">
+            <el-button type="text" @click="getSelect(scope.row)">
+              选择
+            </el-button>
+          </template>
+        </el-table-column>
+        <el-table-column label="音频ID" prop="audioId" align="center" key="audioId" show-overflow-tooltip />
+        <el-table-column label="音频名称" prop="audioName" align="center" key="audioName" show-overflow-tooltip />
+        <el-table-column label="音频封面" align="center" key="audioPic" width="100px">
+          <template slot-scope="scope">
+            <el-image :src="scope.row.audioPic" />
+          </template>
+        </el-table-column>
+        <el-table-column label="音频作者" prop="singerName" align="center" show-overflow-tooltip />
+        <el-table-column label="专辑名称" prop="songName" align="center" show-overflow-tooltip />
+        <el-table-column label="音频类型" prop="audioType" align="center" key="audioType" :formatter="audioFormatter" />
+        <el-table-column label="音频数量" prop="programCount" align="center" key="programCount" />
+        <el-table-column label="付费类型" align="center" key="isFree" :formatter="freeFormatter" width="100px" />
+        <el-table-column label="当前状态" align="center" key="status" :formatter="statusFormatter" />
+      </el-table>
+      <pagination v-show="total > 0" :total="total" :page.sync="dialogForm.pageNum" :limit.sync="dialogForm.pageSize"
+        @pagination="getList" />
     </el-dialog>
   </div>
 </template>
 
 <script>
 import { list } from '@/api/operation/scene'
-import { coverMixin } from '@/mixin/index'
+import { detail, moduleList, radioList, submitThree } from '@/api/operation/recommend'
+import { coverMixin, audioMixin, platformMixin, isFreeMixin, disabledMixin } from '@/mixin/index'
 export default {
-  mixins: [coverMixin],
+  mixins: [coverMixin, audioMixin, platformMixin, isFreeMixin, disabledMixin],
   data() {
     return {
-      // 模块
-      list: [],
+      // 遮罩层
+      loading: false,
+      // 二级id
+      secondId: this.$route.query.secondId,
+      // 三级id
+      threeId: this.$route.query.threeId,
+      // 表单
+      form: [],
+      // 模板
+      module: [],
       // 弹窗
       dialogVisible: false,
-      // 弹窗参数
-      mouldList: [],
-      // 模块选择
-      mouldOptions: [{
-        value: 'title',
-        label: '标题'
-      }, {
-        value: 'model',
-        label: '模式'
-      }, {
-        value: 'description',
-        label: '简介'
-      }, {
-        value: 'contentName',
-        label: '内容'
-      }, {
-        value: 'forwardType',
-        label: '跳转方式'
-      }, {
-        value: 'isCustom',
-        label: '封面模式'
-      }, {
-        value: 'pic',
-        label: '图片'
-      }, {
-        value: 'sort',
-        label: '排序'
-      }, {
-        value: 'list',
-        label: '列表'
-      }],
-      // 模板类型
-      modelOptions: [{
-        value: 0,
-        label: '自动推荐内容'
-      }, {
-        value: 1,
-        label: '手动推荐内容'
-      }],
+      // 弹窗表单
+      dialogForm: {
+        pageNum: 1,
+        pageSize: 10,
+        audioType: '',
+        platformId: ''
+      },
+      // 弹窗列表
+      dialogTableData: [],
+      // 总数据
+      total: 0,
+      // 禁止操作
+      disabled: false,
+      // 是否启用多选
+      isSelection: true,
+      // 弹窗索引
+      index: 0,
+      // 专区模块
+      sceneOptions: [],
       // 跳转方式
       forwardTypeOptions: [{
         value: 0,
-        label: '跳转广播',
+        label: 'APP内容跳转广播',
         type: 2
       }, {
         value: 1,
-        label: '跳转歌曲',
+        label: 'APP内容跳转歌曲',
         type: 11
       }, {
         value: 2,
-        label: '跳转歌单',
+        label: 'APP内容跳转歌单',
         type: 10
       }, {
         value: 3,
-        label: '跳转专辑',
+        label: 'APP内容跳转专辑',
         type: 8
       }, {
         value: 4,
-        label: '跳转节目',
+        label: 'APP内容跳转节目',
         type: 6
       }, {
         value: 7,
-        label: '跳转专区',
+        label: 'APP内容跳转专区',
         type: 16
       }, {
         value: 5,
-        label: '跳转H5内链'
+        label: 'H5内链'
       }, {
         value: 6,
-        label: '跳转H5外链'
+        label: 'H5外链'
       }],
-      // 专区模块
-      sceneOptions: []
+      // 只读
+      isRead: false,
+      // 缓存内容图片
+      picList: {}
+    }
+  },
+  watch: {
+    'dialogForm.audioType'(val) {
+      this.getPlatform({
+        audioType: val
+      })
     }
   },
   mounted() {
     this.getSceneList()
+    this.getModule()
   },
   methods: {
+    // 模块 详情
+    getModule() {
+      let moduleOptions = {
+        1: 'title',
+        3: 'description',
+        4: 'contentName',
+        5: 'forwardType',
+        6: 'isCustom',
+        7: 'pic',
+        8: 'sort',
+        9: 'childList'
+      }
+      moduleList(this.$route.query.moduleTypeId).then(res => {
+        if (res.code === 0) {
+          res.data.elementIds.map(i => {
+            this.module.push(moduleOptions[i])
+          })
+          if (this.$route.query.threeId) {
+            this.getDetail()
+            this.isRead = Boolean(this.$route.query.boolean)
+          }
+        }
+      })
+    },
+
+    // 详情
+    getDetail() {
+      detail(this.$route.query.threeId).then(res => {
+        if (res.code === 0 && res.data.list.length > 0) {
+          // 组件模板
+          let obj = {}
+          this.module.map(j => {
+            obj[j] = ''
+          })
+          // 将详情数据遍历
+          res.data.list.map((i, index) => {
+            let newObj = {}
+            // 只保留组件模板的参数
+            for (const key in i) {
+              if (obj.hasOwnProperty(key)) {
+                newObj[key] = i[key]
+                // 跳转方式关联 内容 栏目 地址
+                if ([0, 1, 2, 3, 4].includes(i.forwardType)) {
+                  newObj.contentName = i.contentName
+                  newObj.module = i.module
+                } else if ([5, 6].includes(i.forwardType)) {
+                  newObj.forwardUrl = i.forwardUrl
+                } else if ([7].includes(i.forwardType)) {
+                  newObj.contentId = i.module.contentId
+                  newObj.module = i.module
+                }
+
+                // 封面模式关联 图片
+                if (i.isCustom === 1) {
+                  this.picList[index] = i.pic
+                }
+              }
+              newObj.status = i.status
+            }
+            this.form.push(newObj)
+          })
+        }
+      })
+    },
+
     // 新增模块
     getPush() {
       let item = {}
-      this.mouldList.map(i => {
-        item[i] = null
+      this.module.map(i => {
+        item[i] = i === 'childList' ? [] : null
       })
-      this.list.push(item)
-      this.dialogVisible = false
-    },
-
-    // 跳转方式
-    changeForwardType(e, index) {
-      [5, 6].includes(e) ? [
-        this.list[index].forwardUrl = null,
-        delete this.list[index].contentName,
-        delete this.list[index].contentId,
-      ] : [7].includes(e) ? [
-        this.list[index].contentId = null,
-        delete this.list[index].contentName,
-        delete this.list[index].forwardUrl
-      ] : [
-        this.list[index].contentName = null,
-        delete this.list[index].forwardUrl,
-        delete this.list[index].contentId,
-      ]
+      this.form.push(item)
     },
 
     // 爱听专区
@@ -204,27 +298,188 @@ export default {
       })
     },
 
+    // 跳转方式
+    forwardTypeChange(item) {
+      this.$set(item, 'module', {}),
+        [0, 1, 2, 3, 4].includes(item.forwardType) ? [
+          this.$set(item, 'contentName', ''),
+          delete item.forwardUrl,
+          delete item.contentId
+        ] : [5, 6].includes(item.forwardType) ? [
+          this.$set(item, 'forwardUrl', ''),
+          delete item.contentName,
+          delete item.contentId
+        ] : [
+          this.$set(item, 'contentId', ''),
+          delete item.contentName,
+          delete item.forwardUrl
+        ]
+    },
+
+    // 封面模式
+    isCustomChange(item, index) {
+      item.isCustom === 1 ? item.pic = this.picList[index] : item.pic = ''
+    },
+
+    // 上传图片
+    upload(e, item) {
+      item.pic = e.file
+    },
+
+    // 专区页面
+    contentIdChange(item) {
+      item.module = {}
+      item.forwardType === 7 ? [
+        item.module.contentType = 16,
+        item.module.contentId = item.contentId
+      ] : ''
+    },
+
+    // 弹窗
+    getDialog(item, index, boolean) {
+      this.dialogVisible = true
+      this.index = index
+      this.isSelection = boolean
+      if ('forwardType' in item) {
+        this.dialogForm.audioType = this.forwardTypeOptions.find(i => i.value === item.forwardType).type
+        this.disabled = true
+      } else {
+        this.dialogForm.audioType = this.audioOptions[0].value
+      }
+      this.getList()
+    },
+
+    // 音频列表
+    getList() {
+      this.loading = true
+      radioList(this.dialogForm).then(res => {
+        if (res.code === 0) {
+          this.dialogTableData = res.data.records
+          this.total = res.data.total
+          let row = ''
+          if (this.form[this.index].childList && this.form[this.index].childList.length > 0) {
+            this.form[this.index].childList.map(i => {
+              row = res.data.records.find(j => j.audioId === i.module.contentId)
+            })
+          }
+          row ? this.$refs.dialogTableData.toggleRowSelection(row) : this.$refs.dialogTableData.clearSelection();
+          this.loading = false
+        }
+      })
+    },
+
+    // 搜索
+    getSearch() {
+      this.dialogForm.pageNum = 1
+      this.getList()
+    },
+
+    rowKey(row) {
+      return row.audioId
+    },
+
+    // 选择
+    getSelect(row) {
+      let e = this.form[this.index]
+      e.module = {
+        contentId: row.audioId,
+        platformId: row.platformId,
+        contentType: row.audioType,
+        description: row.description
+      }
+      e.contentName = row.audioName
+      e.pic = row.audioPic
+      // 封面模式自定义封面会丢失内容封面图片 所以缓存以便改回来使用
+      this.picList[this.index] = row.audioPic
+      this.$message.success('选择成功!')
+      this.dialogVisible = false
+    },
+
+    // 批量选择
+    handleSelectionChange(row) {
+      this.form[this.index].childList = []
+      if (row.length > 0) {
+        row.map(i => {
+          if (this.form[this.index].childList.findIndex(j => j.module.contentId === i.audioId) === -1) {
+            this.form[this.index].childList.push({
+              module: {
+                contentId: i.audioId,
+                platformId: i.platformId,
+                contentType: i.audioType,
+                description: i.description,
+              },
+              contentName: i.audioName,
+              pic: i.audioPic,
+              status: i.status
+            })
+          }
+        })
+      }
+    },
+
     // 提交
     getSubmit() {
-      console.log(this.list);
+      let data = this.secondId ? {
+        secondId: this.secondId,
+        list: this.form
+      } : {
+        threeId: this.threeId,
+        list: this.form
+      }
+      for (const key in this.form) {
+        delete this.form[key].contentId
+      }
+      submitThree(data).then(res => {
+        if (res.code === 0) {
+          this.$message.success('提交成功!')
+          this.cancel()
+        }
+      })
     },
 
     // 返回
-    close() {
-      this.$tab.closeOpenPage("/operation/recommend");
+    cancel() {
+      this.$tab.closeOpenPage("/operation/operationRecommend");
+    },
+
+    // 删除模块
+    getDelete(index) {
+      this.form.splice(index, 1)
+    },
+
+    // 删除关联
+    getRemove(row, index) {
+      let e = this.form[index].childList.findIndex(i => i.contentId === row.contentId)
+      this.form[index].childList.splice(e, 1)
+    },
+
+    // 字典翻译
+    audioFormatter(row) {
+      return this.selectDictLabel(this.audioOptions, row.audioType)
+    },
+    freeFormatter(row) {
+      return this.selectDictLabel(this.freeOptions, row.isFree)
+    },
+    statusFormatter(row) {
+      return this.selectDictLabel(this.disabledOptions, row.status)
     }
   }
 }
 </script>
 
 <style lang="scss" scoped>
+.app-container {
+  padding-bottom: 100px;
+}
+
 .form {
   width: 500px;
   border: 1px solid #dcdfe6;
-  box-shadow: 5px 5px 5px 0px #dcdfe6;
+  box-shadow: 5px 5px 5px 0 #dcdfe6;
   padding: 20px;
   margin-bottom: 20px;
   position: relative;
+  margin-right: 20px;
 
   .sort {
     ::v-deep .el-form-item__label-wrap {
@@ -236,4 +491,18 @@ export default {
     }
   }
 }
+
+.btn {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  height: 100px;
+  border-top: 1px solid #dcdfe6;
+  box-shadow: 5px 0 10px 0 #dcdfe6;
+  line-height: 100px;
+  text-align: right;
+  padding: 0 20px;
+  background: #FFF;
+}
 </style>

+ 228 - 151
src/views/operation/recommend/index.vue

@@ -2,76 +2,100 @@
   <div class="app-container">
     <el-button type="primary" icon="el-icon-plus" size="mini" @click="dialogVisible = true">新增</el-button>
     <!-- 列表 -->
-    <el-table :data="tableData" row-key="id" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
-      <el-table-column width="80px" />
-      <el-table-column label="排序" align="center" prop="sort"></el-table-column>
-      <el-table-column label="导航名称" align="center" prop="tabName"></el-table-column>
-      <el-table-column label="模板名称" align="center" prop="mouldName"></el-table-column>
-      <el-table-column label="模板数量" align="center" prop="number"></el-table-column>
+    <el-table :data="tableData" ref="tableData" row-key="id" :default-sort="{ prop: 'sort', order: 'ascending' }"
+      :tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
+      <el-table-column width="80px">
+        <template slot-scope="scope">
+          <el-link v-if="scope.row.hidden" :underline="false" class="el-icon-arrow-right" @click="getList(scope.row, scope.$index)" />
+        </template>
+      </el-table-column>
+      <el-table-column label="排序" align="center">
+        <template slot-scope="scope">
+          <span v-if="scope.row.lv === 2">{{ scope.row.sort }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="导航名称" align="center" prop="name" show-overflow-tooltip>
+        <template slot-scope="scope">
+          <span v-if="scope.row.lv === 1">{{ scope.row.name }}</span>
+          <span v-else>{{ tabOptions.find(i => i.id == scope.row.categoryId).name }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="模板名称" align="center" prop="moduleName" show-overflow-tooltip />
+      <el-table-column label="模板数量" align="center" prop="moduleNum" />
       <el-table-column label="创建时间" align="center" prop="createTime" show-overflow-tooltip />
-      <el-table-column label="当前状态" align="center" prop="status"></el-table-column>
-      <el-table-column label="生效时间" align="center" prop="time" show-overflow-tooltip />
+      <el-table-column label="当前状态" align="center" prop="status" :formatter="statusFormatter" />
+      <el-table-column label="生效时间" align="center" show-overflow-tooltip width="380px">
+        <template slot-scope="scope">
+          <el-date-picker v-if="scope.row.lv === 3" v-model="scope.row.rsDates" type="datetimerange"
+            start-placeholder="开始日期" end-placeholder="结束日期" value-format="yyyy-MM-dd HH:mm:ss"
+            @change="getChange(scope.row)" />
+        </template>
+      </el-table-column>
       <el-table-column label="操作" align="center">
         <template slot-scope="scope">
-          <el-button v-if="scope.row.type === 2" type="text" @click="getDetail">新增</el-button>
-          <el-button v-if="scope.row.type === 1" type="text" @click="getDialog()">历史记录</el-button>
+          <el-button v-if="scope.row.lv === 2" type="text" @click="getDetail(scope.row, '新增')">新增</el-button>
+          <el-button v-if="scope.row.lv === 1" type="text" @click="getDialog(scope.row.id)">历史记录</el-button>
           <span v-else style="margin-left: 10px">
-            <el-button type="text">查看</el-button>
-            <el-button type="text" @click="getDetail">编辑</el-button>
-            <el-button type="delete">删除</el-button>
+            <el-button type="text" @click="getOpen(scope.row, '查看', true)">查看</el-button>
+            <el-button type="text" @click="getOpen(scope.row, '编辑')">编辑</el-button>
+            <el-button type="delete" @click="getDelete(scope.row)">删除</el-button>
           </span>
         </template>
       </el-table-column>
     </el-table>
 
     <!-- 弹窗 -->
-    <el-dialog :visible.sync="dialogVisible" title="新增" width="500px">
-      <el-form label-width="100px">
-        <el-form-item label="导航名称:">
-          <el-select v-model="dialogForm.tabName" placeholder="请选择导航">
-            <el-option v-for="item in tabOptions" :key="item.value" :value="item.value" :label="item.label" />
+    <el-dialog :visible.sync="dialogVisible" :title="title" width="500px">
+      <el-form :model="dialogForm" :rules="rules" ref="dialogForm" label-width="100px" :disabled="title === '查看'">
+        <el-form-item label="导航名称:" prop="categoryId">
+          <el-select v-model="dialogForm.categoryId" placeholder="请选择导航">
+            <el-option v-for="item in tabOptions" :key="item.id" :value="item.id.toString()" :label="item.name" />
           </el-select>
         </el-form-item>
-        <el-form-item label="模板名称:">
-          <el-input v-model="dialogForm.mouldName" placeholder="请输入模板名称" />
+        <el-form-item label="模板名称:" prop="moduleName">
+          <el-input v-model="dialogForm.moduleName" placeholder="请输入模板名称" />
         </el-form-item>
-        <el-form-item label="模板类型:">
-          <el-select placeholder="请选择模板类型">
-            <el-option v-for="item in typeOptions" :key="item.value" :value="item.value" :label="item.label" />
+        <el-form-item label="模板类型:" prop="moduleTypeId">
+          <el-select v-model="dialogForm.moduleTypeId" placeholder="请选择模板类型">
+            <el-option v-for="item in typeOptions" :key="item.typeId" :value="item.typeId" :label="item.typeName" />
           </el-select>
         </el-form-item>
-        <el-form-item label="排序:">
-          <el-input-number v-model="dialogForm.id" />
+        <el-form-item label="排序:" prop="sort">
+          <el-input-number v-model="dialogForm.sort" :min="1" />
         </el-form-item>
       </el-form>
       <div slot="footer">
-        <el-button>取消</el-button>
-        <el-button type="primary">确定</el-button>
+        <el-button @click="cancel">取消</el-button>
+        <el-button v-if="title !== '查看'" type="primary" @click="getSubmit">确定</el-button>
       </div>
     </el-dialog>
 
     <!-- 历史记录 -->
     <el-dialog :visible.sync="dialogVisible_list" title="历史记录" width="1000px">
       <el-form inline size="mini">
-        <el-form-item label="">
-          <el-date-picker type="datetimerange" start-placeholder="开始日期" end-placeholder="结束日期"
-            value-format="yyyy-MM-dd HH:mm:ss" />
+        <el-form-item label="创建时间:">
+          <el-date-picker v-model="dialogForm_list.rsDates" type="datetimerange" start-placeholder="开始日期"
+            end-placeholder="结束日期" value-format="yyyy-MM-dd HH:mm:ss" />
         </el-form-item>
         <el-form-item label="模块名称:">
-          <el-input placeholder="请输入模块名称" />
+          <el-input v-model="dialogForm_list.moduleName" placeholder="请输入模块名称" />
         </el-form-item>
         <el-form-item>
           <el-button type="primary" icon="el-icon-search">搜索</el-button>
           <el-button icon="el-icon-refresh">重置</el-button>
         </el-form-item>
       </el-form>
-      <el-table>
-        <el-table-column label="模块名称" align="center" />
-        <el-table-column label="模块类型" align="center" />
-        <el-table-column label="模块数量" align="center" />
-        <el-table-column label="有效时间" align="center" />
-        <el-table-column label="当前状态" align="center" />
-        <el-table-column label="创建时间" align="center" />
+      <el-table :data="dialogTableData" v-loading="loading">
+        <el-table-column label="模块名称" prop="moduleName" align="center" />
+        <el-table-column label="模块类型" prop="moduleTypeId" align="center" />
+        <el-table-column label="模块数量" prop="moduleNum" align="center" />
+        <el-table-column label="有效时间" align="center">
+          <template slot-scope="scope">
+            <span>{{ scope.row.rsDates[0] }} - {{ scope.row.rsDates[1] }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column label="当前状态" prop="status" align="center" :formatter="statusFormatter" />
+        <el-table-column label="创建时间" prop="createTime" align="center" />
         <el-table-column label="操作" align="center">
           <template>
             <el-button type="text">查看</el-button>
@@ -83,141 +107,194 @@
 </template>
 
 <script>
+import { tabList, typeList, list, submit, listDetail, remove, history, timeChange } from '@/api/operation/recommend'
+import { currentMixin } from '@/mixin/index'
 export default {
+  mixins: [currentMixin],
   data() {
     return {
-      tableData: [{
-        id: 1,
-        tabName: '推荐',
-        type: 1,
-        children: [{
-          id: 1.1,
-          tabName: '推荐',
-          mouldName: '场景电台',
-          number: 1,
-          type: 2,
-          sort: 1,
-          children: [{
-            id: '1.1.1',
-            tabName: '推荐',
-            mouldName: '场景电台',
-            createTime: '2023-04-09 00:00:00',
-            time: '2023-04-10 00:00:00 至 2023-04-20 00:00:00',
-            number: 4,
-            type: 3,
-            status: '生效中'
-          }, {
-            id: '1.1.2',
-            tabName: '推荐',
-            mouldName: '场景电台',
-            createTime: '2023-04-09 00:00:00',
-            time: '2023-04-21 00:00:00 至 2023-04-29 00:00:00',
-            number: 4,
-            type: 3,
-            status: '未生效'
-          }]
-        }]
-      }, {
-        id: 2,
-        tabName: '电台',
-        type: 1,
-        children: [{
-          id: 2.1,
-          tabName: '电台',
-          mouldName: '四宫格',
-          number: 1,
-          type: 2,
-          sort: 1,
-          children: [{
-            id: '2.1.1',
-            tabName: '电台',
-            mouldName: '四宫格',
-            createTime: '2023-04-09 00:00:00',
-            time: '2023-04-10 00:00:00 至 2023-04-20 00:00:00',
-            number: 4,
-            type: 3,
-            status: '生效中'
-          }, {
-            id: '2.1.2',
-            tabName: '电台',
-            mouldName: '四宫格',
-            createTime: '2023-04-09 00:00:00',
-            time: '2023-04-21 00:00:00 至 2023-04-29 00:00:00',
-            number: 4,
-            type: 3,
-            status: '未生效'
-          }]
-        }]
-      }],
+      // 遮罩层
+      loading: false,
+      // 列表
+      tableData: [],
       // 弹窗
       dialogVisible: false,
       dialogVisible_list: false,
       // 弹窗表单
       dialogForm: {},
-      dialogForm_list: {},
+      dialogForm_list: {
+        pageNum: 1,
+        pageSize: 10
+      },
+      // 弹窗title
+      title: '新增',
+      // 弹窗列表
+      dialogTableData: [],
       // 导航栏
-      tabOptions: [{
-        value: 1,
-        label: '推荐'
-      }, {
-        value: 2,
-        label: '电台'
-      }, {
-        value: 3,
-        label: 'QQ音乐'
-      }, {
-        value: 4,
-        label: '酷狗音乐'
-      }],
+      tabOptions: [],
       // 模板类型
-      typeOptions: [{
-        value: 1,
-        label: '轮播图'
-      }, {
-        value: 2,
-        label: '轮播图(排序)'
-      }, {
-        value: 3,
-        label: '场景模式'
-      }, {
-        value: 4,
-        label: '个性推荐'
-      }, {
-        value: 5,
-        label: '个性推荐(排序)'
-      }, {
-        value: 6,
-        label: '歌单'
-      }, {
-        value: 7,
-        label: '歌单(标题)'
-      }, {
-        value: 8,
-        label: '歌单(排序)'
-      }, {
-        value: 9,
-        label: '音乐随心听'
-      }, {
-        value: 10,
-        label: '精选音乐电台'
-      }]
+      typeOptions: [],
+      // 校验
+      rules: {
+        categoryId: [{
+          required: true, message: '请选择导航', tigger: 'change'
+        }],
+        moduleName: [{
+          required: true, message: '请输入模块名称', trigger: 'blur'
+        }],
+        moduleTypeId: [{
+          required: true, message: '请选择模块类型', tigger: 'change'
+        }],
+        sort: [{
+          required: true, type: 'number', message: '请选择排序', tirgger: 'blur, change'
+        }]
+      }
     }
   },
   mounted() {
-
+    this.getTabList()
+    this.getTypeList()
   },
   methods: {
+    // 导航列表
+    getTabList() {
+      tabList().then(res => {
+        if (res.code === 0) {
+          res.data.map(i => {
+            i.hidden = true
+            i.children = []
+          })
+          this.tabOptions = res.data
+          this.tableData = res.data
+        }
+      })
+    },
+
+    // 模板列表
+    getTypeList() {
+      typeList().then(res => {
+        if (res.code === 0) {
+          this.typeOptions = res.data
+        }
+      })
+    },
+
+    // 首次获取二级列表
+    getList(row, index) {
+      let e = this.tableData[index]
+      list(row.id).then(res => {
+        if (res.code === 0) {
+          if (res.data.length > 0) {
+            e.children = res.data
+            e.hidden = false
+            this.$nextTick(() => {
+              this.$refs.tableData.toggleRowExpansion(row, true)
+            })
+          } else {
+            this.$message.warning('暂无模板!')
+          }
+        }
+      })
+    },
+
+    // 提交二级
+    getSubmit() {
+      this.$refs.dialogForm.validate((valid) => {
+        if (valid) {
+          submit(this.dialogForm).then(res => {
+            if (res.code === 0) {
+              this.$message.success('提交成功')
+              this.cancel()
+              this.getTabList()
+            }
+          })
+        } else {
+          return false
+        }
+      })
+    },
+
+    // 取消
+    cancel() {
+      this.dialogVisible = false
+    },
+
     // 新增模板
-    getDetail() {
+    getDetail(row, boolean) {
       this.$router.push({
-        path: `/operation/recommend/detail`
+        path: `/operation/recommend/detail`,
+        query: row.lv === 2 ? {
+          secondId: row.id,
+          moduleTypeId: row.moduleTypeId,
+          boolean: boolean
+        } : {
+          threeId: row.id,
+          moduleTypeId: row.moduleTypeId,
+          boolean: boolean
+        }
       })
     },
 
+    // 查看 编辑
+    getOpen(row, title, boolean) {
+      this.title = title
+      if (row.lv === 2) {
+        this.dialogVisible = true
+        listDetail(row.id).then(res => {
+          if (res.code === 0) {
+            this.dialogForm = res.data
+          }
+        })
+      } else {
+        this.getDetail(row, boolean)
+      }
+    },
+
+    // 删除
+    getDelete(row) {
+      this.$confirm(`是否删除${row.moduleName}?`, '提醒', {
+        type: 'warning'
+      }).then(() => {
+        remove(row.lv, row.id).then(res => {
+          if (res.code === 0) {
+            this.$message.success('删除成功!')
+            this.getTabList()
+          }
+        })
+      }).catch(() => { })
+    },
+
     // 历史记录
-    getDialog() {
+    getDialog(id) {
       this.dialogVisible_list = true
-    }
+      this.loading = true
+      this.dialogForm_list.categoryId = id
+      history(this.dialogForm_list).then(res => {
+        if (res.code === 0) {
+          this.dialogTableData = res.data.records
+          this.total = res.data.total
+          this.loading = false
+        }
+      })
+    },
+
+    // 有效时间
+    getChange(row) {
+      timeChange({
+        moduleId: row.id,
+        timeList: row.rsDates
+      }).then(res => {
+        if (res.code === 0) {
+          this.$message.success('修改成功!')
+          this.getTabList()
+        }
+      })
+    },
+
+    // 字典翻译
+    statusFormatter(row) {
+      return this.selectDictLabel(this.currentOptions, row.status)
+    },
   }
 }
 </script>