Browse Source

上传文件修改

tangning 3 years ago
parent
commit
bc78ad46c2

+ 5 - 0
config/enprod.js

@@ -0,0 +1,5 @@
+'use strict'
+module.exports = {
+  NODE_ENV: '"production"',
+  GJEDITION: '"international"' //domestic 国内  international 国际版
+}

+ 1 - 1
config/prod.env.js

@@ -1,5 +1,5 @@
 'use strict'
 module.exports = {
   NODE_ENV: '"production"',
-  GJEDITION: '"international"' //domestic 国内  international 国际版
+  GJEDITION: '"domestic"' //domestic 国内  international 国际版
 }

+ 47 - 2
package-lock.json

@@ -80,6 +80,37 @@
         "js-tokens": "^3.0.0"
       }
     },
+    "@babel/runtime": {
+      "version": "7.18.3",
+      "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.18.3.tgz",
+      "integrity": "sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug==",
+      "requires": {
+        "regenerator-runtime": "^0.13.4"
+      },
+      "dependencies": {
+        "regenerator-runtime": {
+          "version": "0.13.9",
+          "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
+          "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
+        }
+      }
+    },
+    "@babel/runtime-corejs3": {
+      "version": "7.18.3",
+      "resolved": "https://registry.npmmirror.com/@babel/runtime-corejs3/-/runtime-corejs3-7.18.3.tgz",
+      "integrity": "sha512-l4ddFwrc9rnR+EJsHsh+TJ4A35YqQz/UqcjtlX2ov53hlJYG5CxtQmNZxyajwDVmCxwy++rtvGU5HazCK4W41Q==",
+      "requires": {
+        "core-js-pure": "^3.20.2",
+        "regenerator-runtime": "^0.13.4"
+      },
+      "dependencies": {
+        "regenerator-runtime": {
+          "version": "0.13.9",
+          "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
+          "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
+        }
+      }
+    },
     "@babel/template": {
       "version": "7.0.0-beta.44",
       "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.44.tgz",
@@ -3181,6 +3212,11 @@
       "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
       "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
     },
+    "core-js-pure": {
+      "version": "3.23.2",
+      "resolved": "https://registry.npmmirror.com/core-js-pure/-/core-js-pure-3.23.2.tgz",
+      "integrity": "sha512-t6u7H4Ff/yZNk+zqTr74UjCcZ3k8ApBryeLLV4rYQd9aF3gqmjjGjjR44ENfeBMH8VVvSynIjAJ0mUuFhzQtrA=="
+    },
     "core-util-is": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
@@ -14995,8 +15031,7 @@
     "tslib": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
-      "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
-      "dev": true
+      "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
     },
     "tty-browserify": {
       "version": "0.0.0",
@@ -15565,6 +15600,16 @@
         "makeerror": "1.0.x"
       }
     },
+    "wangeditor": {
+      "version": "4.7.15",
+      "resolved": "https://registry.npmmirror.com/wangeditor/-/wangeditor-4.7.15.tgz",
+      "integrity": "sha512-aPTdREd8BxXVyJ5MI+LU83FQ7u1EPd341iXIorRNYSOvoimNoZ4nPg+yn3FGbB93/owEa6buLw8wdhYnMCJQLg==",
+      "requires": {
+        "@babel/runtime": "^7.11.2",
+        "@babel/runtime-corejs3": "^7.11.2",
+        "tslib": "^2.1.0"
+      }
+    },
     "watch": {
       "version": "0.18.0",
       "resolved": "https://registry.npmjs.org/watch/-/watch-0.18.0.tgz",

+ 4 - 2
package.json

@@ -11,7 +11,8 @@
     "e2e": "node test/e2e/runner.js",
     "test": "npm run unit && npm run e2e",
     "lint": "eslint --ext .js,.vue src test/unit test/e2e/specs",
-    "build": "node build/build.js"
+    "build": "node build/build.js",
+    "build:en": "cross-env env_config=enprod node build/build.js"
   },
   "dependencies": {
     "axios": "^0.19.0",
@@ -20,7 +21,8 @@
     "js-base64": "^2.5.2",
     "moment": "^2.29.1",
     "vue": "^2.5.2",
-    "vue-router": "^3.0.1"
+    "vue-router": "^3.0.1",
+    "wangeditor": "^4.7.15"
   },
   "devDependencies": {
     "autoprefixer": "^7.1.2",

+ 129 - 0
src/page/case/EditorBar.vue

@@ -0,0 +1,129 @@
+<template>
+  <div ref="editor"></div>
+</template>
+
+<script>
+import E from "wangeditor";
+export default {
+  props: {
+    value: {
+      type: String,
+      default: "",
+    },
+    meanArray: {
+      // 自定义菜单
+      type: Array,
+      default: null,
+    },
+  },
+  model: {
+    prop: "value",
+    event: "change",
+  },
+  watch: {
+    value: {
+      handler(value, oldName) {
+          console.log('editor',value, oldName)
+        if (value !== oldName) {
+            this.editor&&this.editor.txt.html(this.value);
+        }
+      },
+      immediate: true,
+      deep:true,
+    },
+    // value为编辑框输入的内容,这里我监听了一下值,当父组件调用得时候,如果给value赋值了,子组件将会显示父组件赋给的值
+  },
+  data() {
+    return {
+      // 默认有这么多菜单,meanArray有值以meanArray为准
+      uploadUrl: this.$server + '/article/uploadImage',
+      defaultMeanus: [
+        "head",
+        "bold",
+        "fontSize",
+        "fontName",
+        "italic",
+        "underline",
+        "strikeThrough",
+        "indent",
+        "lineHeight",
+        "foreColor",
+        "backColor",
+        "link",
+        "list",
+        "justify",
+        "quote",
+        "emoticon",
+        "image",
+        "video",
+        "table",
+        "code",
+        "splitLine",
+        "undo",
+        "redo",
+      ],
+      editor: "",
+    };
+  },
+  methods: {
+    init() {
+      const _this = this;
+      const uploadUrl =  this.uploadUrl
+      this.editor = new E(this.$refs.editor);
+    //   this.editor.config.uploadImgShowBase64 = true; // 使用 base64 保存图片
+    //   this.editor.config.debugInfo = false; //关闭网络路径图片方式
+      this.editor.config.uploadImgServer = uploadUrl; // 上传图片的接口地址
+      this.editor.config.uploadFileName = "file"; // formdata中的name属性
+      this.editor.config.uploadImgHeaders = {
+        token: sessionStorage.getItem('token') // 设置请求头
+     }
+     this.editor.config.uploadImgHooks = {
+            customInsert: function (insertImg, result, editor) {
+            // 图片上传并返回结果,自定义插入图片的事件(而不是编辑器自动插入图片!!!)
+            // insertImg 是插入图片的函数,editor 是编辑器对象,result 是服务器端返回的结果
+            // 举例:假如上传图片成功后,服务器端返回的是 {url:'....'} 这种格式,即可这样插入图片:
+            var url =result.msg;
+            insertImg(url);
+            // result 必须是一个 JSON 格式字符串!!!否则报错
+        }
+        // 图片上传并返回结果,但图片插入错误时触发
+        // fail: function (xhr, editor, result) {
+        //     console.log(result)
+        // },
+        // success: function (xhr, editor, result) {
+        //     // 图片上传并返回结果,图片插入成功之后触发
+        //     editor.insertImg(_this.$server + result.data);
+        //     console.log(result, 'success')
+        // }
+      }
+      this.setMenus(); // 设置菜单
+      this.editor.config.onchange = (html) => {
+        _this.$emit("change", html); // 将内容同步到父组件中
+      };
+      this.editor.create(); // 创建编辑器
+    },
+    setMenus() {
+      // 设置菜单
+      if (this.meanArray) {
+        this.editor.config.menus = this.meanArray;
+      } else {
+        this.editor.config.menus = this.defaultMeanus;
+      }
+    },
+    getHtml() {
+      // 得到文本内容
+      return this.editor.txt.html();
+    },
+    setHtml(txt) {
+      // 设置富文本里面的值
+      this.editor.txt.html(txt);
+    },
+  },
+  mounted() {
+    const that = this;
+    that.$nextTick(function () {
+      that.init();
+    });
+  },
+};
+</script>

+ 418 - 0
src/page/case/index.vue

@@ -0,0 +1,418 @@
+<template>
+  <div id="device-management">
+    <div class="device-management-body" v-loading.fullscreen.lock="fullscreenLoading">
+      <div v-show="addVisible" class="order-management-body" style="margin-top:0">
+        <!-- 全部 -->
+        <div class="device-management_bottom" style="margin-top:0;padding:60px 20px;">
+          <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px">
+            <el-form-item label="标题" prop="title">
+                <el-input v-model="ruleForm.title"></el-input>
+            </el-form-item>
+            <el-form-item label="主图" prop="imageTitles">
+              <el-upload class="avatar-uploader" :headers="{token}" :action="uploadUrl" :show-file-list="false" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload">
+                <div>
+                  <img v-if="ruleForm.imageTitles" :src="ruleForm.imageTitles" class="avatar">
+                  <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+                </div>
+              </el-upload>
+            </el-form-item>
+            <el-form-item label="描述" prop="description">
+                <el-input v-model="ruleForm.description"></el-input>
+            </el-form-item>
+            <el-form-item label="富文本" prop='content'>
+                <editor-bar ref="editorOne" v-model="ruleForm.content" @change="change"></editor-bar>
+            </el-form-item>
+          </el-form>
+          <div slot="footer" class="dialog-footer">
+            <el-button @click="viewData = !viewData">预 览</el-button>
+            <el-button @click="cancel">取 消</el-button>
+            <el-button type="primary" @click="asyncsubmit">确 定</el-button>
+          </div>
+          <div class="view" v-if="viewData">
+            <div v-html="this.ruleForm.content"></div>
+          </div>
+        </div>
+      </div>
+      <div v-show="!addVisible" class="order-management-body">
+        <div class="order-management-inner" style="height:120px">
+          <div class="base-info">
+            <el-button icon="el-icon-plus" type="primary" style="float: right;" @click="showadd" color='red'>新增</el-button>
+          </div>
+        </div>
+        <!-- 全部 -->
+        <div class="device-management_bottom">
+          <div class="order-management-table">
+            <el-table ref="order_table" class='e-table' :data="cameras" style="width: 100%">
+              <el-table-column  label="序号" type="index" width="50" align="center">
+                  <template slot-scope="scope">
+                      <span>{{(currentPage - 1) * pagesize + scope.$index + 1}}</span>
+                  </template>
+              </el-table-column>
+              <el-table-column prop="title" label="标题">
+              </el-table-column>
+              <!-- <el-table-column prop="description" label="描述">
+              </el-table-column> -->
+              <el-table-column width="300" prop="createTime" label="上传时间">
+              </el-table-column>
+              <el-table-column label="操作">
+                <template slot-scope="scope">
+                  <!-- <el-button type="text" @click="showDialog(scope.row)" class="edit_btn">编辑</el-button> -->
+                  <el-button type="text" @click="setDel(scope.row)" class="delete_btn">修改</el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+          </div>
+          <div class="order-management-pagination">
+            <el-pagination @current-change="handleCurrentChange" :current-page.sync="currentPage" :page-size="pagesize" layout="total, prev, pager, next, jumper" :total="total">
+            </el-pagination>
+          </div>
+        </div>
+      </div>
+
+    </div>
+  </div>
+</template>
+<script>
+let tempForm = {
+  title: '',
+  description: '',
+  content: '',
+  imageTitles: '',
+}
+import EditorBar from './EditorBar'
+export default {
+  data () {
+    return {
+      expands: [],
+      accept: '.ipa, .apk',
+      md5: null,
+      complete: 0,
+      completeshow: false,
+      expandedArr: [],
+      cameras: [],
+      currentPage: 1,
+      key_input: '',
+      fullscreenLoading: false,
+      searchKey: '',
+      total: 0,
+      uploadUrl: this.$server + '/article/uploadImage',
+      token: sessionStorage.getItem('token'),
+      // expressNum_input: "",
+      searchDate: [],
+      searchOrderNumber: '',
+      searchPhone: '',
+      searchExpressNum: '',
+      hasClickSearch: false,
+      tabIndex: 0,
+      addVisible: false,
+      ruleForm: tempForm,
+      isClear: false,
+      viewData:false,
+      detail:"",
+      rules: {
+        title: [
+          { required: true, message: '请输入新闻标题', trigger: 'blur' }
+        ],
+        description: [
+          { required: false, message: '请输入新闻描述', trigger: 'blur' }
+        ],
+        content: [
+          { required: true, message: '请输入新闻内容', trigger: 'blur' }
+        ],
+        imageTitles: [
+          { required: true, message: '请选择主图', trigger: 'blur' }
+        ],
+      },
+      cameraInfo: {
+        wifi: '',
+        type: '',
+        address: '',
+        initPoint: '',
+        orderNum: ''
+      },
+
+      formLabelWidth: '30%',
+      value2: true,
+      currentChildName: '',
+      currentDeviceId: '',
+      currentBalance: '',
+      pagesize: 10,
+      clients: [],
+      restaurants: []
+    }
+  },
+  components: {
+    EditorBar,
+  },
+  watch: {
+    currentPage () {
+      this._getCameraData()
+    }
+  },
+  methods: {
+    change(val){
+      console.log(val)
+    },
+    appTypeChange (val) {
+      const list = {
+        'Android': '.apk',
+        'IOS': '.ipa'
+      }
+      this.accept = list[val] || '.ipa, .apk'
+    },
+    async getAgenetList () {
+      let res = await this.$http.post('/manager/app/agenetList', {})
+      let restaurants = []
+      if (res.code === 0) {
+        restaurants = res.data.map(ele => {
+          return {value: ele}
+        })
+      }
+      this.restaurants = restaurants
+    },
+    async setDel (row) {
+        let {data} = await this.$http.post('/article/detail', {id:row.id})
+        this.ruleForm = {
+          ...data,
+        }
+        // this.$refs.editorOne.setHtml(this.ruleForm.content)
+        this.addVisible = true
+    },
+    async _getCameraData () {
+      
+      this.fullscreenLoading = true
+      if (!Number(this.currentPage)) this.currentPage = 1
+      let res = await this.$http.post('/article/list', {})
+      this.fullscreenLoading = false
+      if (res.code === 0) {
+        let temp = res.data.list
+        this.cameras = temp
+        this.total = res.data.total ? res.data.total : 0
+      }
+    },
+    async chenkMd5 (value, callback) {
+      console.log('value', value == 123456)
+      if (value == this.md5) {
+        callback()
+      } else {
+        callback(new Error('MD5错误!请重新输入'))
+      }
+      return true
+    },
+    uploadFile (file, fileList) {
+      // this.ruleForm.fileList = fileList
+      console.log('file, fileList)', file, fileList)
+    },
+    handleExceed (files, fileList) {
+      this.$message.warning(`只能选择一个文件上传`)
+    },
+    handleCurrentChange (val) {
+      this.currentPage = val
+    },
+    beforeAvatarUpload (file) {
+      const isLt2M = file.size / 1024 / 1024 < 5
+
+      if (!isLt2M) {
+        this.$message.error('上传头像图片大小不能超过 5MB!')
+      }
+      return isLt2M
+    },
+    removeDomain () {
+      console.log()
+      this.$refs['ruleForm'].validate('md5')
+    },
+    async savaCase(){
+      let res = await this.$http.post('/article/save', {
+        ...this.ruleForm,
+      })
+      this.fullscreenLoading = false
+      if (res.code === 0) {
+        this.$alert('上传成功', '添加成功', {
+          confirmButtonText: '确定'
+        })
+        this.ruleForm = tempForm
+        this.getAgenetList()
+        this._getCameraData()
+        this.cancel()
+      } else {
+        this.$alert(res.msg, '操作失败', {
+          confirmButtonText: '确定'
+        })
+      }
+    },
+    async asyncsubmit () {
+      this.$refs['ruleForm'].validate((valid) => {
+        if (valid) {
+        // this.addVisible = true
+          this.savaCase()
+        } else {
+          return false
+        }
+      })
+      // this.$refs['ruleForm'].validate((valid) => {
+      //   if (valid) {
+      //   // this.addVisible = true
+      //     this._editCompany()
+      //   } else {
+      //     return false
+      //   }
+      // })
+    },
+    cancel () {
+      this.ruleForm = tempForm
+      this.$refs['ruleForm'].resetFields()
+      this.md5 = null
+      this.addVisible = false
+    },
+    view (){
+        console.log('view',this.ruleForm)
+    },
+    async _editCompany () {
+      let {
+        fileServerType,
+        agent,
+        appType,
+        md5,
+        name
+      } = this.ruleForm
+
+      this.fullscreenLoading = true
+      let res = await this.$http.post('/manager/app/save', {
+        fileServerType,
+        agent,
+        appType,
+        md5,
+        name
+      })
+      this.fullscreenLoading = false
+      if (res.code === 0) {
+        this.$alert('上传成功', '添加成功', {
+          confirmButtonText: '确定'
+        })
+        this.getAgenetList()
+        this._getCameraData()
+        this.cancel()
+      } else {
+        this.$alert(res.msg, '操作失败', {
+          confirmButtonText: '确定'
+        })
+      }
+    },
+    handleSelect (row) {
+      this.$refs.ruleForm.validateField('agent')
+    },
+    querySearch (queryString, cb) {
+      var restaurants = this.restaurants
+      var results = queryString ? restaurants.filter(this.createFilter(queryString)) : restaurants
+      // 调用 callback 返回建议列表的数据
+      cb(results)
+    },
+    createFilter (queryString) {
+      return (restaurant) => {
+        return (restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0)
+      }
+    },
+    showadd () {
+      this.addVisible = true
+    },
+    fileRemove () {
+      this.ruleForm.fileList = []
+      this.ruleForm.md5 = ''
+      this.md5 = null
+    },
+    handleChange (file) {
+      let fileType = file.type,
+        isLt10M = file.size / 1024 / 1024 < 10
+      if (!isLt10M) {
+        this.$message.error('上传文件不能超过10M,请重新上传')
+        return false
+      }
+      if (file.name !== 'version.json') {
+        this.$message.error('请上传文件名称为version.json')
+        return false
+      }
+      this.ruleForm.jsonFile = [file]
+    },
+    async uploadSectionFile (params) {
+      const file = params.file,
+        fileType = file.type,
+        isImage = fileType.indexOf('image') != -1,
+        isLt1G = file.size / 1024 / 1024 / 1024 < 1
+      console.log('isLt1G', fileType, params)
+      // 这里常规检验,看项目需求而定
+      // if (!isImage) {
+      //   this.$message.error("只能上传图片格式png、jpg、gif!");
+      //   return;
+      // }
+      if (!isLt1G) {
+        this.fileRemove()
+        this.$message.error('上传文件过大,请重新上传')
+        return
+      }
+      // 根据后台需求数据格式
+      const form = new FormData()
+      // 文件对象
+      form.append('file', file)
+      // 本例子主要要在请求时添加特定属性,所以要用自己方法覆盖默认的action
+      // form.append("clientType", 'xxx');
+      // 项目封装的请求方法,下面做简单介绍
+      console.log('isLt1G', form, file)
+      this.completeshow = true
+      let res = await this.$http({
+        url: '/manager/app/upload',
+        method: 'post',
+        data: form,
+        processData: false,
+        contentType: false,
+        onUploadProgress: (progressEvent) => {
+          this.complete = ((progressEvent.loaded / progressEvent.total) * 100) | 0
+          console.log('上传 ' + this.complete)
+        }
+      })
+      this.completeshow = false
+
+      this.complete = 0
+      if (res.code === 0) {
+        this.ruleForm.fileList = [file]
+        this.ruleForm.name = file.name
+        this.md5 = res.data || '0'
+      }
+    },
+    handleAvatarSuccess (res, file) {
+      console.log('image',res, file)
+      this.ruleForm.imageTitles = res.msg
+    },
+  },
+  created () {
+    this._getCameraData()
+    this.getAgenetList()
+  }
+}
+</script>
+<style lang="css" scoped>
+@import "./style.css";
+</style>
+<style type="text/css">
+.inline-input{
+  width:340px;
+}
+.device-management_bottom{
+
+}
+.el-table__expand-icon > i {
+  display: none !important;
+}
+.dialog-footer{
+  text-align: center;
+}
+.view{
+  padding:50px 20px ;
+}
+.edit_btn span {
+  color: #09e1c0;
+}
+
+.delete_btn span {
+  color: #f56c6c;
+}
+</style>

+ 194 - 0
src/page/case/style.css

@@ -0,0 +1,194 @@
+.device-management-body {
+  width: 100%;
+  float: left;
+  /*  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  -moz-box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  -webkit-box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);*/
+  /*border: 1px solid #ebeef5;*/
+}
+
+.order_check_row {
+  display: flex;
+  width: 100%;
+}
+
+.product_info {
+  width: 50%;
+  flex-direction: column;
+  display: flex;
+  padding: 20px;
+  background: #fff;
+}
+
+.order_info {
+  width: 50%;
+  padding: 20px;
+  margin-left: 20px;
+  background: #fff;
+}
+
+.product_info_title {
+  text-align: left;
+  font-weight: 700;
+  margin-bottom: 20px;
+}
+
+.product_info_body {
+  margin-left: 30px;
+  display: flex;
+}
+
+.product_info_body_img {
+  width: 110px;
+  height: 110px;
+  border: 1px solid #ddd;
+}
+
+.product_img {
+  margin: 5px auto;
+  width: 100px;
+  height: 100px;
+}
+
+.product_info_body_info {
+  margin-left: 50px;
+}
+
+.product_info_body_info_item {
+  line-height: 27px;
+  text-align: left;
+}
+
+.product_info_body_info_item_title {
+  width: 100px;
+  display: inline-block;
+  margin-right: 20px;
+  font-weight: 700;
+}
+
+.order_info_title {
+  text-align: left;
+  font-weight: 700;
+  margin-bottom: 20px;
+}
+
+.order_info_body {
+  margin-left: 30px;
+  text-align: left;
+}
+
+/* .order_info_body_info {} */
+
+.order_info_body_info_item {
+  line-height: 23px;
+  padding: 10px 0;
+  border-bottom: 1px solid #f5f5f5;
+  text-align: left;
+}
+
+.order_info_body_info_item_title {
+  width: 100px;
+  display: inline-block;
+  margin-right: 20px;
+  font-weight: 700;
+}
+
+.order-management-body {
+  width: 100%;
+  margin: 30px 0 20px 0;
+  float: left;
+}
+
+.order-management-inner {
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  -moz-box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  -webkit-box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  /*border: 1px solid #ebeef5;*/
+  padding: 20px;
+  background: #fff;
+  border-radius: 5px;
+}
+
+.base-info {
+  margin: 20px 0;
+}
+
+.device-management_bottom {
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  -moz-box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  -webkit-box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  /*border: 1px solid #ebeef5;*/
+  margin-top: 30px;
+  background: #fff;
+  border-radius: 5px;
+  padding: 20px 0;
+}
+
+.device-management_tab {
+  margin: 0 0 20px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.device-management_tab ul {
+  display: inline-block;
+}
+
+.device-management_tab li {
+  display: inline-block;
+  cursor: pointer;
+  color: #999;
+  line-height: 1;
+}
+
+.device-management_tab_li_active {
+  color: #000!important;
+  font-weight: bold;
+}
+
+.order-management-table {
+  margin: 0 20px;
+}
+
+.order-management-pagination {
+  padding: 20px 20px 0;
+  position: relative;
+  text-align: right;
+}
+
+.el-select {
+  width: 340px!important;
+}
+
+.el-input {
+  width: 340px;
+}
+
+
+
+.avatar-uploader .el-upload {
+  border: 1px dashed #d9d9d9;
+  border-radius: 6px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+}
+.avatar-uploader .el-upload:hover {
+  border-color: #409EFF;
+}
+
+.avatar-uploader-icon {
+  font-size: 28px;
+  border: 1px dashed #d9d9d9;
+  color: #8c939d;
+  width: 100px;
+  height: 100px;
+  line-height: 100px;
+  text-align: center;
+}
+.avatar {
+  width: 100px;
+  height: 100px;
+  display: block;
+}

+ 1 - 0
src/page/layout/slide.vue

@@ -66,6 +66,7 @@ export default {
           { text: '场景管理', link: {name: 'scene'} },
           { text: '反馈消息', link: {name: 'feedback'} },
           // { text: '设备管理', link: {name: 'device'} },
+          { text: '案例管理', link: {name: 'case'} },
           { text: 'app管理', link: {name: 'appupload'} },
           { text: '客户管理', link: {name: 'client'} }
         ],

+ 6 - 0
src/router/index.js

@@ -52,6 +52,12 @@ export default new Router({
           meta: {text: '设备管理'}
         },
         {
+          path: '/case',
+          name: 'case',
+          component: require('@/page/case').default,
+          meta: {text: '设备管理'}
+        },
+        {
           path: '/client',
           name: 'client',
           component: require('@/page/client').default,