DESKTOP-SVI9JE1\muzen 1 gadu atpakaļ
vecāks
revīzija
6999df8944

+ 2 - 0
src/api/content/insert.js

@@ -0,0 +1,2 @@
+import request from '@/utils/request'
+

+ 9 - 0
src/api/content/setting.js

@@ -43,4 +43,13 @@ export function detail(query){
     method: 'get',
     params: query
   })
+}
+
+// 内容设定列表
+export function settingList(data) {
+  return request({
+    url: `/radio/tContentPlay/Intercut/queryList`,
+    method: 'post',
+    data
+  })
 }

+ 2 - 0
src/directive/index.js

@@ -2,10 +2,12 @@ import hasRole from './permission/hasRole'
 import hasPermi from './permission/hasPermi'
 import copyText from './common/copyText'
 import loadMore from './common/loadMore'
+import hasUser from './permission/hasUser'
 
 export default function directive(app){
   app.directive('hasRole', hasRole)
   app.directive('hasPermi', hasPermi)
   app.directive('copyText', copyText)
   app.directive('loadMore', loadMore)
+  app.directive('hasUser', hasUser)
 }

+ 15 - 0
src/directive/permission/hasUser.js

@@ -0,0 +1,15 @@
+import useUserStore from '@/store/modules/user'
+
+export default {
+  mounted(el, binding) {
+    const { value } = binding
+    const userId = useUserStore().userId
+    if(value){
+      if(value !== userId) {
+        el.parentNode && el.parentNode.removeChild(el)
+      }
+    }else{
+      throw new Error(`请设置角色权限Id`)
+    }
+  }
+}

+ 27 - 1
src/hooks/index.js

@@ -217,7 +217,7 @@ export function useAreaSelect() {
 }
 
 // 音频聚合列表
-import { audioList } from "../api/content/setting";
+import { audioList, settingList } from "../api/content/setting";
 
 export function useAudioList() {
   const audioData = reactive({
@@ -244,3 +244,29 @@ export function useAudioList() {
 
   return { audioData, getAudio };
 }
+
+// 内容设定列表
+export function useSettingList() {
+  const settingData = reactive({
+    form: {
+      pageNum: 1,
+      pageSize: 10,
+    },
+    tableData: [],
+    loading: false,
+    total: 0,
+  });
+
+  const getSetting = () => {
+    settingData.loading = true;
+    settingList(settingData.form).then((res) => {
+      if (res.code === 0) {
+        settingData.tableData = res.data.records;
+        settingData.total = res.data.total;
+        settingData.loading = false;
+      }
+    });
+  };
+
+  return { settingData, getSetting };
+}

+ 17 - 2
src/router/index.js

@@ -48,7 +48,7 @@ export const constantRoutes = [
     hidden: true,
   },
   {
-    path: "/:pathMatch(.*)*", 
+    path: "/:pathMatch(.*)*",
     component: () => import("@/views/error/404"),
     hidden: true,
   },
@@ -60,7 +60,7 @@ export const constantRoutes = [
   {
     path: "/wifi",
     component: () => import("@/views/wifi"),
-    hidden: true
+    hidden: true,
   },
   {
     path: "",
@@ -193,6 +193,21 @@ export const dynamicRoutes = [
       },
     ],
   },
+  // 内容插播
+  {
+    path: "/content",
+    component: Layout,
+    hidden: true,
+    permissions: ["content:insert:list"],
+    children: [
+      {
+        path: "insert/detail",
+        component: () => import("@/views/content/insert/detail"),
+        name: "insertDetail",
+        meta: { title: "插播详情", activeMenu: "/content/insert" },
+      },
+    ],
+  },
 ];
 
 const router = createRouter({

+ 3 - 1
src/store/modules/user.js

@@ -10,6 +10,7 @@ const useUserStore = defineStore(
       id: '',
       name: '',
       avatar: '',
+      userId: '',
       roles: [],
       permissions: []
     }),
@@ -36,7 +37,7 @@ const useUserStore = defineStore(
           getInfo().then(res => {
             const user = res.user
             const avatar = (user.avatar == "" || user.avatar == null) ? defAva : user.avatar;
-
+            const userId = user.userId
             if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
               this.roles = res.roles
               this.permissions = res.permissions
@@ -46,6 +47,7 @@ const useUserStore = defineStore(
             this.id = user.userId
             this.name = user.userName
             this.avatar = avatar
+            this.userId = userId
             resolve(res)
           }).catch(error => {
             reject(error)

+ 2 - 2
src/views/content/class/index.vue

@@ -12,8 +12,8 @@
       <el-table-column label="创建时间" prop="createTime" align="center"></el-table-column>
       <el-table-column label="操作" align="center">
         <template #default="scope">
-          <el-button type="primary" link @click="getDialog(scope.row.id)">编辑</el-button>
-          <el-button type="danger" link @click="getDelete(scope.row)">删除</el-button>
+          <el-button type="primary" link @click="getDialog(scope.row.id)" v-hasUser="scope.row.userId">编辑</el-button>
+          <el-button type="danger" link @click="getDelete(scope.row)" v-hasUser="scope.row.userId">删除</el-button>
         </template>
       </el-table-column>
     </el-table>

+ 475 - 0
src/views/content/insert/detail.vue

@@ -0,0 +1,475 @@
+<template>
+  <div class='app-container'>
+    <el-form class="form" label-width="auto" ref="form" :model="data.form" :rules="data.rules">
+      <el-form-item class="chooseAudio" label="内容音频:" prop="audioList">
+        <div class="audioList" v-for="(item, index) in data.form.audioList" :key="item.id">
+          <el-tag v-show="item.type === 0 || item.type === 1" size="large" :closable="checkClose()"
+            @close="handleClose(index)">
+            {{ item.audioName }}
+          </el-tag>
+          <div v-show="item.type === 2" class="audio">
+            <img src="@/assets/icons/svg/file.svg" width="70" height="70" />
+            <span>{{ item.audioName }}</span>
+          </div>
+        </div>
+        <el-button v-if="checkClose()" icon="Plus" @click="getDialog">选择音频</el-button>
+      </el-form-item>
+      <el-form-item label="内容设定:" prop="name">
+        <el-button icon="Plus" @click="getContentDialog">选择内容</el-button>
+      </el-form-item>
+      <el-form-item label="播放时间:" prop="listDate">
+        <div class="date" v-for="(item, index) in data.dateList">
+          <el-date-picker v-model="data.dateList[index]" type="datetimerange" start-placeholder="开始时间"
+            end-placeholder="结束时间" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"
+            @change="handleChangeDate($event, index)" />
+          <el-link v-show="data.dateList.length > 1" icon="CircleClose" :underline="false"
+            @click="handleDeleteDate(index)" />
+          <el-link v-show="data.dateList.length - 1 === index" icon="CirclePlus" :underline="false"
+            @click="handlePushDate" />
+        </div>
+      </el-form-item>
+    </el-form>
+    <div class="form-btn">
+      <el-button @click="getClose">取消</el-button>
+      <el-button type="primary" @click="getSubmit">确定</el-button>
+    </div>
+
+    <el-dialog v-model="dialogVisible_audio" title="选择音频" width="1000px">
+      <el-form inline>
+        <el-form-item label="内容分类:">
+          <el-select v-model="audioData.form.type" placeholder="请选择内容分类">
+            <el-option v-for="item in data.radioOptions" :key="item.value" :value="item.value" :label="item.label" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="名称:">
+          <el-input v-model="audioData.form.name" placeholder="请输入名称" />
+        </el-form-item>
+        <el-form-item label="分类:">
+          <el-select v-model="audioData.form.sceneId" placeholder="请选择分类">
+            <el-option v-for="item in audioClassData.options" :key="item.id" :value="item.id" :label="item.name" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="当前状态:">
+          <el-select v-model="audioData.form.status" placeholder="请选择当前状态">
+            <el-option v-for="item in sys_change_status" :key="item.value" :value="item.value" :label="item.label" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" icon="Search" @click="getSearch">搜索</el-button>
+          <el-button icon="Refresh" @click="getRefresh">重置</el-button>
+        </el-form-item>
+      </el-form>
+      <el-table v-if="audioData.form.type !== 2" ref="table" :data="audioData.tableData" :row-key="rowKey"
+        @selection-change="handleSelectionChange" v-loading="audioData.loading">
+        <el-table-column type="selection" width="55" />
+        <el-table-column label="ID" prop="id" align="center" show-overflow-tooltip />
+        <el-table-column label="名称" prop="name" align="center" show-overflow-tooltip />
+        <el-table-column label="时长" prop="playTime" align="center">
+          <template #default="scope">
+            {{ playTime(scope.row.playTime) }}
+          </template>
+        </el-table-column>
+        <el-table-column label="分类" prop="sceneId" align="center" :formatter="sceneFormatter" />
+        <el-table-column label="当前状态" prop="status" align="center" :formatter="statusFormatter" />
+        <el-table-column label="更新时间" prop="updateTime" align="center" show-overflow-tooltip />
+      </el-table>
+      <div class="audio_table" v-else>
+        <div class="audio" v-for="item in audioData.tableData" :key="item.id" @click="handleChooseAudio(item)">
+          <img src="@/assets/icons/svg/file.svg" width="70" height="70" />
+          <span>{{ item.name }}</span>
+        </div>
+      </div>
+      <pagination v-show="audioData.total > 0" :total="audioData.total" v-model:page="audioData.form.pageNum"
+        v-model:limit="audioData.form.pageSize" @pagination="getAudio" />
+      <template #footer>
+        <el-button type="primary" @click="getPush">确定</el-button>
+      </template>
+    </el-dialog>
+
+    <el-dialog v-model="dialogVisible_content" title="选择内容" width="1000px">
+      <el-form inline>
+        <el-form-item label="内容名称:">
+          <el-input v-model="settingData.form.name" placeholder="请输入内容名称" clearable />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="getSearch">搜索</el-button>
+        </el-form-item>
+      </el-form>
+      <el-table>
+        <el-table-column label="内容ID" align="center"></el-table-column>
+        <el-table-column label="内容名称" align="center"></el-table-column>
+        <el-table-column label="当前状态" align="center"></el-table-column>
+        <el-table-column label="播放时段" align="center"></el-table-column>
+        <el-table-column label="操作" align="center">
+          <template #default="scope">
+            <el-button type="primary" link>选择</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { useAudioList, useAudioClass, useSettingList } from '@/hooks/index'
+
+const { proxy } = getCurrentInstance();
+
+const { audioData, getAudio } = useAudioList()
+const { audioClassData, getAudioClass } = useAudioClass()
+getAudioClass()
+const { settingData, getSetting } = useSettingList()
+
+const { sys_change_status } = proxy.useDict("sys_change_status")
+
+const data = reactive({
+  // 表单
+  form: {
+    audioList: [],
+    listDate: []
+  },
+  // 时间段
+  dateList: [[]],
+  // 分页
+  radioOptions: [{
+    value: 0,
+    label: '内容列表'
+  }, {
+    value: 1,
+    label: 'Ohplay音频'
+  }, {
+    value: 2,
+    label: '场景预设'
+  }],
+  // 多选
+  selectionList: [],
+  // 校验
+  rules: {
+    audioList: [{
+      required: true, message: '请选择音频', trigger: 'change'
+    }],
+    listDate: [{
+      required: true, message: '请选择播放时间', trigger: 'change'
+    }]
+  },
+  business_store: []
+})
+
+const getPushTime = (e) => {
+  if (e.startTime) {
+    let y = new Date().getFullYear()
+    let m = new Date().getMonth() + 1
+    let d = new Date().getDate()
+    let startTime = proxy.parseTime(new Date(`${y}-${m}-${d} ${e.startTime}`).getTime(), '{y}-{m}-{d} {h}:{i}:{s}')
+    let endTime = proxy.parseTime(new Date(`${y}-${m}-${d} ${e.endTime}`).getTime(), '{y}-{m}-{d} {h}:{i}:{s}')
+    data.dateList[0] = [startTime, endTime]
+    data.form.listDate.push({
+      startTime: startTime,
+      endTime: endTime
+    })
+  }
+}
+
+// 传参
+const getAudioList = () => {
+  if (proxy.$route.query.audioList) {
+    var e = JSON.parse(proxy.$route.query.audioList)
+    data.form.audioList.push({
+      audioId: e.id,
+      audioName: e.name,
+      audioType: e.audioType,
+      categoryId: e.sceneId,
+      type: e.type,
+    })
+    getPushTime(e)
+  }
+}
+getAudioList()
+
+// 详情
+const getDetail = () => {
+  let e = proxy.$route.query
+  if (e.id) {
+    detail({ id: e.id, storeId: e.storeId }).then(res => {
+      if (res.code === 0) {
+        data.form = res.data
+        data.dateList = []
+        res.data.listDate.map(i => {
+          data.dateList.push([i.startTime, i.endTime])
+        })
+      }
+    })
+  }
+}
+getDetail()
+
+// 检测是否是编辑
+const checkClose = () => {
+  return proxy.$route.query.disabled == undefined ? true : false
+}
+
+// 弹窗
+const dialogVisible_audio = ref(false)
+// 打开弹窗
+function getDialog() {
+  dialogVisible_audio.value = true
+  getAudio()
+  // 监听
+  watch(() => audioData.tableData, (val) => {
+    if (audioData.form.type !== 2) {
+      nextTick(() => {
+        proxy.$refs.table.clearSelection()
+        if (val && data.form.audioList.length > 0) {
+          data.form.audioList.map(i => {
+            let row = val.find(j => j.id === i.audioId)
+            if (row) {
+              proxy.$refs.table.toggleRowSelection(row, true)
+            }
+          })
+        }
+      })
+    }
+  })
+}
+
+const dialogVisible_content = ref(false)
+const getContentDialog = () => {
+  dialogVisible_content.value = true
+  getSetting()
+}
+
+// 搜索
+const getSearch = () => {
+  audioData.form.pageNum = 1
+  getAudio()
+}
+
+// 重置
+const getRefresh = () => {
+  audioData.form = {
+    pageNum: 1,
+    pageSize: 10,
+    type: 0
+  }
+  getAudio()
+}
+
+// 返回id
+const rowKey = (e) => {
+  return e.id
+}
+
+// 多选
+const handleSelectionChange = (e) => {
+  data.selectionList = []
+  e.map(i => {
+    if (data.selectionList.findIndex(j => j.id === i.id) === -1) {
+      data.selectionList.push({
+        audioId: i.id,
+        audioName: i.name,
+        audioType: i.audioType,
+        categoryId: i.sceneId,
+        type: i.type
+      })
+    }
+  })
+}
+
+// 单选
+const handleChooseAudio = (e) => {
+  data.form.audioList = []
+  data.form.audioList.push({
+    audioId: e.id,
+    audioName: e.name,
+    audioType: e.audioType,
+    categoryId: e.sceneId,
+    type: e.type
+  })
+  getPushTime(e)
+  proxy.$modal.msgSuccess('选择成功!')
+  dialogVisible_audio.value = false
+}
+
+// 确定
+const getPush = () => {
+  data.form.audioList = []
+  data.form.audioList = JSON.parse(JSON.stringify(data.selectionList))
+  proxy.$modal.msgSuccess('选择成功!')
+  dialogVisible_audio.value = false
+}
+
+// 删除音频
+const handleClose = (index) => {
+  data.form.audioList.splice(index, 1)
+}
+
+// 删除所属门店
+const getDelete = (index) => {
+  data.form.tpresetContentInfoReq.splice(index, 1)
+}
+
+// 增加时间
+function handlePushDate() {
+  let boolean = false
+  data.dateList.map(i => boolean = i.length === 0 ? true : false)
+  if (boolean) {
+    proxy.$modal.msgError('有时间段未填')
+  } else {
+    data.dateList.push([])
+  }
+}
+
+// 删除时间
+function handleDeleteDate(index) {
+  data.dateList.splice(index, 1)
+}
+
+// 校验时间
+const handleChangeDate = (e, index) => {
+  if (e !== null) {
+    data.listDate = []
+    data.form.listDate = []
+    const start = new Date(e[0]).getTime()
+    const end = new Date(e[1]).getTime()
+
+    for (let i = 0; i < data.dateList.length; i++) {
+      if (i !== index) {
+        let st = new Date(data.dateList[i][0]).getTime()
+        let en = new Date(data.dateList[i][1]).getTime()
+
+        if (start >= st && start <= en || end >= st && end <= en || start <= st && end >= en || end <= st && start >= en) {
+          data.dateList.splice(index, 1)
+          proxy.$modal.msgError("该时间段已设置!")
+          return false
+        }
+      }
+      data.form.listDate.push({
+        startTime: data.dateList[i][0],
+        endTime: data.dateList[i][1]
+      })
+    }
+  }
+}
+
+// 所属企业
+const index = ref(0)
+const handleChangeTenant = (e, i) => {
+  storeData.form.tenantId = e
+  index.value = i
+  getStore()
+}
+
+// 取消
+const getClose = () => {
+  proxy.$tab.closeOpenPage('/content/setting')
+}
+
+// 提交
+const getSubmit = () => {
+  proxy.$refs.form.validate(valid => {
+    if (valid) {
+      submit(data.form).then(res => {
+        if (res.code === 0) {
+          proxy.$modal.msgSuccess('提交成功!')
+          getClose()
+        }
+      })
+    } else {
+      return false
+    }
+  })
+}
+
+// 字典
+const statusFormatter = (row) => {
+  return proxy.selectDictLabel(sys_change_status.value, row.status)
+}
+
+const sceneFormatter = (row) => {
+  let e = audioClassData.options.find(i => i.id === row.sceneId)
+  if (row.sceneId && e) {
+    return audioClassData.options.find(i => i.id === row.sceneId).name
+  }
+}
+
+// 监听
+watch(() => audioData.form.type, (val) => {
+  data.selectionList = []
+  getAudio()
+})
+</script>
+
+<style lang="scss" scoped>
+.form {
+  .el-form-item {
+    width: 500px;
+  }
+
+  .el-table__row {
+    .el-form-item {
+      width: 100%;
+    }
+  }
+}
+
+.chooseAudio {
+  :deep(.el-form-item__content) {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-start;
+
+    .audioList {
+      display: flex;
+      flex-direction: column;
+      align-items: flex-start;
+
+      .el-tag {
+        margin-bottom: 15px;
+      }
+    }
+  }
+}
+
+.audio_table {
+  display: flex;
+  flex-wrap: wrap;
+
+  .audio {
+    margin: 10px;
+  }
+}
+
+.audio {
+  width: 200px;
+  height: 200px;
+  border: 1px solid #e9e9eb;
+  border-radius: 8px;
+  margin-bottom: 15px;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  box-shadow: 0 0 6px 0 #e9e9eb;
+
+  span {
+    width: 160px;
+    height: 40px;
+    line-height: 40px;
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    text-align: center;
+  }
+}
+
+.date {
+  display: flex;
+  align-items: center;
+  margin-bottom: 15px;
+
+  .el-link {
+    margin-left: 10px;
+    font-size: 16px;
+  }
+}
+</style>

+ 232 - 0
src/views/content/insert/index.vue

@@ -0,0 +1,232 @@
+<template>
+  <div class='app-container'>
+    <div class="left">
+      <el-calendar ref="calendar" v-model="nowDate">
+        <template #header="{ date }">
+          <span>{{ date }}</span>
+          <el-button link icon="ArrowLeftBold" @click="selectDate('prev-month')" />
+          <el-button link icon="ArrowRightBold" @click="selectDate('next-month')" />
+        </template>
+      </el-calendar>
+      <div class="list">
+        <el-input v-model="audioData.form.name" placeholder="搜索" clearable>
+          <template #append>
+            <el-button icon="Search" @click="getSearch" />
+          </template>
+        </el-input>
+        <el-tabs v-model="activeName" @tab-click="handleChangeTabs">
+          <el-tab-pane v-for="item in data.tabOptions" :key="item.value" :name="item.value" :label="item.label"
+            v-loading="audioData.loading">
+            <el-empty v-if="audioData.tableData.length === 0" description="暂无数据" />
+            <el-scrollbar v-else :height="260">
+              <draggable class="contentList" :style="[activeName !== 2 ? 'flex-direction: column' : 'flex-wrap: wrap;']"
+                v-model="audioData.tableData" item-key="id" chosen-class="chosenClass" data-id="content"
+                :group="{ name: 'componentGroup', pull: 'clone', put: false }" :sort="false" @end="onEnd">
+                <template #item="{ element, index }">
+                  <div class="item">
+                    <span v-show="activeName !== 2" class="item_line" :title="element.name">
+                      <el-icon style="margin-right: 10px; line-height:40px">
+                        <VideoPlay />
+                      </el-icon>
+                      {{ element.name }}
+                    </span>
+                    <span v-show="activeName === 2" class="item_box">
+                      <img src="@/assets/icons/svg/file.svg" width="50" height="50" />
+                      <span class="takeName">{{ element.name }}</span>
+                    </span>
+                  </div>
+                </template>
+              </draggable>
+            </el-scrollbar>
+            <el-pagination v-show="audioData.total > 0" layout="prev,pager,next" :total="audioData.total"
+              @current-change="handleChangeCurrent" />
+          </el-tab-pane>
+        </el-tabs>
+      </div>
+    </div>
+    <div class="right">
+      <gantt-chart path="/content/insert/detail" type="setting" :date="nowDate" />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { useAudioList } from '@/hooks/index'
+import GanttChart from '@/components/GanttChart'
+
+const { proxy } = getCurrentInstance();
+
+const { audioData, getAudio } = useAudioList()
+getAudio()
+
+// 遮罩层
+const loading = ref(false)
+// tab页
+const activeName = ref(0)
+// 日历
+const nowDate = ref(new Date())
+// 数据
+const data = reactive({
+  // tab数组
+  tabOptions: [{
+    value: 0,
+    label: '内容列表'
+  }, {
+    value: 1,
+    label: 'ohplay音频'
+  }, {
+    value: 2,
+    label: '场景预设'
+  }],
+  // 表单
+  form: {
+    pageNum: 1,
+    pageSize: 10
+  }
+})
+
+// 日历
+const calendar = ref()
+function selectDate(val) {
+  if (!calendar.value) return
+  calendar.value.selectDate(val)
+}
+
+function getDate(e) {
+  nowDate.value = e
+}
+
+// 切换tab
+const handleChangeTabs = (e) => {
+  audioData.tableData = []
+  audioData.form = {
+    pageNum: 1,
+    pageSize: 10,
+    type: e.props.name
+  }
+  getAudio()
+}
+
+// 翻页
+const handleChangeCurrent = (e) => {
+  audioData.form.pageNum = e
+  getAudio()
+}
+
+// 搜索
+const getSearch = () => {
+  audioData.form.pageNum = 1
+  getAudio()
+}
+
+// 拖拽结束
+function onEnd(params) {
+  if (params.from.className !== params.to.className) {
+    proxy.$modal.confirm(`是否要添加?`).then(() => {
+      getRouter({ audioList: JSON.stringify(params.item.__draggable_context.element) })
+    }).catch(() => {
+      params.to.firstChild.remove()
+    })
+  }
+}
+
+// 新增
+function getRouter(query) {
+  proxy.$router.push({
+    path: `/content/setting/detail`,
+    query
+  })
+}
+
+// 拖动样式
+const chosenClass = () => {
+  return '  background: none !important;color: #3979F9 !important; line-height: 60px;'
+}
+
+</script>
+
+<style lang="scss" scoped>
+.app-container {
+  display: flex;
+}
+
+.left {
+  width: 400px;
+  background-color: #f4f4f5;
+  display: flex;
+  flex-direction: column;
+
+  :deep(.el-calendar-day) {
+    height: 42px;
+  }
+
+  :deep(.el-tabs__nav) {
+    justify-content: space-around;
+    float: none;
+  }
+
+  .list {
+    padding: 20px;
+
+    .contentList {
+      display: flex;
+
+      .item {
+        display: flex;
+
+        .item_line {
+          width: 100%;
+          padding: 8px 10px;
+          background-color: #FFF;
+          margin-bottom: 10px;
+          border-radius: 5px;
+          color: #3979F9;
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+        }
+
+        .item_box {
+          display: flex;
+          flex-direction: column;
+          justify-content: center;
+          align-items: center;
+          padding: 0px 10px;
+          font-size: 14px;
+          margin-bottom: 20px;
+        }
+      }
+    }
+  }
+}
+
+.noScene {
+  flex-direction: column;
+}
+
+.scene {
+  flex-wrap: wrap;
+}
+
+.right {
+  display: flex;
+  flex-direction: column;
+  min-width: 700px;
+  width: calc(100% - 400px);
+  height: 792px;
+}
+
+draggable,
+.label {
+  user-select: none;
+}
+
+.chosenClass {
+  display: none;
+  background: none !important;
+}
+
+.el-scrollbar {
+  margin-bottom: 20px;
+}
+</style>

+ 8 - 4
src/views/content/list/index.vue

@@ -28,7 +28,11 @@
     <el-table :data="data.tableData" v-loading="loading">
       <el-table-column label="音频ID" prop="id" align="center" />
       <el-table-column label="音频名称" prop="name" align="center" />
-      <el-table-column label="时长" prop="playTime" align="center" />
+      <el-table-column label="时长" align="center">
+        <template #default="scope">
+          {{ playTime(scope.row.playTime) }}
+        </template>
+      </el-table-column>
       <el-table-column label="音频分类" prop="sceneId" align="center" :formatter="sceneFormatter" />
       <el-table-column label="当前状态" prop="status" align="center">
         <template #default="scope">
@@ -37,7 +41,6 @@
       </el-table-column>
       <el-table-column label="更新时间" prop="updateTime" align="center" />
       <el-table-column label="操作" align="center">
-
         <template #default="scope">
           <el-button type="primary" link @click="getDialog(scope.row.id, '编辑')">编辑</el-button>
           <el-button v-if="scope.row.status === 1" type="primary" link
@@ -62,10 +65,11 @@
         <el-form-item label="音频分类:" prop="sceneId">
           <el-select v-model="data.dialogForm.sceneId" placeholder="请选择音频分类" clearable>
             <el-option v-for="item in audioClassData.options" :key="item.id" :value="item.id" :label="item.name" />
+            <el-option label="无" :value="data.dialogForm.sceneId"
+              v-if="data.dialogForm.sceneId && !audioClassData.options.some(i => i.id === data.dialogForm.sceneId)" />
           </el-select>
         </el-form-item>
       </el-form>
-
       <template #footer>
         <el-button @click="getClose">取消</el-button>
         <el-button type="primary" @click="getSubmit">确定</el-button>
@@ -238,6 +242,6 @@ function getDelete(row) {
 // 字典
 function sceneFormatter(row) {
   let e = audioClassData.options.find(i => i.id === row.sceneId)
-  return e ? e.name : row.sceneId
+  return e ? e.name : '无'
 }
 </script>

+ 0 - 8
src/views/content/scene/detail.vue

@@ -306,14 +306,6 @@ const getClose = () => {
   }
 }
 
-.list {
-  :deep(.el-form-item__content) {
-    display: flex;
-    flex-direction: column;
-    align-items: flex-start;
-  }
-}
-
 .file {
   width: 200px;
   height: 200px;

+ 4 - 9
src/views/content/setting/detail.vue

@@ -475,19 +475,14 @@ watch(() => audioData.form.type, (val) => {
 }
 
 .chooseAudio {
-  :deep(.el-form-item__content) {
+  .audioList {
     display: flex;
     flex-direction: column;
     align-items: flex-start;
+    margin-right: 10px;
 
-    .audioList {
-      display: flex;
-      flex-direction: column;
-      align-items: flex-start;
-
-      .el-tag {
-        margin-bottom: 15px;
-      }
+    .el-tag {
+      margin-bottom: 15px;
     }
   }
 }

+ 4 - 7
src/views/store/group/index.vue

@@ -7,11 +7,11 @@
     </el-form>
     <el-table :data="data.tableData" v-loading="loading">
       <el-table-column label="分组名称" prop="name" align="center"></el-table-column>
-      <el-table-column label="相关设备" prop="deviceNum" align="center"></el-table-column>
+      <el-table-column label="相关设备数量" prop="deviceNum" align="center"></el-table-column>
       <el-table-column label="操作" align="center">
         <template #default="scope">
-          <el-button type="primary" link @click="getDialog(scope.row.id)">编辑</el-button>
-          <el-button type="danger" link @click="getDelete(scope.row)">删除</el-button>
+          <el-button type="primary" link @click="getDialog(scope.row.id)" v-hasUser="scope.row.userId">编辑</el-button>
+          <el-button type="danger" link @click="getDelete(scope.row)" v-hasUser="scope.row.userId">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
@@ -34,12 +34,9 @@
 
 <script setup>
 import { list, submit, detail, remove, edit } from "@/api/store/group"
+import useUserStore from "@/store/modules/user"
 let { proxy } = getCurrentInstance()
 
-const goBack = () => {
-  proxy.$tab.closeOpenPage('/device/control')
-}
-
 // 遮罩层
 const loading = ref(false)
 

+ 2 - 0
src/views/store/list/index.vue

@@ -71,6 +71,8 @@
           <el-select v-model="data.dialogForm.groupId" placeholder="请选择门店分组" filterable remote
             :remote-method="groupRemote" remote-show-suffix>
             <el-option v-for="item in groupData.options" :key="item.id" :value="item.id" :label="item.name" />
+            <el-option v-if="data.dialogForm.groupId && !groupData.options.some(i => i.id === data.dialogForm.groupId)"
+              :label="data.dialogForm.groupName ? data.dialogForm.groupName : '无'" :value="data.dialogForm.groupId" />
           </el-select>
         </el-form-item>
       </el-form>