瀏覽代碼

no message

DESKTOP-SVI9JE1\muzen 1 年之前
父節點
當前提交
bd34449536

+ 52 - 0
src/api/business/class.js

@@ -0,0 +1,52 @@
+import request from "@/utils/request";
+
+// 列表
+export function list(data) {
+  return request({
+    url: `/organization/organizationIndustry/page`,
+    method: "post",
+    data,
+  });
+}
+
+// 详情
+export function detail(id) {
+  return request({
+    url: `/organization/organizationIndustry/${id}`,
+    method: "get",
+  });
+}
+
+// 新增
+export function submit(data) {
+  return request({
+    url: `/organization/organizationIndustry`,
+    method: "post",
+    data,
+  });
+}
+
+// 修改
+export function edit(data) {
+  return request({
+    url: `/organization/organizationIndustry`,
+    method: "put",
+    data,
+  });
+}
+
+// 删除
+export function remove(id) {
+  return request({
+    url: `/organization/organizationIndustry/${id}`,
+    method: "delete",
+  });
+}
+
+// 行业搜索
+export function options() {
+  return request({
+    url: `/organization/organizationIndustry/selectList`,
+    method: "get",
+  });
+}

+ 72 - 0
src/api/business/list.js

@@ -0,0 +1,72 @@
+import request from "@/utils/request";
+
+// 列表
+export function list(data) {
+  return request({
+    url: `/organization/organization/list`,
+    method: "post",
+    data,
+  });
+}
+
+// 详情
+export function detail(id) {
+  return request({
+    url: `/organization/organization/${id}`,
+    method: "get",
+  });
+}
+
+// 删除
+export function remove(data) {
+  return request({
+    url: `/organization/organization/remove`,
+    method: 'delete',
+    data
+  })
+}
+
+// 企业筛选
+export function options(data) {
+  return request({
+    url: `/organization/organization/selectList`,
+    method: 'post',
+    data
+  })
+}
+
+// 新增
+export function submit(data) {
+  return request({
+    url: `/organization/organization`,
+    method: 'post',
+    data
+  })
+}
+
+// 编辑
+export function edit(data) {
+  return request({
+    url: `/organization/organization`,
+    method: 'put',
+    data
+  })
+}
+
+// 状态修改
+export function change(data){
+  return request({
+    url: `/organization/organization/changeStatus`,
+    method: 'put',
+    data
+  })
+}
+
+// 企业菜单树
+export function reset(data){
+  return request({
+    url: `/system/user/resetPwdSend`,
+    method: 'put',
+    data
+  })
+}

+ 36 - 0
src/api/content/class.js

@@ -0,0 +1,36 @@
+import request from '@/utils/request'
+
+// 列表
+export function list() {
+  return request({
+    url: `/radio/tScene/list`,
+    method: 'get'
+  })
+}
+
+// 详情
+export function detail(query) {
+  return request({
+    url: `/radio/tScene/queryDetailById`,
+    method: 'get',
+    params: query
+  })
+}
+
+// 提交
+export function submit(data) {
+  return request({
+    url: `/radio/tScene/saveOrUpdate`,
+    method: 'post',
+    data
+  })
+}
+
+// 删除
+export function remove(query) {
+  return request({
+    url: `/radio/tScene/deleteById`,
+    method: 'get',
+    params: query
+  })
+}

+ 37 - 0
src/api/content/list.js

@@ -0,0 +1,37 @@
+import request from '@/utils/request'
+
+// 列表
+export function list(data) {
+  return request({
+    url: `/radio/tProgram/page`,
+    method: 'post',
+    data
+  })
+}
+
+// 详情
+export function detail(query) {
+  return request({
+    url: `/radio/tProgram/queryDetailById`,
+    method: 'get',
+    params: query
+  })
+}
+
+// 提交
+export function submit(data) {
+  return request({
+    url: `/radio/tProgram/edit`,
+    method: 'post',
+    data
+  })
+}
+
+// 上下架
+export function change(query) {
+  return request({
+    url: `/radio/tProgram/hitOrSold`,
+    method: 'get',
+    params: query
+  })
+}

+ 19 - 0
src/api/content/ohplay.js

@@ -0,0 +1,19 @@
+import request from '@/utils/request'
+
+// 列表
+export function list(data) {
+  return request({
+    url: `/radio/tProgram/ohplay/program/list`,
+    method: 'post',
+    data
+  })
+}
+
+// 资源平台
+export function options(data) {
+  return request({
+    url: `/radio/tProgram/ohplay/getlistByAudioType`,
+    method: 'post',
+    data
+  })
+}

+ 36 - 0
src/api/content/scene.js

@@ -0,0 +1,36 @@
+import request from '@/utils/request'
+
+// 列表
+export function list(data) {
+  return request({
+    url: `/radio/tTakeList/takePage`,
+    method: 'post',
+    data
+  })
+}
+
+// 新增
+export function submit(data) {
+  return request({
+    url: `/radio/tTakeList/editTakeList`,
+    method: 'post',
+    data
+  })
+}
+
+// 详情
+export function detail(query) {
+  return request({
+    url: `/radio/tTakeList/queryDetailById`,
+    method: 'get',
+    params: query
+  })
+}
+
+// 删除
+export function remove(id) {
+  return request({
+    url: `/radio/tTakeList/delete/${id}`,
+    method: 'delete'
+  })
+}

File diff suppressed because it is too large
+ 1 - 0
src/assets/icons/svg/file.svg


+ 196 - 0
src/components/GanttChart/index.vue

@@ -0,0 +1,196 @@
+<template>
+  <div class="timer">
+    <div class="item" v-for="item in data.timeList" :key="item">
+      <div class="value">
+        <span>{{ parseTime(item.timer, '{h}:{i}') }}</span>
+        <span class="solid"></span>
+      </div>
+      <draggable class="label_box" v-model="item.list" group="componentGroup" :item-key="item.value" :move="onMove"
+        @end="onEnd">
+        <template #item="{ element, index }">
+          <div @mousedown.stop style="width: 100%">
+            <el-popover placement="bottom" trigger="click" width="300px" popper-class="popper"
+              :popper-style="popperStyle" :hide-after="0">
+              <div class="title">
+                <h2>双12活动内容</h2>
+                <div style="display:flex; justify-content: space-between;">
+                  <span>1月23日22:00 - 23:00</span>
+                  <div style="display:flex; align-items: center">
+                    <el-icon style="margin-right: 10px" @click="getDetail(element)">
+                      <Edit />
+                    </el-icon>
+                    <el-icon>
+                      <Delete />
+                    </el-icon>
+                  </div>
+                </div>
+              </div>
+              <div class="main">
+                <span>当前门店:瑞幸中国</span>
+                <span>当前设备:猫2</span>
+                <span>当前状态:上架</span>
+              </div>
+              <template #reference>
+                <span class="label">{{ element.label }}</span>
+              </template>
+            </el-popover>
+          </div>
+        </template>
+      </draggable>
+    </div>
+  </div>
+</template>
+
+<script setup>
+const { proxy } = getCurrentInstance();
+
+const data = reactive({
+  timeList: [
+    { value: '0', list: [{ value: 1, label: '双十一' }] },
+    { value: '1', list: [] },
+    { value: '2', list: [] },
+    { value: '3', list: [] },
+    { value: '4', list: [] },
+    { value: '5', list: [] },
+    { value: '6', list: [] },
+    { value: '7', list: [] },
+    { value: '8', list: [] },
+    { value: '9', list: [] },
+    { value: '10', list: [] },
+    { value: '11', list: [] },
+    { value: '12', list: [] },
+    { value: '13', list: [] },
+    { value: '14', list: [] },
+    { value: '15', list: [] },
+    { value: '16', list: [] },
+    { value: '17', list: [] },
+    { value: '18', list: [] },
+    { value: '19', list: [] },
+    { value: '20', list: [] },
+    { value: '21', list: [] },
+    { value: '22', list: [] },
+    { value: '23', list: [] },
+    { value: '24', list: [] }
+  ]
+})
+
+// 时间段
+function getTime() {
+  data.timeList.map(i => {
+    // i.list = []
+    i.timer = new Date(new Date(new Date().toLocaleDateString()).getTime() + i.value * 3600000).getTime()
+  })
+}
+getTime()
+
+const popperStyle = ref({
+  padding: 0,
+  borderRadius: '10px'
+})
+
+// 拖拽内容
+function onMove(params) {
+  if (params.to.childElementCount < 1) {
+    return true
+  } else {
+    return false
+  }
+}
+
+// 拖拽结束
+function onEnd(params) {
+  if (params.from.className === 'contentList' &&
+    params.to.className === 'label_box' ||
+    params.from.className === 'label_box' &&
+    params.from.__draggable_component__.itemKey !== params.to.__draggable_component__.itemKey) {
+    let query = {
+      value: params.item._underlying_vm_.value,
+      label: params.item._underlying_vm_.label
+    }
+    getDetail(query)
+  }
+}
+
+// 新增
+function getDetail(query) {
+  proxy.$router.push({
+    path: `/content/setting/detail`,
+    query
+  })
+}
+</script>
+
+<style lang="scss" scoped>
+.timer {
+  display: flex;
+  flex-direction: column;
+  width: calc(100% - 50px);
+  margin-left: 50px;
+
+  .item {
+    width: 100%;
+    height: 100px;
+    line-height: 100px;
+    position: relative;
+    border-left: 1px solid #e3e3e3;
+    display: flex;
+    align-items: center;
+
+    .value {
+      margin-left: -50px;
+
+      .solid {
+        border-top: 1px solid #e3e3e3;
+        width: 100%;
+        position: absolute;
+        top: 50px;
+        left: 0;
+      }
+    }
+
+    .label_box {
+      display: flex;
+      width: 100%;
+      z-index: 99;
+      position: absolute;
+      top: 70px;
+
+      .label {
+        background-color: #ebf1fe;
+        color: #3979F9;
+        height: 60px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        border-left: 4px solid #3979F9;
+        border-radius: 4px;
+        margin-right: 10px;
+        font-size: 12px;
+        padding: 0 20px;
+        flex: 1;
+      }
+    }
+  }
+}
+
+.popper {
+
+  .title,
+  .main {
+    line-height: 35px;
+    padding: 20px;
+  }
+
+  .title {
+    background-color: #337ecc;
+    color: #FFF;
+    border-radius: 10px 10px 0 0;
+    font-size: 16px;
+  }
+
+  .main {
+    display: flex;
+    flex-direction: column;
+  }
+}
+</style>

+ 1 - 1
src/components/Pagination/index.vue

@@ -89,7 +89,7 @@ function handleCurrentChange(val) {
 <style scoped>
 .pagination-container {
   /* background: #fff; */
-  /* padding: 32px 16px; */
+  padding: 32px 16px;
 }
 
 .pagination-container.hidden {

+ 41 - 0
src/components/Selection/index.vue

@@ -0,0 +1,41 @@
+<script>
+// 自定义指令 (Vue 3)
+export const selectScroll = {
+  beforeMount(el, binding) {
+    const handleScroll = (event) => {
+      binding.value(event); // 调用传进来的函数,传递事件对象
+    };
+    el.addEventListener('scroll', handleScroll);
+    // 提供一个方法供组件清理事件监听
+    el['cleanUpSelectScroll'] = () => {
+      el.removeEventListener('scroll', handleScroll);
+    };
+  },
+  unmounted(el) {
+    // 组件卸载时清理事件监听
+    el['cleanUpSelectScroll'] && el['cleanUpSelectScroll']();
+  },
+};
+
+
+<template>
+  <el-select v-selectScroll="handleScroll">
+    <!-- options -->
+  </el-select>
+</template>
+ 
+<script>
+import { selectScroll } from './path/to/your/directive';
+ 
+export default {
+  directives: {
+    selectScroll,
+  },
+  methods: {
+    handleScroll(event) {
+      // 处理滚动事件
+      console.log('Scroll event:', event);
+    },
+  },
+};
+</script>

+ 58 - 20
src/components/Upload/index.vue

@@ -1,11 +1,14 @@
 <template>
-  <el-upload :action="reactiveData.action[listType]" :headers="reactiveData.headers" :list-type="listType"
-    name="multipartFile" :multiple="multiple" :data="data" :show-file-list="showFileList" :before-upload="beforeUpload"
-    :on-success="onSuccess" :on-error="onError" :before-remove="beforeRemove" :on-remove="handleRemove"
-    :disabled="disabled">
-    <el-icon v-if="listType === 'picture-card'" size="28">
-      <Plus />
-    </el-icon>
+  <el-upload ref="upload" :action="url ? url : reactiveData.action[listType]" :headers="reactiveData.headers"
+    :list-type="listType" name="multipartFile" :multiple="multiple" :data="data" :show-file-list="showFileList"
+    :before-upload="beforeUpload" :on-success="onSuccess" :on-error="onError" :before-remove="beforeRemove"
+    :on-remove="handleRemove" :disabled="disabled">
+    <div class="image" v-if="listType === 'picture-card'">
+      <el-icon v-if="src === ''" size="28">
+        <Plus />
+      </el-icon>
+      <el-image v-else :src="src" />
+    </div>
     <el-button v-else :type="type" :loading="loading === 1">{{ title }}</el-button>
   </el-upload>
 </template>
@@ -13,7 +16,14 @@
 <script setup>
 import { getToken } from "@/utils/auth";
 
+const { proxy } = getCurrentInstance()
+
 const props = defineProps({
+  // 上传路径
+  url: {
+    type: String,
+    default: undefined
+  },
   // 是否支持多文件上传
   multiple: {
     type: Boolean,
@@ -38,22 +48,25 @@ const props = defineProps({
   disabled: {
     type: Boolean,
     default: false
+  },
+  // 图片
+  src: {
+    type: String,
+    default: ''
   }
 })
 
-const { proxy } = getCurrentInstance()
-
 // 上传地址
 const baseUrl = ref(import.meta.env.VITE_APP_BASE_API)
 
-// 上传文件
 const reactiveData = reactive({
-  form: [],
   action: {
     'text': `${baseUrl.value}/system/file/file/upload`,
     'picture-card': `${baseUrl.value}/system/file/picture/upload`
   },
-  headers: { Authorization: "Bearer " + getToken() }
+  headers: { Authorization: "Bearer " + getToken() },
+  // 上传文件
+  form: [],
 })
 
 // 上传状态
@@ -65,19 +78,23 @@ const title = ref('点击上传')
 function beforeUpload(file) {
   loading.value = true
   title.value = 'Loading'
+  if(!props.multiple) {
+    reactiveData.form.size = file.size
+    reactiveData.form.name = file.name
+  }
 }
 
 // 上传成功
-function onSuccess(file, uploadFiles) {
+function onSuccess(file) {
   if (file.code === 0) {
     loading.value = false
     type.value = 'success'
     title.value = '上传成功'
-    reactiveData.form.push({
-      file: uploadFiles.response.data,
-      name: uploadFiles.name,
-      size: uploadFiles.size
-    })
+    if (props.multiple) {
+      file.data.map(i => reactiveData.form.push(i))
+    }else{
+      reactiveData.form.file = file.data
+    }
     proxy.$emit('upload', reactiveData.form)
   } else {
     onError()
@@ -86,7 +103,7 @@ function onSuccess(file, uploadFiles) {
 
 // 文件移除之前
 function beforeRemove() {
-  return proxy.$modal.confirm('是否删除').then(
+  return proxy.$modal.confirm('是否删除').then(
     () => true,
     () => false
   )
@@ -104,4 +121,25 @@ function onError() {
   type.value = 'danger'
   title.value = '上传失败'
 }
-</script>
+
+// 重置组件
+function onRefresh() {
+  type.value = 'primary'
+  title.value = '点击上传'
+  proxy.$refs.upload.clearFiles()
+}
+
+defineExpose({
+  onRefresh
+})
+</script>
+
+<style lang="scss" scoped>
+.image {
+  width: 148px;
+  height: 148px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+</style>

+ 83 - 0
src/hooks/index.js

@@ -0,0 +1,83 @@
+import { ref, reactive } from "vue";
+
+// // 内容管理-标签分类
+import { list as contentClassList } from "@/api/content/class";
+
+export function useContentClass() {
+  const classOptions = ref([]);
+  function getContentClass() {
+    contentClassList().then((res) => {
+      if (res.code === 0) {
+        classOptions.value = res.data;
+      }
+    });
+  }
+
+  // 挂载
+  onMounted(() => getContentClass());
+  // 卸载
+  onUnmounted(() => getContentClass());
+
+  return { classOptions };
+}
+
+// // 企业管理-行业管理
+import { options as businessClassList } from "@/api/business/class";
+
+export function useBusinessClass() {
+  const classOptions = ref([]);
+  function getClassOptions() {
+    businessClassList().then((res) => {
+      if (res.code === 0) {
+        res.data.map((i) => {
+          classOptions.value.push({
+            value: i.id,
+            label: i.name,
+          });
+        });
+      }
+    });
+  }
+
+  // 挂载
+  onMounted(() => getClassOptions());
+  // 卸载
+  onUnmounted(() => getClassOptions());
+
+  return { classOptions };
+}
+
+// // 企业管理-企业中心
+import { options as businessList } from "@/api/business/list";
+
+export function useBusinessList(type) {
+  /* type为筛选条件 */
+  const businessForm = ref({
+    pageNum: 1,
+    pageSize: 10,
+  });
+  const businessOptions = ref([]);
+
+  function getOptions() {
+    businessOptions.value = [];
+    businessList(businessForm).then((res) => {
+      if (res.code === 0) {
+        res.data.forEach((i) => {
+          businessOptions.value.push({
+            value: i.id,
+            label: i.name,
+          });
+        });
+        if (type) {
+          businessOptions.value = businessOptions.value.slice(1);
+        }
+      }
+    });
+  }
+
+  onMounted(() => getOptions());
+
+  onUnmounted(() => getOptions());
+
+  return { businessForm, businessOptions };
+}

+ 18 - 7
src/router/index.js

@@ -158,19 +158,30 @@ export const dynamicRoutes = [
       },
     ],
   },
-  // 设备管理
   {
-    path: "/device",
+    path: "/content",
     component: Layout,
     hidden: true,
-    permissions: ["device:control:list"],
+    permissions: ["content:setting:list"],
     children: [{
-      path: "control/storeGrouping",
-      component: () => import("@/views/device/control/storeGrouping"),
-      name: "storeGrouping",
-      meta: { title: "门店分组", activeMenu: "/device/control"}
+      path: "setting/detail",
+      component: () => import("@/views/content/setting/detail"),
+      name: 'settingDetail',
+      meta: { title: '设定详情', activeMenu: "/content/setting"}
     }]
   },
+  {
+    path: "/content",
+    component: Layout,
+    hidden: true,
+    permissions: ["content:scene:list"],
+    children: [{
+      path: "scene/detail",
+      component: () => import("@/views/content/scene/detail"),
+      name: "sceneDetail",
+      meta: { title: '预设详情', activeMenu: "/content/scene" }
+    }]
+  }
 ];
 
 const router = createRouter({

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

@@ -35,7 +35,7 @@ const useUserStore = defineStore(
         return new Promise((resolve, reject) => {
           getInfo().then(res => {
             const user = res.user
-            const avatar = (user.avatar == "" || user.avatar == null) ? defAva : import.meta.env.VITE_APP_BASE_API + user.avatar;
+            const avatar = (user.avatar == "" || user.avatar == null) ? defAva : user.avatar;
 
             if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
               this.roles = res.roles

+ 2 - 1
src/utils/request.js

@@ -76,7 +76,8 @@ service.interceptors.response.use(res => {
     // 未设置状态码则默认成功状态
     const code = res.data.code || 200;
     // 获取错误信息
-    const msg = errorCode[code] || res.data.msg || errorCode['default']
+    // const msg = errorCode[code] || res.data.msg || errorCode['default']
+    const msg = res.data.message
     // 二进制数据则直接返回
     if (res.request.responseType ===  'blob' || res.request.responseType ===  'arraybuffer') {
       return res.data

+ 112 - 16
src/views/business/class/index.vue

@@ -2,45 +2,141 @@
   <div class='app-container'>
     <el-form>
       <el-form-item>
-        <el-button type="primary" icon="Plus" @click="getDialog">新增行业</el-button>
+        <el-button type="primary" icon="Plus" @click="getDialog()">新增行业</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 :data="data.tableData" v-loading="loading">
+      <el-table-column label="行业ID" prop="id" align="center"></el-table-column>
+      <el-table-column label="行业名称" prop="name" align="center"></el-table-column>
+      <el-table-column label="创建时间" prop="createTimeStr" align="center"></el-table-column>
       <el-table-column label="操作" align="center">
         <template #default="scope">
-          <el-button type="primary" link>编辑</el-button>
-          <el-button type="danger" link>删除</el-button>
+          <el-button type="primary" link @click="getDialog(scope.row.id)">编辑</el-button>
+          <el-button type="danger" link @click="getDelete(scope.row)">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
+    <pagination v-show="total > 0" :total="total" v-model:page="data.form.pageNum" v-model:limit="data.form.pageSize"
+      @pagination="getList" />
+
     <!-- 弹窗 -->
-    <el-dialog v-model="dialogVisible" :title="title" width="500">
-      <el-form>
-        <el-form-item label="行业名称:">
-          <el-input placeholder="请输入行业名称" />
+    <el-dialog v-model="dialogVisible" :title="title" width="500" :before-close="getClose">
+      <el-form ref="dialogForm" :model="data.dialogForm">
+        <el-form-item label="行业名称:" prop="name" :rules="[{ required: true, message: '请输入行业名称', trigger: 'blur' }]">
+          <el-input v-model="data.dialogForm.name" placeholder="请输入行业名称" />
         </el-form-item>
       </el-form>
       <template #footer>
-        <el-button>取消</el-button>
-        <el-button type="primary">确定</el-button>
+        <el-button @click="getClose">取消</el-button>
+        <el-button type="primary" @click="getSubmit">确定</el-button>
       </template>
     </el-dialog>
   </div>
 </template>
 
 <script setup>
+import { list, detail, submit, edit, remove } from '@/api/business/class'
+
+let { proxy } = getCurrentInstance();
+
+// 遮罩层
+const loading = ref(false)
+
 const data = reactive({
+  // 表单
+  form: {
+    pageNum: 1,
+    pageSize: 10
+  },
+  // 列表
+  tableData: [],
+  // 弹窗表单
   dialogForm: {}
 })
 
+// 总数据
+const total = ref(0)
+
+// 列表
+function getList() {
+  loading.value = true
+  list(data.form).then(res => {
+    if (res.code === 0) {
+      data.tableData = res.data
+      total.value = res.total
+      loading.value = false
+    }
+  })
+}
+getList()
+
 // 弹窗
 const dialogVisible = ref(false)
-const title = ref("新增")
-
-function getDialog() {
+// 弹窗标题
+const title = ref("")
+// 打开弹窗
+function getDialog(id) {
   dialogVisible.value = true
+  title.value = '新增'
+  if (id) {
+    getDetail(id)
+  }
 }
+
+// 详情
+function getDetail(id) {
+  title.value = '编辑'
+  detail(id).then(res => {
+    if (res.code === 0) {
+      data.dialogForm = res.data
+    }
+  })
+}
+
+// 关闭弹窗
+function getClose() {
+  dialogVisible.value = false
+  data.dialogForm = {}
+  proxy.$refs.dialogForm.resetFields()
+}
+
+// 新增
+function getSubmit() {
+  proxy.$refs['dialogForm'].validate(valid => {
+    if (valid) {
+      if (data.dialogForm.id) {
+        edit(data.dialogForm).then(res => {
+          if (res.code === 0) {
+            proxy.$modal.msgSuccess('修改成功!')
+            getClose()
+            getList()
+          }
+        })
+      } else {
+        submit(data.dialogForm).then(res => {
+          if (res.code === 0) {
+            proxy.$modal.msgSuccess('提交成功!')
+            getClose()
+            getList()
+          }
+        })
+      }
+    } else {
+      return false
+    }
+  })
+}
+
+// 删除
+function getDelete(row) {
+  proxy.$modal.confirm(`是否删除行业名称为:${row.name}的数据?`).then(() => {
+    remove(row.id).then(res => {
+      if (res.code === 0) {
+        proxy.$modal.msgSuccess('删除成功!')
+        getList()
+      }
+    })
+  }).catch(() => { })
+}
+
 </script>

+ 299 - 84
src/views/business/list/index.vue

@@ -2,86 +2,86 @@
   <div class='app-container'>
     <el-form inline>
       <el-form-item label="企业ID:">
-        <el-input placeholder="请输入企业ID" />
+        <el-input v-model="data.form.id" placeholder="请输入企业ID" clearable />
       </el-form-item>
       <el-form-item label="企业名称:">
-        <el-input placeholder="请输入企业名称" />
+        <el-input v-model="data.form.name" placeholder="请输入企业名称" clearable />
       </el-form-item>
       <el-form-item label="行业:">
-        <el-select placeholder="请选择行业">
-          <!-- <el-option /> -->
+        <el-select v-model="data.form.organizationIndustryId" placeholder="请选择行业" clearable>
+          <el-option v-for="item in classOptions" :key="item.value" :value="item.value" :label="item.label" />
         </el-select>
       </el-form-item>
       <el-form-item>
-        <el-button type="primary" icon="Search">搜索</el-button>
-        <el-button icon="Refresh">重置</el-button>
-        <el-button type="primary" plain icon="Plus" @click="getDialog">新增</el-button>
-        <el-button type="danger" plain icon="Delete">批量删除</el-button>
-        <el-button type="warning" plain icon="Download">导出</el-button>
+        <el-button type="primary" icon="Search" @click="getSearch">搜索</el-button>
+        <el-button icon="Refresh" @click="getRefresh">重置</el-button>
+        <el-button type="warning" plain icon="Download" @click="getExport" :disabled="ids === ''">导出</el-button>
+        <el-button type="primary" plain icon="Plus" @click="getDialog()">新增</el-button>
       </el-form-item>
     </el-form>
     <!-- 列表 -->
-    <el-table :data="data.tableData" v-loading="loading" row-key="id"
-      :tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
-      <!-- <el-table-column type="selection" align="center"></el-table-column> -->
-      <el-table-column align="center" width="50" />
+    <el-table :data="data.tableData" ref="tableData" v-loading="loading" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" />
       <el-table-column label="企业ID" prop="id" align="center"></el-table-column>
       <el-table-column label="企业名称" prop="name" align="center"></el-table-column>
-      <el-table-column label="企业管理员" prop="user" align="center"></el-table-column>
+      <el-table-column label="企业管理员" prop="userName" align="center"></el-table-column>
       <el-table-column label="联系方式" prop="phone" align="center"></el-table-column>
+      <el-table-column label="上级企业" prop="parentName" align="center"></el-table-column>
       <el-table-column label="当前状态" prop="status" align="center">
         <template #default="scope">
-          <el-switch />
+          <el-switch v-model="scope.row.status" active-value="0" inactive-value="1"
+            :before-change="() => beforeChange(scope.row)" />
         </template>
       </el-table-column>
-      <el-table-column label="行业" prop="class" align="center"></el-table-column>
-      <el-table-column label="创建时间" prop="createtime" align="center"></el-table-column>
+      <el-table-column label="行业" prop="organizationIndustryName" align="center" />
+      <el-table-column label="创建时间" prop="createTimeStr" align="center"></el-table-column>
       <el-table-column label="操作" align="center">
         <template #default="scope">
-          <el-button type="primary" link @click="getDialog">编辑</el-button>
+          <el-button type="primary" link @click="getDialog(scope.row.id, '编辑')">编辑</el-button>
           <el-button type="primary" link @click="getDialogHistory">操作日志</el-button>
-          <el-button type="primary" link>重置密码</el-button>
-          <el-button type="danger" link>删除</el-button>
+          <el-button type="primary" link @click="getReset(scope.row)">重置密码</el-button>
+          <el-button type="danger" link @click="getDelete(scope.row)">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
     <pagination v-show="total > 0" :total="total" v-model:page="data.form.pageNum" v-model:limit="data.form.pageSize"
       @pagination="getList" />
     <!-- 弹窗 -->
-    <el-dialog v-model="dialogVisible" :title="title" width="500">
-      <el-form label-width="100px">
-        <el-form-item label="公司名称:">
-          <el-input placeholder="请输入公司名称" />
+    <el-dialog v-model="dialogVisible" :title="title" width="500" :before-close="getClose">
+      <el-form ref="dialogForm" :model="data.dialogForm" :rules="data.rules" label-width="100px">
+        <el-form-item label="公司名称:" prop="name">
+          <el-input v-model="data.dialogForm.name" placeholder="请输入公司名称" />
         </el-form-item>
-        <el-form-item label="营业执照:">
-          <CustomUpload listType="picture-card" />
+        <el-form-item label="营业执照:" prop="businessLicense">
+          <CustomUpload listType="picture-card" :src="data.dialogForm.businessLicense" @upload="upload" />
         </el-form-item>
-        <el-form-item label="行业:">
-          <el-select placeholder="请选择行业">
-            <!-- <el-option /> -->
+        <el-form-item label="行业:" prop="organizationIndustryId">
+          <el-select v-model="data.dialogForm.organizationIndustryId" placeholder="请选择行业">
+            <el-option v-for="item in classOptions" :key="item.value" :value="item.value" :label="item.label" />
           </el-select>
         </el-form-item>
-        <el-form-item label="联系方式:">
-          <el-input placeholder="请输入联系方式" />
+        <el-form-item label="联系方式:" prop="phone">
+          <el-input v-model="data.dialogForm.phone" placeholder="请输入联系方式" />
         </el-form-item>
-        <el-form-item label="账号名称:">
-          <el-input placeholder="<企业名>@<用户名>,例如:yundong@admin" />
+        <el-form-item label="账号名称:" prop="userName">
+          <el-input v-model="data.dialogForm.userName" placeholder="<企业名>@<用户名>,例如:yundong@admin" />
         </el-form-item>
-        <el-form-item label="归属企业:">
-          <el-select placeholder="请选择归属企业">
-            <!-- <el-option /> -->
+        <el-form-item label="归属企业:" prop="parentId">
+          <el-select v-model="data.dialogForm.parentId" filterable :filter-method="filterMethod" placeholder="请选择归属企业">
+            <el-option v-for="item in businessData.options" :key="item.value" :value="item.value" :label="item.label"
+              :disabled="disabledBusiness(item)" />
           </el-select>
         </el-form-item>
         <el-form-item label="菜单权限:">
-          <el-checkbox label="展开/折叠" />
-          <el-checkbox label="全选/全不选" />
-          <el-checkbox label="父子联动" />
-          <el-tree class="tree-border" :data="data.deptOptions" :props="{ label: 'label', children: 'children' }"
-            show-checkbox default-expand-all />
+          <el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand">展开/折叠</el-checkbox>
+          <el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll">全选/全不选</el-checkbox>
+          <el-checkbox v-model="menuCheckStrictly" @change="handleCheckedTreeConnect">父子联动</el-checkbox>
+          <el-tree class="tree-border" :data="data.treeOptions" :props="{ label: 'label', children: 'children' }"
+            show-checkbox ref="menuRef" node-key="id" :check-strictly="!menuCheckStrictly" empty-text="加载中,请稍候" />
         </el-form-item>
       </el-form>
       <template #footer>
-        <el-button>取消</el-button>
+        <el-button @click="getClose">取消</el-button>
         <el-button type="primary" @click="getSubmit">确定</el-button>
       </template>
     </el-dialog>
@@ -96,84 +96,299 @@
 </template>
 
 <script setup>
+import { list, detail, remove, submit, edit, change, reset } from '@/api/business/list'
+import { useBusinessClass, useBusinessList } from '@/hooks/index'
+import { treeselect } from '@/api/system/menu'
+import { ElMessageBox } from 'element-plus';
+import { nextTick } from 'vue';
+
 let { proxy } = getCurrentInstance();
+
+const { classOptions } = useBusinessClass()
+const { businessData, getBusinessOptions } = useBusinessList()
+
+const reg = ref(/1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}/)
+const checkPhone = (rule, value, callback) => {
+  if (value) {
+    if (!reg.value.test(value)) {
+      callback(new Error('请输入正确的手机号'))
+    } else {
+      callback()
+    }
+  }
+}
 // 遮罩层
 const loading = ref(false)
 
 const data = reactive({
-  // 表单
+  // 表单
   form: {
     pageNum: 1,
     pageSize: 10
   },
   // 列表
-  tableData: [{
-    id: '1',
-    name: '深圳瑞幸(南山)',
-    user: 'admin',
-    phone: '186xxxx2785',
-    status: 1,
-    class: '餐饮',
-    createtime: '2024-02-29 00:00:00',
-    children: [{
-      id: '2',
-      name: '深圳瑞幸中科大厦店',
-      user: 'admin1',
-      phone: '138xxxx2222',
-      status: 1,
-      class: '餐饮',
-      createtime: '2024-02-29 00:00:00'
-    }]
-  }, {
-    id: '3',
-    name: '深圳瑞幸(宝安)',
-    user: 'admin',
-    phone: '186xxxx2785',
-    status: 1,
-    class: '餐饮',
-    createtime: '2024-02-29 00:00:00',
-    children: [{
-      id: '4',
-      name: '深圳瑞幸(宝安)大仟里店',
-      user: 'admin2',
-      phone: '138xxxx2222',
-      status: 1,
-      class: '餐饮',
-      createtime: '2024-02-29 00:00:00'
-    }]
-  }],
+  tableData: [],
   // 菜单权限
   deptOptions: [],
   // 弹窗表单
-  dialogForm: {}
+  dialogForm: {},
+  // 校验
+  rules: {
+    name: [{
+      required: true, message: "请输入公司名称", trigger: "blur"
+    }],
+    businessLicense: [{
+      required: true, message: "请上传营业执照", trigger: "change"
+    }],
+    organizationIndustryId: [{
+      required: true, message: '请选择行业', trigger: 'change'
+    }],
+    phone: [{
+      required: true, message: '请输入手机号', trigger: 'blur'
+    }, {
+      validator: checkPhone, trigger: 'blur'
+    }],
+    userName: [{
+      required: true, message: '请输入账号名称', trigger: 'blur'
+    }],
+    parentId: [{
+      required: true, message: '请选择归属企业', trigger: 'change'
+    }]
+  }
 })
 
+const menuExpand = ref(false)
+const menuNodeAll = ref(false)
+const menuCheckStrictly = ref(false)
+
 // 总数据
 const total = ref(0)
 
+// 多选
+const ids = ref('')
+
+// 列表
 function getList() {
+  loading.value = true
+  list(data.form).then(res => {
+    if (res.code === 0) {
+      data.tableData = res.data
+      total.value = res.total
+      loading.value = false
+    }
+  })
+}
+getList()
 
+// 搜索
+function getSearch() {
+  data.form.pageNum = 1
+  getList()
 }
 
-getList()
+// 重置
+function getRefresh() {
+  data.form = {
+    pageNum: 1,
+    pageSize: 10
+  }
+  getList()
+}
+
+// 列表多选
+function handleSelectionChange(val) {
+  let arr = []
+  val.map(i => arr.push(i.id))
+  ids.value = arr.join(',')
+}
+
+// 导出
+function getExport() {
+  proxy.download("/organization/organization/export",
+    { ids: ids.value }, `business_${new Date().getTime()}.xlsx`);
+}
+
+// 修改状态
+function beforeChange(row) {
+  let status = row.status == 0 ? 1 : 0
+  return new Promise((resolve, reject) => {
+    change({ id: row.id, status: status }).then(res => {
+      if (res.code === 0) {
+        return resolve(true)
+      }
+    }).catch(() => {
+      return reject()
+    })
+  })
+}
 
 // 弹窗
 const dialogVisible = ref(false)
 // 操作日志弹窗
 const dialogVisible_history = ref(false)
+// 弹窗标题
 const title = ref("新增")
 
-function getDialog() {
+// 打开弹窗
+function getDialog(id, key) {
+  getTree()
   dialogVisible.value = true
+  title.value = '新增'
+  if (id) {
+    getDetail(id)
+  }
 }
 
-function getDialogHistory() {
-  dialogVisible_history.value = true
+// 详情
+function getDetail(id) {
+  title.value = '编辑'
+  detail(id).then(res => {
+    if (res.code === 0) {
+      data.dialogForm = res.data
+      let checkedKeys = res.data.menuIds
+      checkedKeys.forEach(i => {
+        nextTick(() => {
+          proxy.$refs.menuRef.setChecked(i, true, false)
+        })
+      })
+    }
+  })
+}
+
+// 新增的菜单权限
+function getTree() {
+  treeselect().then(res => {
+    if (res.code === 0) {
+      data.treeOptions = res.data
+    }
+  })
+}
+
+// 上传
+function upload(e) {
+  data.dialogForm.businessLicense = e.file
+}
+
+// 归属企业搜索
+function filterMethod(query) {
+  if (query) {
+    setTimeout(() => {
+      businessData.form.pageNum = 1
+      businessData.form.name = query
+      getBusinessOptions()
+    }, 300)
+  }
+}
+
+// 关闭弹窗
+function getClose() {
+  dialogVisible.value = false
+  data.dialogForm = {}
+  menuExpand.value = false
+  menuNodeAll.value = false
+  menuCheckStrictly.value = false
+  if (proxy.$refs.menuRef != undefined) {
+    proxy.$refs.menuRef.setCheckedKeys([]);
+  }
+  proxy.$refs.dialogForm.resetFields()
 }
 
 // 提交
 function getSubmit() {
-  proxy.$modal.msgSuccess("提交成功!密码将通过短信方式生成!");
+  proxy.$refs.dialogForm.validate(valid => {
+    if (valid) {
+      data.dialogForm.menuIds = getMenuAllCheckedKeys()
+      if (data.dialogForm.id) {
+        edit(data.dialogForm).then(res => {
+          if (res.code === 0) {
+            proxy.$modal.msgSuccess("提交成功!");
+            getClose()
+            getList()
+          }
+        })
+      } else {
+        submit(data.dialogForm).then(res => {
+          if (res.code === 0) {
+            ElMessageBox.alert(`密码将通过短信方式生成!`, '提示', {
+              type: 'warning',
+              callback: () => {
+                proxy.$modal.msgSuccess("提交成功!");
+                getClose()
+                getList()
+              }
+            })
+          }
+        })
+      }
+    } else {
+      return false
+    }
+  })
+}
+
+// 操作日志
+function getDialogHistory() {
+  dialogVisible_history.value = true
+}
+
+// 删除
+function getDelete(row) {
+  proxy.$modal.confirm(`是否删除企业名称为:${row.name}的数据?`).then(() => {
+    remove({ id: row.id }).then(res => {
+      if (res.code === 0) {
+        proxy.$modal.msgSuccess('删除成功!')
+        getList()
+      }
+    })
+  }).catch(() => { })
+}
+
+/** 所有菜单节点数据 */
+function getMenuAllCheckedKeys() {
+  // 目前被选中的菜单节点
+  let checkedKeys = proxy.$refs.menuRef.getCheckedKeys();
+  // 半选中的菜单节点el-
+  let halfCheckedKeys = proxy.$refs.menuRef.getHalfCheckedKeys();
+  checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys);
+  return checkedKeys;
+}
+
+/** 树权限(展开/折叠)*/
+function handleCheckedTreeExpand(value) {
+  let treeList = data.treeOptions;
+  for (let i = 0; i < treeList.length; i++) {
+    proxy.$refs.menuRef.store.nodesMap[treeList[i].id].expanded = value
+  }
+}
+
+/** 树权限(全选/全不选) */
+function handleCheckedTreeNodeAll(value) {
+  proxy.$refs.menuRef.setCheckedNodes(value ? data.treeOptions : []);
+}
+
+/** 树权限(父子联动) */
+function handleCheckedTreeConnect(value) {
+  menuCheckStrictly.value = value ? true : false;
+}
+
+// 禁止选择自己为归属企业
+function disabledBusiness(item) {
+  if (data.dialogForm.id) {
+    return data.dialogForm.id === item.value ? true : false
+  }
+}
+
+// 重置密码
+function getReset(row) {
+  proxy.$modal.confirm(`是否要重置账号为:${row.userName}的密码?`).then(() => {
+    reset({
+      userId: row.userId
+    }).then(res => {
+      if (res.code === 0) {
+        proxy.$modal.msgSuccess('短信已发送!')
+      }
+    })
+  }).catch(() => { })
 }
 </script>
 

+ 89 - 16
src/views/content/class/index.vue

@@ -2,50 +2,123 @@
   <div class='app-container'>
     <el-form>
       <el-form-item>
-        <el-button type="primary" icon="Plus" @click="getDialog">新增分类</el-button>
+        <el-button type="primary" icon="Plus" @click="getDialog()">新增分类</el-button>
       </el-form-item>
     </el-form>
     <!-- 列表 -->
     <el-table :data="data.tableData" v-loading="loading">
-      <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="分类ID" prop="id" align="center"></el-table-column>
+      <el-table-column label="分类名称" prop="name" align="center"></el-table-column>
+      <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>编辑</el-button>
-          <el-button type="danger" link>删除</el-button>
+          <el-button type="primary" link @click="getDialog(scope.row.id)">编辑</el-button>
+          <el-button type="danger" link @click="getDelete(scope.row)">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
     <!-- 弹窗 -->
-    <el-dialog v-model="dialogVisible" :title="title" width="500">
-      <el-form>
-        <el-form-item label="分类名称:">
-          <el-input placeholder="请输入分类名称" />
+    <el-dialog v-model="dialogVisible" :title="title" width="500" :before-close="getClose">
+      <el-form ref="dialogForm" :model="data.dialogForm" :rules="data.rules">
+        <el-form-item label="分类名称:" prop="name">
+          <el-input v-model="data.dialogForm.name" placeholder="请输入分类名称" />
         </el-form-item>
       </el-form>
+
       <template #footer>
-        <el-button>取消</el-button>
-        <el-button type="primary">确定</el-button>
+        <el-button @click="getClose">取消</el-button>
+        <el-button type="primary" @click="getSubmit">确定</el-button>
       </template>
     </el-dialog>
   </div>
 </template>
 
 <script setup>
+import { list, detail, submit, remove } from '@/api/content/class'
+
+const { proxy } = getCurrentInstance();
 // 遮罩层
 const loading = ref(false)
 
 const data = reactive({
-  tableData: [{}],
-  dialogForm: {}
+  // 列表
+  tableData: [],
+  // 弹窗表单
+  dialogForm: {},
+  // 校验
+  rules: {
+    name: [{
+      required: true, message: '请输入分类名称', trigger: 'blur'
+    }]
+  }
 })
 
+// 列表
+function getList() {
+  list(data.form).then(res => {
+    data.tableData = res.data
+  })
+}
+getList()
+
 // 弹窗
 const dialogVisible = ref(false)
+// 弹窗标题
 const title = ref("新增")
-
-function getDialog() {
+// 打开弹窗
+function getDialog(id, key) {
   dialogVisible.value = true
+  title.value = '新增'
+  if (id) {
+    getDetail(id)
+  }
+}
+
+// 详情
+function getDetail(id) {
+  title.value = '编辑'
+  detail({ id: id }).then(res => {
+    if (res.code === 0) {
+      data.dialogForm = res.data
+    }
+  })
+}
+
+// 取消
+function getClose() {
+  dialogVisible.value = false
+  data.dialogForm = {}
+  proxy.resetForm('dialogForm')
+}
+
+// 提交
+function getSubmit() {
+  proxy.$refs['dialogForm'].validate(valid => {
+    if (valid) {
+      submit(data.dialogForm).then(res => {
+        if (res.code === 0) {
+          proxy.$modal.msgSuccess("提交成功!");
+          getClose()
+          getList()
+        }
+      })
+    } else {
+      return false
+    }
+  })
+}
+
+// 删除
+function getDelete(row) {
+  proxy.$modal.confirm(`是否删除分类名称为:${row.name}的数据?`, '提示', {
+    type: 'warning'
+  }).then(() => {
+    remove({ id: row.id }).then(res => {
+      if (res.code === 0) {
+        proxy.$modal.msgSuccess('删除成功!')
+        getList()
+      }
+    }).catch(() => { })
+  })
 }
 </script>

+ 184 - 36
src/views/content/list/index.vue

@@ -3,92 +3,240 @@
     <!-- 搜索 -->
     <el-form inline>
       <el-form-item label="音频ID:">
-        <el-input placeholder="请输入音频ID" />
+        <el-input v-model="data.form.id" placeholder="请输入音频ID" clearable />
       </el-form-item>
       <el-form-item label="音频名称:">
-        <el-input placeholder="请输入音频名称" />
+        <el-input v-model="data.form.name" placeholder="请输入音频名称" clearable />
       </el-form-item>
       <el-form-item label="音频分类:">
-        <el-select>
-          <!-- <el-option /> -->
+        <el-select v-model="data.form.sceneId" placeholder="请选择音频分类" clearable>
+          <el-option v-for="item in classOptions" :key="item.id" :value="item.id" :label="item.name" />
         </el-select>
       </el-form-item>
       <el-form-item label="当前状态:">
-        <el-select placeholder="请选择当前状态">
-          <!-- <el-option /> -->
+        <el-select v-model="data.form.status" placeholder="请选择当前状态" clearable>
+          <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">搜索</el-button>
-        <el-button icon="Refresh">重置</el-button>
-        <el-button type="warning" plain icon="Download">导出</el-button>
-        <el-button type="primary" plain icon="Plus" @click="getDialog">新增</el-button>
+        <el-button type="primary" icon="Search" @click="getSearch">搜索</el-button>
+        <el-button icon="Refresh" @click="getRefresh">重置</el-button>
+        <el-button type="primary" plain icon="Plus" @click="getDialog()">新增</el-button>
       </el-form-item>
     </el-form>
     <!-- 列表 -->
     <el-table :data="data.tableData" v-loading="loading">
-      <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"></el-table-column>
-      <el-table-column label="更新时间" align="center"></el-table-column>
+      <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="音频分类" prop="sceneId" align="center" :formatter="sceneFormatter" />
+      <el-table-column label="当前状态" prop="status" align="center">
+        <template #default="scope">
+          <dict-tag :options="sys_change_status" :value="scope.row.status" />
+        </template>
+      </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>编辑</el-button>
-          <el-button type="primary" link>上架</el-button>
-          <el-button type="primary" link>下架</el-button>
-          <el-button type="danger" link>删除</el-button>
+          <el-button type="primary" link @click="getDialog(scope.row.id, '编辑')">编辑</el-button>
+          <el-button v-if="scope.row.status === 1" type="primary" link
+            @click="getChange(scope.row.id, '上架', 0)">上架</el-button>
+          <el-button v-else type="primary" link @click="getChange(scope.row.id, '下架', 1)">下架</el-button>
+          <el-button type="danger" link @click="getDelete(scope.row)">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
     <pagination v-show="total > 0" :total="total" v-model:page="data.form.pageNum" v-model:limit="data.form.pageSize"
       @pagination="getList" />
     <!-- 弹窗 -->
-    <el-dialog v-model="dialogVisible" :title="title" width="500">
-      <el-form>
-        <el-form-item label="上传音频:">
-          <CustomUpload showFileList multiple @upload="upload" style="width: 100%" />
+    <el-dialog v-model="dialogVisible" :title="title" width="500" :before-close="getClose">
+      <el-form ref="dialogForm" :model="data.dialogForm" :rules="data.rules" label-width="100px">
+        <el-form-item label="上传音频:" prop="list" v-if="title === '编辑' ? false : true">
+          <CustomUpload ref="customUpload" :url="`${baseUrl}/radio/tProgram/mp3/upload`" showFileList multiple
+            @upload="upload" style="width: 100%" />
         </el-form-item>
-        <el-form-item label="音频分类:">
-          <el-input placeholder="请输入音频分类名称" />
+        <el-form-item label="音频名称:" prop="name" v-else>
+          <el-input v-model="data.dialogForm.name" disabled />
+        </el-form-item>
+        <el-form-item label="音频分类:" prop="sceneId">
+          <el-select v-model="data.dialogForm.sceneId" placeholder="请选择标签分类" clearable>
+            <el-option v-for="item in classOptions" :key="item.id" :value="item.id" :label="item.name" />
+          </el-select>
         </el-form-item>
       </el-form>
+
       <template #footer>
-        <el-button>取消</el-button>
-        <el-button type="primary">确定</el-button>
+        <el-button @click="getClose">取消</el-button>
+        <el-button type="primary" @click="getSubmit">确定</el-button>
       </template>
     </el-dialog>
   </div>
 </template>
 
 <script setup>
+import { list, detail, submit, change } from '@/api/content/list'
+import { useContentClass } from '@/hooks/index.js'
+
+const { proxy } = getCurrentInstance();
+const { sys_change_status } = proxy.useDict("sys_change_status")
+const { classOptions } = useContentClass()
+const baseUrl = ref(import.meta.env.VITE_APP_BASE_API)
+
 // 遮罩层
 const loading = ref(false)
 
 const data = reactive({
+  // 表单
   form: {
     pageNum: 1,
     pageSize: 10
   },
-  tableData: [{}]
+  // 列表
+  tableData: [],
+  // 校验
+  rules: {
+    list: [{
+      required: true, message: '请上传音频', trigger: 'change'
+    }],
+    sceneId: [{
+      required: true, message: '请选择音频分类', trigger: 'change'
+    }]
+  },
+  // 弹窗表单
+  dialogForm: {
+    list: [],
+    sceneId: ''
+  }
 })
-
+// 总数据
 const total = ref(0)
 
+// 列表
 function getList() {
-
+  loading.value = true
+  list(data.form).then(res => {
+    if (res.code === 0) {
+      data.tableData = res.data.records
+      total.value = res.data.total
+      loading.value = false
+    }
+  })
 }
 getList()
 
-const dialogVisible = ref(false)
-const title = ref("新增")
+// 搜索
+function getSearch() {
+  data.form.pageNum = 1
+  getList()
+}
+
+// 重置
+function getRefresh() {
+  data.form = {
+    pageNum: 1,
+    pageSize: 10
+  }
+  getList()
+}
 
-function getDialog() {
+// 弹窗
+const dialogVisible = ref(false)
+// 弹窗标题
+const title = ref(undefined)
+// 打开弹窗
+function getDialog(id, key) {
   dialogVisible.value = true
+  title.value = '新增'
+  if (id) {
+    getDetail(id)
+  }
+}
+
+// 详情
+function getDetail(id) {
+  title.value = '编辑'
+  detail({ id: id }).then(res => {
+    if (res.code === 0) {
+      data.dialogForm = res.data
+    }
+  })
+}
+
+// 上传
+function upload(file) {
+  data.dialogForm.list = file
+}
+
+// 提交
+function getSubmit() {
+  proxy.$refs['dialogForm'].validate(valid => {
+    if (valid) {
+      let list = []
+      if (!data.dialogForm.id) {
+        data.dialogForm.list.map(i => {
+          i['sceneId'] = data.dialogForm.sceneId
+        })
+        delete data.dialogForm.sceneId
+        list = data.dialogForm.list
+      } else {
+        list.push(data.dialogForm)
+      }
+      submit(list).then(res => {
+        if (res.code === 0) {
+          proxy.$modal.msgSuccess("提交成功!")
+          getClose()
+          getList()
+        }
+      })
+    } else {
+      return false
+    }
+  })
+}
+
+// 取消
+function getClose() {
+  dialogVisible.value = false
+  data.dialogForm = {}
+  proxy.$refs.dialogForm.resetFields()
+  if (title.value === '新增') {
+    proxy.$refs.customUpload.onRefresh()
+  }
+}
+
+// 上下架
+function getChange(id, key, status) {
+  change({
+    ids: id,
+    status: status
+  }).then(res => {
+    if (res.code === 0) {
+      proxy.$modal.msgSuccess(`${key}成功!`)
+      getList()
+    }
+  })
+}
+
+// 删除
+function getDelete(row) {
+  proxy.$modal.confirm(`是否删除音频名称为:${row.name}的数据?`).then(() => {
+    change({
+      ids: row.id,
+      status: row.status,
+      delFlag: 2
+    }).then(res => {
+      if (res.code === 0) {
+        proxy.$modal.msgSuccess('删除成功!')
+        getList()
+      }
+    })
+  })
 }
 
-function upload(e) {
-  console.log(e);
+// 字典
+function sceneFormatter(row) {
+  let e = classOptions._rawValue.find(i => i.id === row.sceneId)
+  return e ? e.name : row.sceneId
 }
 </script>

+ 127 - 0
src/views/content/ohplay/index.vue

@@ -0,0 +1,127 @@
+<template>
+  <div class='app-container'>
+    <el-form inline>
+      <el-form-item label="歌曲ID:">
+        <el-input v-model="data.form.id" placeholder="请输入歌曲ID" clearable />
+      </el-form-item>
+      <el-form-item label="歌曲名称:">
+        <el-input v-model="data.form.name" placeholder="请输入歌曲名称" clearable />
+      </el-form-item>
+      <el-form-item label="歌手名称:">
+        <el-input v-model="data.form.singerName" placeholder="请输入歌手名称" clearable />
+      </el-form-item>
+      <el-form-item label="资源平台:">
+        <el-select v-model="data.form.platformId" placeholder="请选择资源平台" clearable>
+          <el-option v-for="item in data.platformOptions" :key="item.value" :value="item.value" :label="item.label" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="当前状态:">
+        <el-select v-model="data.form.status" placeholder="请选择当前状态" clearable>
+          <el-option v-for="item in ohplay_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 :data="data.tableData" v-loading="loading">
+      <el-table-column label="歌曲ID" prop="id" align="center"></el-table-column>
+      <el-table-column label="歌曲名称" prop="name" align="center"></el-table-column>
+      <el-table-column label="歌曲封面" prop="thumbUrl" align="center" width="100px">
+        <template #default="scope">
+          <el-image :src="scope.row.thumbUrl" />
+        </template>
+      </el-table-column>
+      <el-table-column label="歌手名称" prop="singerName" align="center"></el-table-column>
+      <el-table-column label="资源平台" prop="platformId" align="center" :formatter="platformFormatter"></el-table-column>
+      <el-table-column label="当前状态" prop="status" align="center">
+        <template #default="scope">
+          <dict-tag :options="ohplay_change_status" :value="scope.row.status" />
+        </template>
+      </el-table-column>
+      <el-table-column label="更新时间" prop="updateTime" align="center">
+        <template #default="scope">
+          <span>{{ parseTime(scope.row.updateTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
+        </template>
+      </el-table-column>
+    </el-table>
+    <pagination v-show="total > 0" :total="total" v-model:page="data.form.pageNum" v-model:limit="data.form.pageSize"
+      @pagination="getList" />
+  </div>
+</template>
+
+<script setup>
+import { list, options } from '@/api/content/ohplay.js'
+
+const { proxy } = getCurrentInstance();
+const { ohplay_change_status } = proxy.useDict("ohplay_change_status")
+
+// 遮罩层
+const loading = ref(false)
+
+const data = reactive({
+  // 表单
+  form: {
+    pageNum: 1,
+    pageSize: 10
+  },
+  // 列表
+  tableData: [],
+  // 资源平台
+  platformOptions: []
+})
+
+// 总数据
+const total = ref(0)
+
+// 列表
+function getList() {
+  loading.value = true
+  list(data.form).then(res => {
+    if (res.code === 0) {
+      data.tableData = res.data.records
+      total.value = res.data.total
+      loading.value = false
+    }
+  })
+}
+getList()
+
+// 搜索
+function getSearch() {
+  data.form.pageNum = 1
+  getList()
+}
+
+// 重置
+function getRefresh() {
+  data.form = {
+    pageNum: 1,
+    pageSize: 10
+  }
+  getList()
+}
+
+// 资源平台
+function getOptions() {
+  options({
+    audioType: 11
+  }).then(res => {
+    if (res.code === 0) {
+      res.data.forEach(i => {
+        data.platformOptions.push({
+          value: i.id,
+          label: i.name
+        })
+      })
+    }
+  })
+}
+getOptions()
+
+function platformFormatter(row) {
+  return proxy.selectDictLabel(data.platformOptions, row.platformId)
+}
+</script>

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

@@ -0,0 +1,165 @@
+<template>
+  <div class='app-container'>
+    <el-form class="form" label-width="100px" ref="form" :model="data.form" :rules="data.rules">
+      <el-form-item class="audioList" label="选择音频:">
+        <div class="audio">
+          <img src="@/assets/icons/svg/file.svg" width="70" height="70" />
+          <span>双十一活动</span>
+          <span>3小时21分</span>
+        </div>
+        <el-button icon="Plus" @click="getDialog" style="width: 100%">新增</el-button>
+      </el-form-item>
+      <el-form-item label="内容名称:">
+        <el-input v-model="data.form.name" placeholder="请输入内容名称" />
+      </el-form-item>
+      <el-form-item label="播放时间:">
+        <el-date-picker type="datetimerange" start-placeholder="开始时间" end-placeholder="结束时间"
+          format="YYYY-MM-DD HH:mm:ss" date-format="YYYY/MM/DD ddd" time-format="A hh:mm:ss" />
+        <el-button icon="Plus" style="width: 100%; margin-top: 15px">新增时段</el-button>
+      </el-form-item>
+      <el-form-item label="所属门店:" style="width: 800px">
+        <el-table :data="data.form.list">
+          <el-table-column label="所属" align="center">
+            <template #default="scope">
+              <el-select>
+                <!-- <el-option /> -->
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column label="所属门店" align="center">
+            <template #default="scope">
+              <el-select>
+                <!-- <el-option /> -->
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column label="所属设备" align="center">
+            <template #default="scope">
+              <el-select>
+                <!-- <el-option /> -->
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" align="center">
+            <template #default="scope">
+              <el-button type="danger" link>删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-form-item>
+      <el-form-item style="width: 800px">
+        <el-button icon="Plus" style="width: 100%">新增关联</el-button>
+      </el-form-item>
+    </el-form>
+    <div class="form-btn">
+      <el-button>取消</el-button>
+      <el-button type="primary">确定</el-button>
+    </div>
+
+    <el-dialog v-model="dialogVisible" title="导入内容">
+      <el-form inline>
+        <el-form-item label="内容分类:">
+          <el-select v-model="data.dialogForm.radio" 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 placeholder="请输入音频名称" />
+        </el-form-item>
+        <el-form-item label="分类:">
+          <el-select placeholder="请选择音频分类">
+            <!-- <el-option /> -->
+          </el-select>
+        </el-form-item>
+        <el-form-item label="当前状态:">
+          <el-select placeholder="请选择当前状态">
+            <!-- <el-option /> -->
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" icon="Plus">搜索</el-button>
+          <el-button icon="Refresh">重置</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"></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>
+const data = reactive({
+  form: {
+
+  },
+  rules: {},
+  radioOptions: [{
+    value: 1,
+    label: '播放内容'
+  }, {
+    value: 2,
+    label: 'Ohplay歌曲'
+  }, {
+    value: 3,
+    label: '上传新内容'
+  }],
+  dialogForm: {
+    radio: 1
+  }
+})
+
+// 弹窗
+const dialogVisible = ref(false)
+// 打开弹窗
+function getDialog() {
+  dialogVisible.value = true
+}
+</script>
+
+<style lang="scss" scoped>
+.form {
+  .el-form-item {
+    width: 500px;
+  }
+}
+
+.form-btn {
+  margin-left: 100px;
+}
+
+.audioList {
+  :deep(.el-form-item__content) {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-start;
+
+    .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;
+      line-height: 10px;
+      span{
+        margin-top: 20px;
+      }
+    }
+  }
+}
+</style>

+ 278 - 0
src/views/content/scene/index.vue

@@ -0,0 +1,278 @@
+<template>
+  <div class='app-container'>
+    <div class="left">
+      <el-button type="primary" icon="Plus" @click="getDialog()">新增场景</el-button>
+      <el-input class="search" v-model="data.form.takeName" placeholder="搜索场景名称" clearable>
+        <template #append>
+          <el-button icon="Search" @click="getSearch" />
+        </template>
+      </el-input>
+      <draggable class="contentList" v-model="data.tableData" item-key="id" chosenClass="chosenClass"
+        dragClass="dragClass" data-id="content" :group="{ name: 'componentGroup', pull: 'clone', put: false }"
+        :sort="false" :move="onMove" @end="onEnd" forceFallback v-loading="loading">
+        <template #item="{ element, index }">
+          <div class="item" @click="getDialog(element.takeId)">
+            <el-icon class="close" size="18" @click.stop="getDelete(element)">
+              <CircleClose />
+            </el-icon>
+            <img src="@/assets/icons/svg/file.svg" width="50" height="50" />
+            <span style="margin-top: 10px">{{ element.takeName }}</span>
+          </div>
+        </template>
+      </draggable>
+      <pagination v-show="total > 10" layout="prev, pager, next" :background="false" :total="total"
+        v-model:page="data.form.pageNum" v-model:limit="data.form.pageSize" @pagination="getList" />
+    </div>
+    <div class="right">
+      <el-form class="search" inline>
+        <el-form-item>
+          <el-select filterable placeholder="请选择门店" style="width: 200px" @change="getSearch">
+            <el-option v-for="item in businessOptions" :key="item.value" :value="item.value" :label="item.label" />
+          </el-select>
+        </el-form-item>
+        <el-form-item style="float:right">
+          <el-button type="primary" icon="Plus" @click="getRouter()">新增预设</el-button>
+        </el-form-item>
+      </el-form>
+      <div class="chart">
+        <GanttChart />
+      </div>
+    </div>
+
+    <!-- 弹窗 -->
+    <el-dialog v-model="dialogVisible" :title="title" width="500px" :before-close="getClose">
+      <el-form :model="data.dialogForm" ref="dialogForm" :rules="data.rules">
+        <el-form-item label="播放音频:" prop="list">
+          <CustomUpload v-if="title !== '编辑'" ref="customUpload" :url="`${baseUrl}/radio/tProgram/mp3/upload`" multiple
+            showFileList @upload="upload" />
+          <div v-else>
+            <div v-for="item in data.dialogForm.list" :key="item.id">{{ item.name }}</div>
+          </div>
+        </el-form-item>
+        <el-form-item label="场景名称:" prop="takeName">
+          <el-input v-model="data.dialogForm.takeName" placeholder="请输入场景名称" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="getClose">取消</el-button>
+        <el-button type="primary" @click="getSubmit">确定</el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { list, submit, detail, remove } from '@/api/content/scene'
+import GanttChart from '@/components/GanttChart/index.vue'
+import { useBusinessList } from '@/hooks/index'
+
+const { businessForm, businessOptions } = useBusinessList(true)
+
+const baseUrl = ref(import.meta.env.VITE_APP_BASE_API)
+const { proxy } = getCurrentInstance();
+
+// 遮罩层
+const loading = ref(false)
+
+const data = reactive({
+  // 表单
+  form: {
+    pageNum: 1,
+    pageSize: 10
+  },
+  // 列表
+  tableData: [],
+  // 弹窗表单
+  dialogForm: {},
+  // 校验
+  rules: {
+    list: [{
+      required: true, message: '请上传音频', trigger: 'change'
+    }],
+    takeName: [{
+      required: true, message: '请输入场景名称', trigger: 'blur'
+    }]
+  },
+  businessForm: {
+    pageNum: 1,
+    pageSize: 10
+  },
+  options: []
+})
+
+// 总数据
+const total = ref(0)
+
+// 列表
+function getList() {
+  loading.value = true
+  list(data.form).then(res => {
+    if (res.code === 0) {
+      data.tableData = res.data.records
+      total.value = res.data.total
+      loading.value = false
+    }
+  })
+}
+getList()
+// 搜索
+function getSearch() {
+  data.form.pageNum = 1
+  getList()
+}
+
+// 拖拽中
+function onMove(params) {
+  if (params.to.childElementCount < 1) {
+    return true
+  } else {
+    return false
+  }
+}
+// 拖拽结束
+function onEnd(params) {
+  if (params.from.className === 'contentList' &&
+    params.to.className === 'label_box' ||
+    params.from.className === 'label_box' &&
+    params.from.__draggable_component__.itemKey !== params.to.__draggable_component__.itemKey) {
+    let query = {
+      value: params.item._underlying_vm_.value,
+      label: params.item._underlying_vm_.label
+    }
+    getRouter(query)
+  }
+}
+
+// 弹窗
+const dialogVisible = ref(false)
+// 弹窗标题
+const title = ref('')
+// 打开弹窗
+function getDialog(id) {
+  dialogVisible.value = true
+  title.value = '新增'
+  if (id) {
+    getDetail(id)
+  }
+}
+// 详情
+function getDetail(id) {
+  title.value = '编辑'
+  detail({ id: id }).then(res => {
+    if (res.code === 0) {
+      data.dialogForm = res.data
+    }
+  })
+}
+// 上传音频
+function upload(file) {
+  data.dialogForm.list = file
+}
+// 提交
+function getSubmit() {
+  proxy.$refs.dialogForm.validate((valid) => {
+    if (valid) {
+      submit(data.dialogForm).then(res => {
+        if (res.code === 0) {
+          proxy.$modal.msgSuccess('提交成功!')
+          getClose()
+          getList()
+        }
+      })
+    } else {
+      return false
+    }
+  })
+}
+// 取消
+function getClose() {
+  dialogVisible.value = false
+  data.dialogForm = {}
+  proxy.$refs.dialogForm.resetFields()
+  if (title.value === '新增') {
+    proxy.$refs.customUpload.onRefresh()
+  }
+}
+// 删除
+function getDelete(row) {
+  proxy.$modal.confirm(`是否删除${row.takeName}`).then(() => {
+    remove(row.takeId).then(res => {
+      if (res.code === 0) {
+        proxy.$modal.msgSuccess('删除成功!')
+        getList()
+      }
+    })
+  }).catch(() => { })
+}
+
+// 新增预设
+function getRouter(query) {
+  proxy.$router.push({
+    path: `/content/scene/detail`,
+    query
+  })
+}
+</script>
+
+<style lang="scss" scoped>
+.app-container {
+  display: flex;
+}
+
+.left {
+  min-width: 400px;
+  position: relative;
+
+  .search {
+    margin: 15px 0;
+  }
+
+  .contentList {
+    display: flex;
+    flex-wrap: wrap;
+
+    .item {
+      width: 33.333333%;
+      display: flex;
+      flex-direction: column;
+      font-size: 12px;
+      align-items: center;
+      padding: 20px 0;
+      position: relative;
+
+      .close {
+        position: absolute;
+        right: 35px;
+        top: 15px;
+      }
+    }
+  }
+}
+
+.right {
+  display: flex;
+  flex-direction: column;
+  min-width: 700px;
+  width: calc(100% - 400px);
+  height: 792px;
+
+  .search {
+    padding-left: 70px;
+  }
+
+  .chart {
+    overflow-y: auto;
+    padding: 20px;
+    display: flex;
+  }
+}
+
+draggable,
+.label {
+  user-select: none;
+}
+
+.chosenClass {
+  background: none !important;
+}
+</style>

+ 180 - 0
src/views/content/setting/detail.vue

@@ -0,0 +1,180 @@
+<template>
+  <div class='app-container'>
+    <el-form class="form" label-width="100px" ref="form" :model="data.form" :rules="data.rules">
+      <el-form-item class="audioList" label="选择音频:">
+        <el-tag v-for="item in data.form.audioList" :key="item.audioId" size="large" closable>
+          {{ item.audioName }}
+        </el-tag>
+        <div class="audio">
+          <img src="@/assets/icons/svg/file.svg" width="70" height="70" />
+          <span>双十一活动</span>
+          <span>3小时21分</span>
+        </div>
+        <el-button icon="Plus" @click="getDialog" style="width: 100%">新增</el-button>
+      </el-form-item>
+      <el-form-item label="内容名称:">
+        <el-input v-model="data.form.name" placeholder="请输入内容名称" />
+      </el-form-item>
+      <el-form-item label="播放时间:">
+        <el-date-picker type="datetimerange" start-placeholder="开始时间" end-placeholder="结束时间"
+          format="YYYY-MM-DD HH:mm:ss" date-format="YYYY/MM/DD ddd" time-format="A hh:mm:ss" />
+        <el-button icon="Plus" style="width: 100%; margin-top: 15px">新增时段</el-button>
+      </el-form-item>
+      <el-form-item label="所属门店:" style="width: 800px">
+        <el-table :data="data.form.list">
+          <el-table-column label="所属" align="center">
+            <template #default="scope">
+              <el-select>
+                <!-- <el-option /> -->
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column label="所属门店" align="center">
+            <template #default="scope">
+              <el-select>
+                <!-- <el-option /> -->
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column label="所属设备" align="center">
+            <template #default="scope">
+              <el-select>
+                <!-- <el-option /> -->
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" align="center">
+            <template #default="scope">
+              <el-button type="danger" link>删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-form-item>
+      <el-form-item style="width: 800px">
+        <el-button icon="Plus" style="width: 100%">新增关联</el-button>
+      </el-form-item>
+    </el-form>
+    <div class="form-btn">
+      <el-button>取消</el-button>
+      <el-button type="primary">确定</el-button>
+    </div>
+
+    <el-dialog v-model="dialogVisible" title="导入内容">
+      <el-form inline>
+        <el-form-item label="内容分类:">
+          <el-select v-model="data.dialogForm.radio" 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 placeholder="请输入音频名称" />
+        </el-form-item>
+        <el-form-item label="分类:">
+          <el-select placeholder="请选择音频分类">
+            <!-- <el-option /> -->
+          </el-select>
+        </el-form-item>
+        <el-form-item label="当前状态:">
+          <el-select placeholder="请选择当前状态">
+            <!-- <el-option /> -->
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" icon="Plus">搜索</el-button>
+          <el-button icon="Refresh">重置</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"></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>
+const data = reactive({
+  form: {
+    audioList: [{
+      audioName: '测试111111111111111111'
+    }, {
+      audioName: '测试111111111111111111'
+    }, {
+      audioName: '测试111111111111111111'
+    }, {
+      audioName: '测试111111111111111111'
+    }]
+  },
+  rules: {},
+  radioOptions: [{
+    value: 1,
+    label: '播放内容'
+  }, {
+    value: 2,
+    label: 'Ohplay歌曲'
+  }, {
+    value: 3,
+    label: '上传新内容'
+  }],
+  dialogForm: {
+    radio: 1
+  }
+})
+
+// 弹窗
+const dialogVisible = ref(false)
+// 打开弹窗
+function getDialog() {
+  dialogVisible.value = true
+}
+</script>
+
+<style lang="scss" scoped>
+.form {
+  .el-form-item {
+    width: 500px;
+  }
+}
+
+.form-btn {
+  margin-left: 100px;
+}
+
+.audioList {
+  :deep(.el-form-item__content) {
+    display: flex;
+    flex-direction: column;
+    align-items: flex-start;
+
+    .el-tag {
+      margin-bottom: 15px;
+    }
+
+    .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;
+      line-height: 10px;
+      span{
+        margin-top: 20px;
+      }
+    }
+  }
+}
+</style>

+ 47 - 154
src/views/content/setting/index.vue

@@ -2,7 +2,7 @@
   <div class='app-container'>
     <el-row style="height: 100%;">
       <el-col :span="6" class="left">
-        <el-calendar ref="calendar">
+        <el-calendar ref="calendar" @click="getDate">
           <template #header="{ date }">
             <span>{{ date }}</span>
             <el-button link icon="ArrowLeftBold" @click="selectDate('prev-month')" />
@@ -14,9 +14,9 @@
           <el-tabs v-model="activeName">
             <el-tab-pane label="内容列表" name="first">
               <el-scrollbar :height="270">
-                <draggable class="contentList" v-model="data.contentList" item-key="value" chosen-class="chosen"
+                <draggable class="contentList" v-model="data.contentList" item-key="id" chosen-class="chosen"
                   data-id="content" :group="{ name: 'componentGroup', pull: 'clone', put: false }" :sort="false"
-                  @end="handleChangeEnd">
+                  :move="onMove" @end="onEnd">
                   <template #item="{ element, index }">
                     <span class="item">
                       <el-icon>
@@ -34,96 +34,34 @@
         </div>
       </el-col>
       <el-col :span="18" class="right">
-        <div class="search">
-          <el-input placeholder="搜索" suffix-icon="Search" style="width: 200px; margin-right: 20px" />
-          <el-button type="primary" icon="Plus" @click="getDialog">新增</el-button>
-        </div>
+        <el-form class="search" inline>
+          <el-form-item>
+            <el-select placeholder="请选择门店" style="width: 200px">
+              <!-- <el-option /> -->
+            </el-select>
+          </el-form-item>
+          <el-form-item style="float:right">
+            <el-button type="primary" icon="Plus" @click="getDetail">新增</el-button>
+          </el-form-item>
+        </el-form>
         <div class="chart">
-          <div class="timer">
-            <div class="item" v-for="item in data.timer" :key="item">
-              <div class="value">
-                <span>{{ item.value }}</span>
-                <span class="solid"></span>
-              </div>
-              <draggable class="label_box" v-model="item.list" group="componentGroup" item-key="value" data-id="timer"
-                @end="handleChangeEnd">
-                <template #item="{ element, index }">
-                  <span class="label">{{ element.label }}</span>
-                </template>
-              </draggable>
-            </div>
-          </div>
+          <gantt-chart />
         </div>
       </el-col>
     </el-row>
-
-    <el-dialog v-model="dialogVisible" title="新增" width="500" :before-close="beforeClose">
-      <el-form label-width="100px" ref="dialogForm" :model="data.dialogForm" :rules="data.rules">
-        <el-form-item>
-          <el-radio-group v-model="data.dialogForm.radio" :disabled="draggableActive">
-            <el-radio v-for="item in data.radioOptions" :key="item.value" :label="item.value">
-              {{ item.label }}
-            </el-radio>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="选择内容:">
-          <el-input v-model="data.dialogForm.contentName" placeholder="选择内容" prefix-icon="Search" :disabled="draggableActive" />
-        </el-form-item>
-        <el-form-item label="内容名称:">
-          <el-input v-model="data.dialogForm.name" placeholder="请输入内容名称" />
-        </el-form-item>
-        <el-form-item label="所属门店:">
-          <el-select>
-            <!-- <el-option /> -->
-          </el-select>
-        </el-form-item>
-        <el-form-item label="选择设备:">
-          <el-select>
-            <!-- <el-option /> -->
-          </el-select>
-        </el-form-item>
-        <el-form-item label="播放时间:">
-          <el-date-picker type="datetimerange" start-placeholder="开始时间" end-placeholder="结束时间"
-            format="YYYY-MM-DD HH:mm:ss" date-format="YYYY/MM/DD ddd" time-format="A hh:mm:ss" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <el-button>取消</el-button>
-        <el-button type="primary">确定</el-button>
-      </template>
-    </el-dialog>
   </div>
 </template>
 
 <script setup>
+import GanttChart from '@/components/GanttChart'
+
 const { proxy } = getCurrentInstance();
 
 const data = reactive({
   contentList: [
     { value: 1123123, label: '你就不要想起我' }, { value: 2124123124, label: '双11活动' }
   ],
-  timer: [
-    { value: '23:00', list: [{ value: 1, label: '双十一' }, { value: 2, label: '三八女神节' }] }, { value: '22:00', list: [{ value: 1, label: '双十一' }] }, { value: '21:00', list: [] }, { value: '20:00', list: [] },
-    { value: '19:00', list: [] }, { value: '18:00', list: [] }, { value: '17:00', list: [] }, { value: '16:00', list: [] },
-    { value: '15:00', list: [] }, { value: '14:00', list: [] }, { value: '13:00', list: [] }, { value: '12:00', list: [] },
-    { value: '11:00', list: [] }, { value: '10:00', list: [] }, { value: '09:00', list: [] }, { value: '08:00', list: [] },
-    { value: '07:00', list: [] }, { value: '06:00', list: [] }, { value: '05:00', list: [] }, { value: '04:00', list: [] },
-    { value: '03:00', list: [] }, { value: '02:00', list: [] }, { value: '01:00', list: [] }, { value: '00:00', list: [] }
-  ],
-  radioOptions: [{
-    value: 1,
-    label: '播放内容'
-  }, {
-    value: 2,
-    label: 'Ohplay歌曲'
-  }, {
-    value: 3,
-    label: '上传新内容'
-  }],
-  dialogForm: {
-    radio: 1,
-    name: '测试'
-  }
+
 })
 
 const activeName = ref("first")
@@ -135,34 +73,41 @@ function selectDate(val) {
   calendar.value.selectDate(val)
 }
 
-// 弹窗
-const dialogVisible = ref(false)
+function getDate(e) {
+  console.log(e._vts);
+  console.log(new Date().getTime());
+}
 
-// 拖拽新增禁止选择
-const draggableActive = ref(false)
 // 拖拽内容
-function handleChangeEnd(params) {
-  let e = {
-    value: params.item._underlying_vm_.value,
-    label: params.item._underlying_vm_.label
+function onMove(params) {
+  console.log(params);
+  if (params.to.childElementCount < 1) {
+    return true
+  } else {
+    return false
   }
-  draggableActive.value = true
-  dialogVisible.value = true
-  data.dialogForm.contentId = e.value
-  data.dialogForm.contentName = e.label
 }
 
-// 弹窗
-function getDialog() {
-  dialogVisible.value = true
+// 拖拽结束
+function onEnd(params) {
+  if (params.from.className === 'contentList' &&
+    params.to.className === 'label_box' ||
+    params.from.className === 'label_box' &&
+    params.from.__draggable_component__.itemKey !== params.to.__draggable_component__.itemKey) {
+    let query = {
+      value: params.item._underlying_vm_.value,
+      label: params.item._underlying_vm_.label
+    }
+    getDetail(query)
+  }
 }
 
-// 关闭弹窗
-function beforeClose(){
-  dialogVisible.value = false
-  draggableActive.value = false
-  data.dialogForm = {}
-  proxy.resetForm('dialogForm')
+// 新增
+function getDetail(query) {
+  proxy.$router.push({
+    path: `/content/setting/detail`,
+    query
+  })
 }
 
 </script>
@@ -208,65 +153,13 @@ function beforeClose(){
   height: 792px;
 
   .search {
-    display: flex;
-    justify-content: flex-end;
+    padding-left: 70px;
   }
 
   .chart {
     overflow-y: auto;
     padding: 20px;
     display: flex;
-
-    .timer {
-      display: flex;
-      flex-direction: column;
-      width: calc(100% - 50px);
-      margin-left: 50px;
-
-      .item {
-        width: 100%;
-        height: 100px;
-        line-height: 100px;
-        position: relative;
-        border-left: 1px solid #e3e3e3;
-        display: flex;
-        align-items: center;
-
-        .value {
-          margin-left: -50px;
-          width: 50px;
-
-          .solid {
-            border-top: 1px solid #e3e3e3;
-            width: 100%;
-            position: absolute;
-            top: 50px;
-            left: 0;
-          }
-        }
-
-        .label_box {
-          display: flex;
-          width: 100%;
-          z-index: 99;
-
-          .label {
-            background-color: #ebf1fe;
-            color: #3979F9;
-            height: 60px;
-            display: flex;
-            justify-content: center;
-            align-items: center;
-            border-left: 4px solid #3979F9;
-            border-radius: 4px;
-            margin-right: 10px;
-            font-size: 12px;
-            padding: 0 20px;
-            flex: 1;
-          }
-        }
-      }
-    }
   }
 }
 
@@ -282,6 +175,6 @@ draggable,
 .chosen {
   flex: 1;
   height: 60px !important;
-  margin-right: 10px;
+  line-height: 60px;
 }
 </style>

+ 1 - 1
src/views/device/class/index.vue

@@ -2,7 +2,7 @@
   <div class='app-container'>
     <el-form>
       <el-form-item>
-        <el-button type="primary" icon="Plus" plain @click="getDialog">新增分类</el-button>
+        <el-button type="primary" icon="Plus" plain @click="getDialog">新增</el-button>
       </el-form-item>
     </el-form>
     <!-- 列表 -->

+ 0 - 210
src/views/device/control/devices.vue

@@ -1,210 +0,0 @@
-<template>
-  <div class="tab">
-    <!-- 分类筛选 -->
-    <el-tabs v-model="activeName" style="width: 100%;">
-      <el-tab-pane v-for="item in data.tabOptions" :key="item.value" :label="item.label" :name="item.value"
-        v-loading="loading">
-        <!-- 列表 -->
-        <div class="card" v-for="item in data.tableData" :key="item">
-          <div class="card-header">
-            <i class="state" />
-            <el-dropdown>
-              <el-icon>
-                <MoreFilled />
-              </el-icon>
-              <template #dropdown>
-                <el-dropdown-menu>
-                  <el-dropdown-item>查看</el-dropdown-item>
-                  <el-dropdown-item>编辑</el-dropdown-item>
-                  <el-dropdown-item>删除</el-dropdown-item>
-                  <el-dropdown-item>上架</el-dropdown-item>
-                  <el-dropdown-item>下架</el-dropdown-item>
-                </el-dropdown-menu>
-              </template>
-            </el-dropdown>
-          </div>
-          <el-image class="icon" src="" />
-          <span class="name">猫王音响·Mate X1</span>
-        </div>
-      </el-tab-pane>
-      <pagination v-show="total > 0" :total="total" v-model:page="data.form.pageNum" v-model:limit="data.form.pageSize"
-        @pagination="getList" />
-    </el-tabs>
-
-    <!-- 下拉筛选 -->
-    <div class="dropdown">
-      <el-dropdown v-for="item in data.selectOptions" :key="item.value">
-        <span>{{ item.label }}<el-icon><arrow-down /></el-icon></span>
-        <template #dropdown>
-          <el-dropdown-menu>
-            <el-dropdown-item v-for="item in 4" :key="item">{{ item }}</el-dropdown-item>
-          </el-dropdown-menu>
-        </template>
-      </el-dropdown>
-    </div>
-
-    <!-- 搜索框 + 新增按钮 -->
-    <div class="flex-right">
-      <el-input placeholder="搜索设备名称" suffix-icon="Search" />
-      <el-button type="primary" icon="Plus" plain @click="getDialog">新增设备</el-button>
-    </div>
-
-    <!-- 新增弹窗 -->
-    <el-dialog v-model="dialogVisible" :title="title" width="500" :before-close="close">
-      <el-form label-width="100px">
-        <el-form-item label="设备型号:">
-          <el-input placeholder="请输入设备型号" />
-        </el-form-item>
-        <el-form-item label="设备序列号:">
-          <el-input placeholder="请输入设备序列号" />
-        </el-form-item>
-        <el-form-item label="设备名称:">
-          <el-input placeholder="请输入设备名称" />
-        </el-form-item>
-        <el-form-item label="设备分类:">
-          <el-select placeholder="请选择设备分类">
-            <!-- <el-option /> -->
-          </el-select>
-        </el-form-item>
-        <el-form-item label="所属门店:">
-          <el-select placeholder="请选择所属门店">
-            <!-- <el-option /> -->
-          </el-select>
-        </el-form-item>
-        <el-form-item label="所在城市:">
-          <el-select placeholder="请选择所在城市">
-            <!-- <el-option /> -->
-          </el-select>
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <el-button @click="close">取消</el-button>
-        <el-button type="primary">确定</el-button>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup>
-// 遮罩层
-const loading = ref(false)
-
-const data = reactive({
-  tabOptions: [
-    { value: '1', label: '全部' },
-    { value: '2', label: '在线' },
-    { value: '3', label: '离线' }
-  ],
-  selectOptions: [
-    { value: '4', label: '门店' },
-    { value: '5', label: '设备类型' },
-    { value: '6', label: '所属地区' }
-  ],
-  // 数据表单
-  form: {
-    pageNum: 1,
-    pageSize: 10
-  },
-  // 数据列表
-  tableData: []
-})
-
-// 焦点tab
-const activeName = ref('1')
-
-// 总数据
-const total = ref(0)
-
-// 列表
-function getList() {
-
-}
-getList()
-
-// 弹窗
-const dialogVisible = ref(false)
-const title = ref('新增')
-
-// 打开弹窗
-function getDialog() {
-  dialogVisible.value = true
-}
-
-// 关闭弹窗
-function close() {
-  dialogVisible.value = false
-}
-
-</script>
-
-<style lang="scss" scoped>
-.tab {
-  display: flex;
-
-  .el-tab-pane {
-    display: flex;
-    flex-wrap: wrap;
-    padding: 10px;
-    min-height: 200px;
-
-    .card {
-      display: flex;
-      flex-direction: column;
-      padding: 10px 10px 20px;
-      width: 185px;
-      border-radius: 10px;
-      box-shadow: 0px 0px 12px rgba(0, 0, 0, .12);
-      margin-right: 40px;
-      margin-bottom: 30px;
-
-      .card-header {
-        display: flex;
-        justify-content: space-between;
-        align-items: center;
-
-        .state {
-          width: 10px;
-          height: 10px;
-          background-color: #8aff5b;
-          border-radius: 50%;
-          display: inline-block;
-        }
-      }
-
-      .icon {
-        padding: 0 20px;
-        height: 110px;
-        margin: 15px 0;
-      }
-
-      .name {
-        font-size: 14px;
-        text-align: center;
-      }
-    }
-  }
-
-  .dropdown {
-    position: absolute;
-    left: 164px;
-
-    .el-dropdown {
-      margin-left: 40px;
-      height: 42px;
-      line-height: 42px;
-    }
-  }
-}
-
-.flex-right {
-  position: absolute;
-  right: 20px;
-  top: 20px;
-  transform: translate(0, -50%);
-  display: flex;
-
-  .el-input {
-    margin-right: 20px;
-  }
-}
-</style>

+ 167 - 16
src/views/device/control/index.vue

@@ -1,23 +1,174 @@
 <template>
   <div class='app-container'>
-    <el-tabs v-model="activeName">
-      <el-tab-pane label="全部设备" name="first">
-        <keep-alive>
-          <Devices />
-        </keep-alive>
-      </el-tab-pane>
-      <el-tab-pane label="门店列表" name="second">
-        <keep-alive>
-          <Store />
-        </keep-alive>
-      </el-tab-pane>
-    </el-tabs>
+    <el-form inline>
+      <el-form-item label="设备名称:">
+        <el-input placeholder="请输入设备名称" />
+      </el-form-item>
+      <el-form-item label="设备分类:">
+        <el-select placeholder="请选择设备分类">
+          <el-option />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="所属门店:">
+        <el-select placeholder="请选择门店">
+          <el-option />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="所属城市:">
+        <el-select placeholder="请选择所属城市">
+          <el-option />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="当前状态:">
+        <el-select placeholder="请选择当前状态">
+          <el-option />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="Search">搜索</el-button>
+        <el-button icon="Refresh">重置</el-button>
+        <el-button type="primary" plain icon="Plus" @click="getDialog()">关联设备</el-button>
+      </el-form-item>
+      <el-form-item style="float: right">
+        <el-button icon="Expand" @click="grid = false" />
+        <el-button icon="Grid" @click="grid = true" />
+      </el-form-item>
+    </el-form>
+    <!-- 列表 -->
+    <el-table v-if="!grid" :data="tableData" v-loading="loading">
+      <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"></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>
+          <el-button type="primary" link>上架</el-button>
+          <el-button type="primary" link>下架</el-button>
+          <el-button type="danger" link>删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <div v-else class="card" v-for="item in data.tableData" :key="item">
+      <div class="card-header">
+        <i class="state" />
+        <el-dropdown>
+          <el-icon>
+            <MoreFilled />
+          </el-icon>
+          <template #dropdown>
+            <el-dropdown-menu>
+              <el-dropdown-item>查看</el-dropdown-item>
+              <el-dropdown-item>编辑</el-dropdown-item>
+              <el-dropdown-item>删除</el-dropdown-item>
+              <el-dropdown-item>上架</el-dropdown-item>
+              <el-dropdown-item>下架</el-dropdown-item>
+            </el-dropdown-menu>
+          </template>
+        </el-dropdown>
+      </div>
+      <el-image class="icon" src="" />
+      <span class="name">猫王音响·Mate X1</span>
+    </div>
+    <!-- 弹窗 -->
+    <el-dialog v-model="dialogVisible" :title="title" width="500" :before-close="close">
+      <el-form label-width="100px">
+        <el-form-item label="设备型号:">
+          <el-input placeholder="请输入设备型号" />
+        </el-form-item>
+        <el-form-item label="设备序列号:">
+          <el-input placeholder="请输入设备序列号" />
+        </el-form-item>
+        <el-form-item label="设备名称:">
+          <el-input placeholder="请输入设备名称" />
+        </el-form-item>
+        <el-form-item label="设备分类:">
+          <el-select placeholder="请选择设备分类">
+            <!-- <el-option /> -->
+          </el-select>
+        </el-form-item>
+        <el-form-item label="所属门店:">
+          <el-select placeholder="请选择所属门店">
+            <!-- <el-option /> -->
+          </el-select>
+        </el-form-item>
+        <el-form-item label="所在城市:">
+          <el-select placeholder="请选择所在城市">
+            <!-- <el-option /> -->
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="close">取消</el-button>
+        <el-button type="primary">确定</el-button>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
 <script setup>
-import Devices from './devices.vue'
-import Store from './store.vue'
+// 遮罩层
+const loading = ref(false)
 
-const activeName = ref('first')
-</script>
+const data = reactive({
+  // 表单
+  form: {},
+  // 列表
+  tableData: [{}],
+  // 弹窗表单
+  dialogForm: {}
+})
+
+const grid = ref(false)
+
+// 弹窗
+const dialogVisible = ref(false)
+// 弹窗标题
+const title = ref('')
+// 打开弹窗
+function getDialog() {
+  dialogVisible.value = true
+  title.value = '关联'
+}
+</script>
+
+<style lang="scss" scoped>
+.card {
+  display: flex;
+  flex-direction: column;
+  padding: 10px 10px 20px;
+  width: 185px;
+  border-radius: 10px;
+  box-shadow: 0px 0px 12px rgba(0, 0, 0, .12);
+  margin-right: 40px;
+  margin-bottom: 30px;
+
+  .card-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+
+    .state {
+      width: 10px;
+      height: 10px;
+      background-color: #8aff5b;
+      border-radius: 50%;
+      display: inline-block;
+    }
+  }
+
+  .icon {
+    padding: 0 20px;
+    height: 110px;
+    margin: 15px 0;
+  }
+
+  .name {
+    font-size: 14px;
+    text-align: center;
+  }
+}
+</style>

+ 0 - 139
src/views/device/control/store.vue

@@ -1,139 +0,0 @@
-<template>
-  <div class='tab'>
-    <!-- 下拉筛选 -->
-    <div class="dropdown">
-      <el-dropdown v-for="item in data.selectOptions" :key="item.value">
-        <span>{{ item.label }}<el-icon><arrow-down /></el-icon></span>
-        <template #dropdown>
-          <el-dropdown-menu>
-            <el-dropdown-item v-for="item in 4" :key="item">{{ item }}</el-dropdown-item>
-          </el-dropdown-menu>
-        </template>
-      </el-dropdown>
-    </div>
-
-    <!-- 搜索框 + 新增按钮 -->
-    <div class="flex-right">
-      <el-input placeholder="搜索门店名称或门店编码" suffix-icon="Search" />
-      <el-button @click="getDetail">门店分组</el-button>
-      <el-button type="primary" icon="Plus" plain @click="getDialog">新增门店</el-button>
-    </div>
-
-    <!-- 列表 -->
-    <div class="list">
-      <div class="item" v-for="item in data.list" :key="item.value">
-        <span>瑞幸咖啡(高新南三道中科大厦)</span>
-        <span>门店编码:110022</span>
-        <span>广东省-深圳市-南山区</span>
-      </div>
-    </div>
-
-    <!-- 弹窗 -->
-    <el-dialog v-model="dialogVisible" :title="title" width="500" :before-close="close">
-      <el-form label-width="100px">
-        <el-form-item label="门店名称:">
-          <el-input placeholder="请输入门店名称" />
-        </el-form-item>
-        <el-form-item label="门店编码:">
-          <el-input placeholder="请输入门店编码" />
-        </el-form-item>
-        <el-form-item label="归属账号:">
-          <el-select placeholder="请选择归属账号">
-            <!-- <el-option /> -->
-          </el-select>
-        </el-form-item>
-        <el-form-item label="上级组织:">
-          <el-select placeholder="请选择上级组织">
-            <!-- <el-option /> -->
-          </el-select>
-        </el-form-item>
-        <el-form-item label="所在城市:">
-          <el-select placeholder="请选择所在城市">
-            <!-- <el-option /> -->
-          </el-select>
-        </el-form-item>
-        <el-form-item label="门店分组:">
-          <el-select placeholder="请选择门店分组">
-            <!-- <el-option /> -->
-          </el-select>
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <el-button @click="close">取消</el-button>
-        <el-button type="primary">确定</el-button>
-      </template>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup>
-let { proxy } = getCurrentInstance();
-
-const data = reactive({
-  selectOptions: [
-    { value: 1, label: '组织架构' },
-    { value: 2, label: '分组' }
-  ],
-  list: [{}, {}, {}, {}, {}, {}]
-})
-
-// 弹窗
-const dialogVisible = ref(false)
-const title = ref('新增')
-
-function getDialog() {
-  dialogVisible.value = true
-}
-
-function close() {
-  dialogVisible.value = false
-}
-
-function getDetail() {
-  proxy.$router.push({
-    path: '/device/control/storeGrouping'
-  })
-}
-</script>
-
-<style lang="scss" scoped>
-.el-dropdown {
-  margin-right: 40px;
-  line-height: 42px;
-}
-
-.flex-right {
-  position: absolute;
-  right: 20px;
-  top: 20px;
-  transform: translate(0, -50%);
-  display: flex;
-
-  .el-input {
-    margin-right: 20px;
-  }
-}
-
-.list {
-  display: flex;
-  flex-wrap: wrap;
-  margin-top: 20px;
-  
-  .item{
-    width: 300px;
-    height: 120px;
-    background-color: #fdfdfd;
-    border-left: 3px solid #409EFF;
-    border-top: 1px solid #e5e5e5;
-    border-right: 1px solid #e5e5e5;
-    border-bottom: 1px solid #e5e5e5;
-    display: flex;
-    flex-direction: column;
-    justify-content: space-around;
-    padding: 10px 20px;
-    font-size: 14px;
-    margin-right: 80px;
-    margin-bottom: 40px;
-  }
-}
-</style>

+ 5 - 5
src/views/device/control/storeGrouping.vue

@@ -1,9 +1,10 @@
 <template>
   <div class='app-container'>
-    <div class="header">
-      <el-page-header @back="goBack" />
-      <el-button type="primary" icon="Plus" plain @click="getDialog">新增分组</el-button>
-    </div>
+    <el-form>
+      <el-form-item>
+        <el-button type="primary" icon="Plus" plain @click="getDialog">新增分组</el-button>
+      </el-form-item>
+    </el-form>
     <el-table :data="tableData" v-loading="loading">
       <el-table-column label="分组名称" align="center"></el-table-column>
       <el-table-column label="相关设备" align="center"></el-table-column>
@@ -14,7 +15,6 @@
         </template>
       </el-table-column>
     </el-table>
-
     <!-- 弹窗 -->
     <el-dialog v-model="dialogVisible" :title="title" width="500">
       <el-form>

+ 102 - 0
src/views/device/store/index.vue

@@ -0,0 +1,102 @@
+<template>
+  <div class='app-container'>
+    <el-form inline>
+      <el-form-item label="门店名称:">
+        <el-input placeholder="请输入门店名称" />
+      </el-form-item>
+      <el-form-item label="门店编码:">
+        <el-input placeholder="请输入门店编码" />
+      </el-form-item>
+      <el-form-item label="门店分组:">
+        <el-select placeholder="请选择门店分组">
+          <!-- <el-option /> -->
+        </el-select>
+      </el-form-item>
+      <el-form-item label="组织架构:">
+        <el-select placeholder="请选择组织架构">
+          <!-- <el-option /> -->
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="Search">搜索</el-button>
+        <el-button icon="Refresh">重置</el-button>
+        <el-button type="primary" plain icon="Plus" @click="getDialog()">新增</el-button>
+      </el-form-item>
+    </el-form>
+    <!-- 列表 -->
+    <el-table :data="data.tableData" v-loading="loading">
+      <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>编辑</el-button>
+          <el-button>删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 弹窗 -->
+    <el-dialog v-model="dialogVisible" :title="title" width="500">
+      <el-form label-width="100px">
+        <el-form-item label="门店名称:">
+          <el-input placeholder="请输入门店名称" />
+        </el-form-item>
+        <el-form-item label="门店编码:">
+          <el-input placeholder="请输入门店编码" />
+        </el-form-item>
+        <el-form-item label="归属账号:">
+          <el-select placeholder="请选择归属账号">
+            <!-- <el-option /> -->
+          </el-select>
+        </el-form-item>
+        <el-form-item label="上级组织:">
+          <el-select placeholder="请选择上级组织">
+            <!-- <el-option /> -->
+          </el-select>
+        </el-form-item>
+        <el-form-item label="所在城市:">
+          <el-select placeholder="请选择所在城市">
+            <!-- <el-option /> -->
+          </el-select>
+        </el-form-item>
+        <el-form-item label="门店分组:">
+          <el-select placeholder="请选择门店分组">
+            <!-- <el-option /> -->
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button>取消</el-button>
+        <el-button type="primary">确定</el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+// 遮罩层
+const loading = ref(false)
+
+const data = reactive({
+  // 表单
+  form: {
+    pageNum: 1,
+    pageSize: 10
+  },
+  // 列表
+  tableData: [],
+  // 弹窗表单
+  dialogForm: {}
+})
+
+// 弹窗
+const dialogVisible = ref(false)
+// 弹窗标题
+const title = ref('')
+// 打开弹窗
+function getDialog() {
+  dialogVisible.value = true
+  title.value = '新增'
+}
+
+</script>

+ 2 - 2
src/views/login.vue

@@ -52,8 +52,8 @@ const router = useRouter();
 const { proxy } = getCurrentInstance();
 
 const loginForm = ref({
-  username: "admin",
-  password: "admin123",
+  username: "",
+  password: "",
   rememberMe: false,
   code: "",
   uuid: ""

+ 1 - 1
src/views/system/user/profile/userAvatar.vue

@@ -114,7 +114,7 @@ function uploadImg() {
     formData.append("avatarfile", data, options.filename);
     uploadAvatar(formData).then(response => {
       open.value = false;
-      options.img = import.meta.env.VITE_APP_BASE_API + response.imgUrl;
+      options.img = response.imgUrl;
       userStore.avatar = options.img;
       proxy.$modal.msgSuccess("修改成功");
       visible.value = false;