doum
2025-12-11 3cd92951fd2a67a02e649a870d100b3e8776ae11
经销商管理
已添加5个文件
已修改10个文件
1283 ■■■■ 文件已修改
admin/src/components/business/OperaLabelsZhuanquWindow.vue 151 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/RichEditor.vue 405 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/UploadFile.vue 145 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/system/dict/DictDataManagerWindow.vue 72 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/system/dict/OperaDictDataWindow.vue 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/system/dict/OperaDictWindow.vue 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/goodsBrand.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/goodsLabels.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/labelsBrand.vue 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/labelsBrandSerial.vue 139 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/business/labelsZhuanqu.vue 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmmall_service/src/main/java/com/doumee/core/utils/Constants.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmmall_service/src/main/java/com/doumee/dao/system/model/SystemDictData.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmmall_service/src/main/java/com/doumee/service/business/impl/LabelsServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/dmmall_service/src/main/resources/mappers/SystemDictDataMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/business/OperaLabelsZhuanquWindow.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,151 @@
<template>
  <GlobalAlertWindow
    v-loading="isUploading"
    :title="title"
    :visible.sync="visible"
    :confirm-working="isWorking"
    @confirm="confirm"
  >
    <el-form :model="form" ref="form" :rules="rules" label-width="120px" label-suffix=":"  inline>
      <el-form-item label="所属品牌" prop="parentId" v-if="form.type === 15">
        <el-select  v-model="form.parentId" placeholder="请选择所属品牌" >
          <el-option
              v-for="item in labels()"
              :key="item.id"
              :value="item.id"
              :label="item.name"
          ></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="名称" prop="name">
        <el-input v-model="form.name" placeholder="请输入名称" :maxlength="5" v-trim/>
      </el-form-item>
      <el-form-item label="展示图" prop="imgurlfull">
        <UploadAvatarImage
          :file="{ 'imgurlfull': form.imgFullurl, 'imgurl': form.imgurl }"
          :upload-data="{folder:'labels'}"
          @uploadSuccess="uploadAvatarSuccess"
          @uploadEnd="isUploading=false"
          @uploadBegin="isUploading = true"
        />
      </el-form-item>
      <el-form-item label="排序码" prop="sortnum">
        <el-input type="number" v-model="form.sortnum" placeholder="请输入排序码" v-trim/>
      </el-form-item>
      <el-form-item label="备注" prop="info">
        <el-input type="textarea" v-model="form.info" placeholder="请输入备注" :maxlength="200" v-trim/>
      </el-form-item>
    </el-form>
  </GlobalAlertWindow>
</template>
<script>
import BaseOpera from '@/components/base/BaseOpera'
import GlobalAlertWindow from '@/components/common/GlobalAlertWindow'
import UploadAvatarImage from '@/components/common/UploadAvatarImage'
export default {
  name: 'OperaLabelsWindow',
  extends: BaseOpera,
  components: { GlobalAlertWindow, UploadAvatarImage },
  data () {
    return {
      isUploading: false,
      // è¡¨å•数据
      form: {
        id: null,
        name: '',
        info: '',
        type: null,
        status: '',
        parentId: null,
        sortnum: null,
        imgFullurl: null,
        imgurl: ''
      },
      // éªŒè¯è§„则
      rules: {
        parentId: [{ required: true, message: '请选择所属品牌'  }],
        name: [{ required: true, message: '请输入名称', tigger: 'blur' }]
      }
    }
  },
  inject: ['labels'],
  created () {
    this.config({
      api: '/business/labels',
      'field.id': 'id'
    })
  },
  methods: {
    open (title, target, type) {
      this.title = title
      this.visible = true
      this.form.imgFullurl =null
      this.form.imgurl =null
      // æ–°å»º
      if (target == null) {
        this.$nextTick(() => {
          this.$refs.form.resetFields()
          this.form.provinceId = ''
          this.form[this.configData['field.id']] = null
          this.form.type = type
        })
        return
      }
      // ç¼–辑
      this.$nextTick(() => {
        for (const key in this.form) {
          this.form[key] = target[key]
        }
        this.form.type = type
      })
    },
    // ä¸Šä¼ å›¾ç‰‡
    uploadAvatarSuccess (file) {
      this.form.imgurl = file.imgurl
      this.form.imgFullurl = file.imgurlfull
    }
  }
}
</script>
<style lang="scss" scoped>
@import "@/assets/style/alertstyle.scss";
$image-width: 100px;
::v-deep .el-select {
    width: 100%;
    .el-input__inner {
      width: 100%;
    }
  }
.avatar-uploader {
  width: $image-width;
  height: $image-width;
}
::v-deep .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  width: $image-width;
  height: $image-width;
  overflow: hidden;
}
.avatar-uploader .el-upload:hover {
  border-color: #409EFF;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: $image-width;
  height: $image-width;
  line-height: $image-width;
  text-align: center;
}
.avatar {
  width: $image-width;
  height: $image-width;
  display: block;
}
</style>
admin/src/components/common/RichEditor.vue
@@ -1,159 +1,318 @@
<template>
  <div style="border: 1px solid #ccc;">
    <Toolbar
      style="border-bottom: 1px solid #ccc"
      :editor="editor"
      :defaultConfig="toolbarConfig"
      :mode="mode"
    />
    <Editor
      style="height: 300px; overflow-y: hidden;"
      v-model="content.content"
      :mode="mode"
      :defaultConfig="editorConfig"
      @onCreated="onCreated"
      @onChange="onChange"
    />
  <div :style="styleEditor">
    <Toolbar style="border-bottom: 1px solid #ccc" :editor="editor" :defaultConfig="toolbarConfig" :mode="mode" />
    <Editor style="min-height: 80px; overflow-y: hidden;" v-model="html" :defaultConfig="editorConfig" :mode="mode"
            @onCreated="onCreated" @onChange="onChange" />
  </div>
</template>
<style src="@wangeditor/editor/dist/css/style.css"></style>
<script>
import Vue from 'vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
export default {
  name: 'RichEditor',
  components: { Editor, Toolbar },
import { Loading } from 'element-ui';
let loadingInstance = null
export default Vue.extend({
  props: {
    content: Object
    richData: { // çˆ¶ç»„件传递的数据
      type: String,
      default: ''
    },
    styleEditor: '',
    readonly: false, // æ˜¯å¦å¯ä»¥è¾“å…¥
  },
  name:'RichEditor',
  components: { Editor, Toolbar },
  data() {
    return {
      editor: null,
      html: '',
      toolbarConfig: {
        toolbarKeys: [
          "headerSelect",
          "blockquote",
          "|",
          "bold",
          "underline",
          "italic",
      toolbarConfig: { // å·¥å…·æ é…ç½®
        toolbarKeys: this.readonly ? ["fullScreen"]: [ // æ˜¾ç¤ºæŒ‡å®šçš„菜单项
          "bold", // ç²—体
          "underline", // ä¸‹åˆ’线
          "italic", // æ–œä½“
          "through", // åˆ é™¤çº¿
          "code", // è¡Œå†…代码
          "sub", // ä¸‹æ ‡
          "sup", // ä¸Šæ ‡
          "clearStyle", // æ¸…除格式
          "color", // å­—体颜色
          "bgColor", // èƒŒæ™¯è‰²
          "fontSize", // å­—号
          "fontFamily", // å­—体
          "indent", // å¢žåŠ ç¼©è¿›
          "delIndent", // å‡å°‘缩进
          "justifyLeft", // å·¦å¯¹é½
          "justifyRight", // å³å¯¹é½
          "justifyCenter", // å±…中对齐
          "justifyJustify", // ä¸¤ç«¯å¯¹é½
          "lineHeight", // è¡Œé«˜
          // "viewImageLink", // æŸ¥çœ‹é“¾æŽ¥
          "divider", // åˆ†å‰²çº¿
          "emotion", // è¡¨æƒ…
          "insertLink", // æ’入链接
          // "editLink", // ä¿®æ”¹é“¾æŽ¥
          // "unLink", // å–消链接
          // "viewLink", // æŸ¥çœ‹é“¾æŽ¥
          "codeBlock", // ä»£ç å—
          "blockquote", // å¼•用
          "headerSelect", // æ ‡é¢˜
          // "header1", // æ ‡é¢˜1
          // "header2", // æ ‡é¢˜2
          // "header3", // æ ‡é¢˜3
          // "header4", // æ ‡é¢˜4
          // "header5", // æ ‡é¢˜5
          // "todo", // å¾…办
          "redo", // é‡åš
          "undo", // æ’¤é”€
          // "enter", // å›žè½¦
          // "bulletedList", // æ— åºåˆ—表
          // "numberedList", // æœ‰åºåˆ—表
          // "codeSelectLang" // é€‰æ‹©è¯­è¨€
          // è¡¨æ ¼åŠŸèƒ½åˆ†ç»„
          /* {
             key: 'table-style', // å¿…填,要以 group å¼€å¤´
             title: '表格', // å¿…å¡«
             // iconSvg: '<svg>....</svg>', // å¯é€‰
             menuKeys: [
               "insertTable", // æ’入表格
               "deleteTable", // åˆ é™¤è¡¨æ ¼
               "insertTableRow", // æ’入行
               "deleteTableRow", // åˆ é™¤è¡Œ
               "insertTableCol", // æ’入列
               "deleteTableCol", // åˆ é™¤åˆ—
               "tableHeader", // è¡¨å¤´
               "tableFullWidth", // å®½åº¦è‡ªé€‚应
             ] // ä¸‹çº§èœå• key ï¼Œå¿…å¡«
           },*/
          // ä¸Šä¼ å›¾ç‰‡åˆ†ç»„
          {
              "key": "group-more-style",
              "title": "更多",
              "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M204.8 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z\"></path><path d=\"M505.6 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z\"></path><path d=\"M806.4 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z\"></path></svg>",
              "menuKeys": [
                  "through",
                  "code",
                  "sup",
                  "sub",
                  "clearStyle"
              ]
            key: 'img-style', // å¿…填,要以 group å¼€å¤´
            title: '图片', // å¿…å¡«
            // iconSvg: '<svg>....</svg>', // å¯é€‰
            menuKeys: [
              "uploadImage", // ä¸Šä¼ å›¾ç‰‡
              "insertImage", // ç½‘络图片
              "deleteImage", // åˆ é™¤å›¾ç‰‡
              "editImage", // ç¼–辑图片
              "imageWidth30", // å›¾ç‰‡å®½åº¦ç›¸å¯¹äºŽç¼–辑器宽度的百分比30
              "imageWidth50", // å›¾ç‰‡å®½åº¦ç›¸å¯¹äºŽç¼–辑器宽度的百分比50
              "imageWidth100", // å›¾ç‰‡å®½åº¦ç›¸å¯¹äºŽç¼–辑器宽度的百分比100
            ] // ä¸‹çº§èœå• key ï¼Œå¿…å¡«
          },
          "color",
          "bgColor",
          "|",
          "fontSize",
          "fontFamily",
          "lineHeight",
          "|",
          "bulletedList",
          "numberedList",
          "todo",
          // è§†é¢‘分组
          {
              "key": "group-justify",
              "title": "对齐",
              "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M768 793.6v102.4H51.2v-102.4h716.8z m204.8-230.4v102.4H51.2v-102.4h921.6z m-204.8-230.4v102.4H51.2v-102.4h716.8zM972.8 102.4v102.4H51.2V102.4h921.6z\"></path></svg>",
              "menuKeys": [
                  "justifyLeft",
                  "justifyRight",
                  "justifyCenter",
                  "justifyJustify"
              ]
            key: 'video-style', // å¿…填,要以 group å¼€å¤´
            title: '视频', // å¿…å¡«
            // iconSvg: '<svg>....</svg>', // å¯é€‰
            menuKeys: [
              "insertVideo", // æ’入网络视频
              "uploadVideo", // ä¸Šä¼ è§†é¢‘
              "editVideoSize", // ä¿®æ”¹è§†é¢‘尺寸
            ] // ä¸‹çº§èœå• key ï¼Œå¿…å¡«
          },
          {
              "key": "group-indent",
              "title": "缩进",
              "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M0 64h1024v128H0z m384 192h640v128H384z m0 192h640v128H384z m0 192h640v128H384zM0 832h1024v128H0z m0-128V320l256 192z\"></path></svg>",
              "menuKeys": [
                  "indent",
                  "delIndent"
              ]
          },
          // "|",
          "emotion",
          "insertLink",
          {
              "key": "group-image",
              "title": "图片",
              "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M959.877 128l0.123 0.123v767.775l-0.123 0.122H64.102l-0.122-0.122V128.123l0.122-0.123h895.775zM960 64H64C28.795 64 0 92.795 0 128v768c0 35.205 28.795 64 64 64h896c35.205 0 64-28.795 64-64V128c0-35.205-28.795-64-64-64zM832 288.01c0 53.023-42.988 96.01-96.01 96.01s-96.01-42.987-96.01-96.01S682.967 192 735.99 192 832 234.988 832 288.01zM896 832H128V704l224.01-384 256 320h64l224.01-192z\"></path></svg>",
              "menuKeys": [
                  "insertImage",
                  "uploadImage"
              ]
          },
          "insertTable",
          "codeBlock",
          "divider",
          "|",
          "undo",
          "redo",
          "|",
          "fullScreen"
        ]
          "fullScreen", // å…¨å±
        ],
        excludeKeys: [ // éšè—æŒ‡å®šçš„菜单项
          // 'headerSelect',
          // 'video-style'
          // æŽ’除菜单组,写菜单组 key çš„值即可
        ],
      },
      editorConfig: {
      editorConfig: { // ç¼–辑器配置
        placeholder: '请输入内容...',
        readOnly: this.readonly, // æ˜¯å¦åªè¯»ï¼Œé»˜è®¤false
        autoFocus: false, // æ˜¯å¦è‡ªåЍfocus,默认为true
        scroll: true, // é…ç½®ç¼–辑器是否支持滚动,默认为 true ã€‚注意,此时不要固定 editor-container çš„高度,设置一个 min-height å³å¯ã€‚
        maxLength: 20000, // æœ€å¤§é™åˆ¶ï¼Œé¿å…å†…容过多卡顿
        MENU_CONF: {
          // å›¾ç‰‡ä¸Šä¼ 
          uploadImage: {
            // server: '/api/upload',
            name: 'file',
            server: process.env.VUE_APP_API_PREFIX + '/public/uploadPicture',
            server: process.env.VUE_APP_API_PREFIX + '/visitsAdmin/cloudService/public/upload?folder=richeditor',
            fieldName: 'file',
            // å•个文件的最大体积限制,默认为 2M
            maxFileSize: 10 * 1024 * 1024, // 10M
            // æœ€å¤šå¯ä¸Šä¼ å‡ ä¸ªæ–‡ä»¶ï¼Œé»˜è®¤ä¸º 100
            maxNumberOfFiles: 10,
            // é€‰æ‹©æ–‡ä»¶æ—¶çš„类型限制,默认为 ['image/*'] ã€‚如不想限制,则设置为 []
            allowedFileTypes: ['image/*'],
            // è‡ªå®šä¹‰ä¸Šä¼ å‚数,例如传递验证的 token ç­‰ã€‚参数会被添加到 formData ä¸­ï¼Œä¸€èµ·ä¸Šä¼ åˆ°æœåŠ¡ç«¯ã€‚
            meta: {
              folder: 'znzz/project_file'
            },
            onBeforeUpload(file) {    // JS è¯­æ³•
              // file é€‰ä¸­çš„æ–‡ä»¶ï¼Œæ ¼å¼å¦‚ { key: file }
              // debugger
              return file
            // å°† meta æ‹¼æŽ¥åˆ° url å‚数中,默认 false
            metaWithUrl: false,
            // è‡ªå®šä¹‰å¢žåŠ  http  header
            // headers: { Authorization: "Bearer " + getToken() },
            // è·¨åŸŸæ˜¯å¦ä¼ é€’ cookie ï¼Œé»˜è®¤ä¸º false
            withCredentials: true,
            // è¶…时时间,默认为 10 ç§’
            timeout: 10 * 1000, //10 ç§’
            // ä¸Šä¼ å‰
            onBeforeUpload(files) {
              loadingInstance = Loading.service({
                lock: true,
                text: '上传中...',
                spinner: 'el-icon-loading',
                background: 'rgba(0, 0, 0, 0.7)'
              });
              return files;
            },
            // è‡ªå®šä¹‰æ’入图片
            customInsert(res, insertFn) {
              console.log(res);
              // å› ä¸ºè‡ªå®šä¹‰æ’入导致onSuccess与onFailed回调函数不起作用,自己手动处理
              // å…ˆå…³é—­ç­‰å¾…çš„Message
              loadingInstance = Loading.service({
                lock: true,
                text: '上传中...',
                spinner: 'el-icon-loading',
                background: 'rgba(0, 0, 0, 0.7)'
              }).close();
              if (res.code === 200) {
                // Message.success({
                //     message: `${res.data.originalName} ä¸Šä¼ æˆåŠŸ`
                // });
              } else {
                // Message.error({
                //     message: `${res.data.originalName} ä¸Šä¼ å¤±è´¥ï¼Œè¯·é‡æ–°å°è¯•`
                // });
              }
              insertFn(res.data.url, res.data.originname, res.data.imgname);
            },
            // å•个文件上传成功之后
            onSuccess(file, res) {
                console.log(`${file.name} ä¸Šä¼ æˆåŠŸ`, res)
              console.log(`${file.originalFilename} ä¸Šä¼ æˆåŠŸ`, res);
            },
            // å•个文件上传失败
            onFailed(file, res) {
              console.log(`${file.originalFilename} ä¸Šä¼ å¤±è´¥`, res);
              loadingInstance.close();
            },
            // ä¸Šä¼ è¿›åº¦çš„回调函数
            onProgress(progress) {
              console.log('progress', progress);
              // progress æ˜¯ 0-100 çš„æ•°å­—
            },
            // ä¸Šä¼ é”™è¯¯ï¼Œæˆ–者触发 timeout è¶…æ—¶
            onError(file, err, res) {
              console.log(`${file.name} ä¸Šä¼ å‡ºé”™`, err, res)
            },
              loadingInstance.close();
              console.log(`${file.originalFilename} ä¸Šä¼ å‡ºé”™`, err, res);
            }
          },
          // è§†é¢‘上传
          uploadVideo: {
            fieldName: 'file',
            server: process.env.VUE_APP_API_PREFIX + '/public/upload?folder=richeditor',
            // å•个文件的最大体积限制,默认为 10M
            maxFileSize: 50 * 1024 * 1024, // 50M
            // æœ€å¤šå¯ä¸Šä¼ å‡ ä¸ªæ–‡ä»¶ï¼Œé»˜è®¤ä¸º 5
            maxNumberOfFiles: 3,
            // é€‰æ‹©æ–‡ä»¶æ—¶çš„类型限制,默认为 ['video/*'] ã€‚如不想限制,则设置为 []
            allowedFileTypes: ['video/*'],
            // è‡ªå®šä¹‰ä¸Šä¼ å‚数,例如传递验证的 token ç­‰ã€‚参数会被添加到 formData ä¸­ï¼Œä¸€èµ·ä¸Šä¼ åˆ°æœåŠ¡ç«¯ã€‚
            meta: {
              // token: 'xxx',
              // otherKey: 'yyy'
            },
            // å°† meta æ‹¼æŽ¥åˆ° url å‚数中,默认 false
            metaWithUrl: false,
            // è‡ªå®šä¹‰å¢žåŠ  http  header
            headers: {
              // Authorization: "Bearer " + getToken()
              // otherKey: 'xxx'
            },
            // è·¨åŸŸæ˜¯å¦ä¼ é€’ cookie ï¼Œé»˜è®¤ä¸º false
            withCredentials: true,
            // è¶…时时间,默认为 30 ç§’
            timeout: 1000 * 1000, // 1000 ç§’,
            // ä¸Šä¼ ä¹‹å‰è§¦å‘
            onBeforeUpload(file) {
              return file;
            },
            // è‡ªå®šä¹‰æ’入视频
            customInsert(res, insertFn) {
              // å› ä¸ºè‡ªå®šä¹‰æ’入导致onSuccess与onFailed回调函数不起作用,自己手动处理
              // å…ˆå…³é—­ç­‰å¾…çš„Message
              // Message.closeAll();
              if (res.code === 200) {
                // Message.success({
                //     message: `${res.data.originalName} ä¸Šä¼ æˆåŠŸ`
                // });
              } else {
                // Message.error({
                //     message: `${res.data.originalName} ä¸Šä¼ å¤±è´¥ï¼Œè¯·é‡æ–°å°è¯•`
                // });
              }
              insertFn(res.data.url, res.data.url);
            },
            // ä¸Šä¼ è¿›åº¦çš„回调函数
            onProgress(progress) {
              console.log(progress);
              // onProgress(progress) {       // JS è¯­æ³•
              // progress æ˜¯ 0-100 çš„æ•°å­—
            },
            // // å•个文件上传成功之后
            // onSuccess(file, res) {
            //   console.log(`${file.name} ä¸Šä¼ æˆåŠŸ`, res);
            //   this.successMsg(file);
            // },
            // // å•个文件上传失败
            // onFailed(file, res) {
            //   console.log(`${file.name} ä¸Šä¼ å¤±è´¥`, res);
            //   this.errorMsg(file);
            // },
            // ä¸Šä¼ é”™è¯¯ï¼Œæˆ–者触发 timeout è¶…æ—¶
            onError(file, err, res) {
              console.log(`${file.name} ä¸Šä¼ å‡ºé”™`, err, res);
              // Notification.error({
              //     title: '错误',
              //     message: `${file.name} ä¸Šä¼ å¤±è´¥ï¼Œè¯·é‡æ–°å°è¯•`
              // });
            }
          }
        }
      },
      mode: 'default', // or 'simple'
    }
  },
  watch: {
    richData: function (value) {
      this.html = value
    },
    readonly: function (value) {
      this.readonly = value
    },
    styleEditor: function (value) {
      this.styleEditor = value
    },
  },
  mounted() {
    // éœ€è¦åœ¨ç¼–辑器创建完毕后在赋值
    this.$nextTick(()=>{
      this.html = this.richData
    })
  },
  methods: {
    // ç¼–辑器创建完毕时的回调函数
    onCreated(editor) {
      this.editor = Object.seal(editor) // ä¸€å®šè¦ç”¨ Object.seal() ï¼Œå¦åˆ™ä¼šæŠ¥é”™
    },
    // ç¼–辑器内容、选区变化时的回调函数
    onChange(editor) {
      this.$emit('getWangedditor', editor.getHtml())
      console.log("onChange", editor.getHtml()); // onChange æ—¶èŽ·å–ç¼–è¾‘å™¨æœ€æ–°å†…å®¹
    },
  },
  beforeDestroy() {
    // ç¼–辑器销毁时的回调函数。调用 editor.destroy() å³å¯é”€æ¯ç¼–辑器
    const editor = this.editor
    if (editor == null) return
    editor.destroy() // ç»„件销毁时,及时销毁编辑器
  },
  methods: {
    onCreated (editor) {
      this.editor = Object.seal(editor)
    },
    onChange (editor) {
      // debugger
      this.$emit('edit', this.content.content)
      // this.value = this.html
      // console.log(this.content);
    },
    // onBlur (editor) {
    //   console.log('onBlur', editor)
    //   this.$emit('edit', this.html)
    // },
  },
}
  }
})
</script>
<style src="@wangeditor/editor/dist/css/style.css"></style>
<style lang="scss">
</style>>
admin/src/components/common/UploadFile.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,145 @@
<template>
  <div>
    <el-upload
      class="upload-demo"
      :accept="uploadData.fileType"
      :action="uploadImgUrl"
      :limit="this.fileLength"
      :on-exceed="handleExceed"
      :on-success="handleFileSuccess"
      :on-error="uploadError"
      :before-upload="beforeFileUpload"
      :file-list="fileList">
    <el-button size="small" type="primary">点击上传</el-button>
    <div slot="tip" class="el-upload__tip"  >
      åªèƒ½ä¸Šä¼ {{ this.fileLength }}个文件,
      {{uploadData.fileType?('只支持上传【'+uploadData.fileType+'】类型文件'):''}}
      æ–‡ä»¶å¤§å°ä¸èƒ½è¶…过30MB,
      æ•°é‡è¶…过请删除已传附件重新上传
     </div>
  </el-upload>
  </div>
</template>
<script>
export default {
  props: {
    file: {
      type: Object,
      default: () => {}
    },
    tipsLabel: '',
    customStyle: {
      type: String,
    default: 'width: 190px; height: 190px;'
    },
    fileLength:{
      type: Number,
      default: () => 1
    },
    uploadData: Object
  },
  data() {
    return {
      fileList: [],
      uploadImgUrl: process.env.VUE_APP_API_PREFIX + '/visitsAdmin/cloudService/public/upload?folder='+this.uploadData.folder
    }
  },
  methods: {
    // ä¸Šä¼ å›¾ç‰‡
    handleExceed(){
      if(this.fileList && this.fileList.length >= this.fileLength){
        this.$message.error('只允许上传【'+this.fileLength+'个附件】')
      }
    },
    handleFileSuccess(res, file) {
      if (res.code == 200) {
        let { data } = res
        this.fileList = [{name: data.originname, url: data.url }]
        this.$message.success('上传成功')
        this.$emit('uploadSuccess', { fileurl: data.imgaddr, fileurlFull: data.url, name: data.originname,fileSize:data.fileSize })
      } else {
        this.$message.error('上传失败')
      }
      this.$emit('uploadEnd')
    },
    uploadError() {
      this.$message.error('上传失败')
      this.$emit('uploadEnd')
    },
    //
    beforeFileUpload(file) {
      if(this.fileList && this.fileList.length >= this.fileLength){
        this.$message.error('只允许上传【'+this.fileLength+'个文件】')
        return false;
      }
      const isLt2M = file.size / 1024 / 1024 <= 30; // æ£€æŸ¥æ–‡ä»¶å¤§å°æ˜¯å¦å°äºŽ30MB
      if (!isLt2M) {
        this.$message.error('上传文件大小不能超过 30MB!');
        return false; // ä¸å…è®¸ä¸Šä¼ è¶…过指定大小的文件
      }
      this.$emit('uploadBegin')
      return true
    }
  }
}
</script>
<style lang="scss" scoped>
$image-width: 100px;
$image-height: 30px;
.avatar-uploader {
  width: 100px;
  height: $image-width;
}
::v-deep .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  width: $image-width;
  height: $image-height;
  overflow: hidden;
}
.avatar-uploader .el-upload:hover {
  border-color: #409EFF;
}
.avatar-uploader-icon {
  line-height: 90px;
  font-size: 28px;
  color: #8c939d;
  width: $image-width;
  height: $image-height;
  text-align: center;
}
.avatar {
  width: $image-width;
  height: $image-height;
  display: block;
}
.tips-style {
  height: 13px;
  font-size: 13px;
  font-weight: 400;
  color: #999999;
  line-height: 13px;
}
</style>
<style lang="scss" scoped>
::v-deep .el-upload--picture-card{
  width: 90px !important;
  height: 90px !important;
}
.icon {
  -webkit-transform: translate(-50%,-50%);
  -ms-transform: translate(-50%,-50%);
  transform: translate(0%, -85%);
}
::v-deep .el-upload-list__item {
  width: 500px !important;
  height: 30px !important;
}
</style>
admin/src/components/system/dict/DictDataManagerWindow.vue
@@ -1,9 +1,9 @@
<template>
  <GlobalWindow
    :title="dictName + '数据管理'"
    width="78%"
    :visible.sync="visible"
    :with-footer="false"
      :title="dictName + '数据管理'"
      width="78%"
      :visible.sync="visible"
      :with-footer="false"
  >
    <TableLayout :with-breadcrumb="false">
      <!-- è¡¨æ ¼å’Œåˆ†é¡µ -->
@@ -13,14 +13,22 @@
          <li><el-button @click="deleteByIdInBatch" icon="el-icon-delete">删除</el-button></li>
        </ul>
        <el-table
          v-loading="isWorking.search"
          :data="tableData.list"
          stripe
          @selection-change="handleSelectionChange"
            v-loading="isWorking.search"
            :data="tableData.list"
            stripe
            class="no-scroll"
            @selection-change="handleSelectionChange"
        >
          <el-table-column type="selection" width="55"></el-table-column>
          <el-table-column prop="label" label="数据标签" min-width="100px"></el-table-column>
          <el-table-column prop="code" label="数据值" min-width="100px"></el-table-column>
          <el-table-column prop="code" label="数据值" min-width="100px">
            <template slot-scope="{row}">
              <div v-if="row.code || row.code.length>500" >
                <el-button type="text" @click="showCode(row)" >点击查看</el-button>
              </div>
              <div v-else>{{row.code}}</div>
            </template>
          </el-table-column>
          <el-table-column prop="disabled" label="状态" min-width="100px">
            <template slot-scope="{row}">{{row.disabled | disabledText}}</template>
          </el-table-column>
@@ -30,27 +38,44 @@
          <el-table-column prop="updateUser" label="更新人" min-width="100px">
            <template slot-scope="{row}">{{row.updateUserInfo == null ? '' : row.updateUserInfo.username}}</template>
          </el-table-column>
          <el-table-column prop="remark" label="说明" min-width="100px"></el-table-column>
          <el-table-column prop="createTime" label="创建时间" min-width="100px"></el-table-column>
          <el-table-column prop="updateTime" label="更新时间" min-width="100px"></el-table-column>
          <el-table-column
            label="操作"
            min-width="120"
            fixed="right"
              label="操作"
              min-width="120"
              fixed="right"
          >
            <template slot-scope="{row}">
              <el-button type="text" @click="$refs.operaDictDataWindow.open('编辑字典数据', dictId, row)" icon="el-icon-edit">编辑</el-button>
              <el-button type="text" @click="$refs.operaDictDataWindow.open('编辑字典数据', searchForm.dictId, row)" icon="el-icon-edit">编辑</el-button>
              <el-button type="text" @click="deleteById(row)" icon="el-icon-delete">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <pagination
          @size-change="handleSizeChange"
          @current-change="handlePageChange"
          :pagination="tableData.pagination"
            @size-change="handleSizeChange"
            @current-change="handlePageChange"
            :pagination="tableData.pagination"
        ></pagination>
      </template>
      <!-- æ–°å»º/修改 -->
      <OperaDictDataWindow ref="operaDictDataWindow" @success="handlePageChange(tableData.pagination.pageIndex)"/>
      <el-dialog
          class="center-title"
          title="字典值"
          width="70%"
          height="70%"
          text="字典值"
          :visible.sync="visible1"
          append-to-body
      >
        <div class="agree-list"  v-html="agreement">
        </div>
        <template  v-slot:footer>
          <el-button @click="visible1=false">返回</el-button>
        </template>
      </el-dialog>
    </TableLayout>
  </GlobalWindow>
</template>
@@ -68,6 +93,8 @@
  data () {
    return {
      visible: false,
      visible1: false,
      agreement: '',
      searchForm: {
        // å­—å…¸ID
        dictId: null
@@ -83,6 +110,10 @@
      this.dictName = dictName
      this.visible = true
      this.search()
    },
    showCode(row){
      this.agreement=row.code
      this.visible1=true
    }
  },
  created () {
@@ -95,6 +126,14 @@
</script>
<style scoped lang="scss">
.agree-list{
  height: 550px;
  //max-height: 50%;
  overflow: auto;
}
.no-scroll {
  overflow: hidden !important;
}
/deep/ .window__body {
  .table-content {
    padding: 0;
@@ -102,5 +141,6 @@
      padding-top: 0;
    }
  }
}
</style>
admin/src/components/system/dict/OperaDictDataWindow.vue
@@ -1,42 +1,65 @@
<template>
  <GlobalAlertWindow
    :title="title"
    :visible.sync="visible"
    :confirm-working="isWorking.create"
    @confirm="confirm"
  <GlobalWindow
      :title="title"
      :visible.sync="visible"
      :confirm-working="isWorking.create"
      @confirm="confirm"
  >
    <el-form :model="form" ref="form" :rules="rules">
      <el-form-item label="数据说明" prop="label" required>
        <el-input v-model="form.remark" placeholder="请输入数据说明" v-trim/>
      </el-form-item>
      <el-form-item label="数据标签" prop="label" required>
        <el-input v-model="form.label" placeholder="请输入数据标签" v-trim maxlength="50"/>
        <el-input v-model="form.label" placeholder="请输入数据标签" v-trim/>
      </el-form-item>
      <el-form-item label="是否富文本" prop="istext" >
        <el-radio-group v-model="form.istext">
          <el-radio :label="0" value="0">文本</el-radio>
          <el-radio :label="1" value="1">图片|文件</el-radio>
          <el-radio :label="2" value="2">富文本</el-radio>
        </el-radio-group>
<!--        <el-switch v-model="form.istext" :active-value="true" :inactive-value="false"/>
        <span class="status-text">{{form.istext | disabledText1}}</span>-->
      </el-form-item>
      <el-form-item label="数据值" prop="code" required>
        <el-input v-model="form.code" placeholder="请输入数据值" v-trim maxlength="50"/>
        <template  v-if="form.istext == 1" >
          <UploadFile :uploadData="{ folder: 'richeditor',fileType:'' }" :fileList="fileList" @uploadSuccess="fileUploaded" />
          <el-input  readonly v-model="form.code" placeholder="完整数据值" v-trim/>
        </template>
        <RichEditor v-if="form.istext == 2"  :richData="form.code" :styleEditor="styleEditor" @getWangedditor="getWangedditor" :readonly="false"/>
        <el-input v-if="form.istext == 0"  v-model="form.code" placeholder="请输入数据值" v-trim/>
      </el-form-item>
      <el-form-item label="状态" prop="disabled" required class="form-item-status">
        <el-switch v-model="form.disabled" :active-value="false" :inactive-value="true"/>
        <span class="status-text">{{form.disabled | disabledText}}</span>
      </el-form-item>
    </el-form>
  </GlobalAlertWindow>
  </GlobalWindow>
</template>
<script>
import BaseOpera from '@/components/base/BaseOpera'
import GlobalAlertWindow from '@/components/common/GlobalAlertWindow'
import GlobalWindow from '@/components/common/GlobalWindow'
import RichEditor from '@/components/common/RichEditor'
import UploadFile from "@/components/common/UploadFile"
export default {
  name: 'OperaDictDataWindow',
  extends: BaseOpera,
  components: { GlobalAlertWindow },
  components: {UploadFile, GlobalWindow,RichEditor },
  data () {
    return {
      // è¡¨å•数据
      styleEditor:'border: 1px solid #ccc;display: inline-block;',
      form: {
        id: null,
        dictId: null,
        code: '',
        label: '',
        disabled: false
        disabled: false,
        istext: 0,
        remark: ''
      },
      fileList: [],
      // éªŒè¯è§„则
      rules: {
        label: [
@@ -49,6 +72,12 @@
    }
  },
  methods: {
    fileUploaded(data){
      this.form.code = data.fileurlFull
    },
    getWangedditor(val){
      this.form.code =val
    },
    /**
     * @title çª—口标题
     * @dict æ‰€å±žå­—å…¸ID
@@ -57,12 +86,15 @@
    open (title, dictId, target) {
      this.title = title
      this.visible = true
      this.form.istext = 0
      // æ–°å»º
      if (target == null) {
        this.$nextTick(() => {
          this.$refs.form.resetFields()
          this.form.id = null
          this.form.dictId = dictId
          this.form.istext=0
        })
        return
      }
@@ -70,6 +102,8 @@
      this.$nextTick(() => {
        for (const key in this.form) {
          this.form[key] = target[key]
          this.form.dictId = dictId
          this.form.istext = 0
        }
      })
    }
admin/src/components/system/dict/OperaDictWindow.vue
@@ -1,5 +1,5 @@
<template>
  <GlobalAlertWindow
  <GlobalWindow
    :title="title"
    :visible.sync="visible"
    :confirm-working="isWorking"
@@ -7,25 +7,25 @@
  >
    <el-form :model="form" ref="form" :rules="rules">
      <el-form-item label="字典编码" prop="code" required>
        <el-input v-model="form.code" placeholder="请输入字典编码" v-trim maxlength="50"/>
        <el-input v-model="form.code" placeholder="请输入字典编码" v-trim />
      </el-form-item>
      <el-form-item label="字典名称" prop="name" required>
        <el-input v-model="form.name" placeholder="请输入字典名称" v-trim maxlength="50"/>
        <el-input v-model="form.name" placeholder="请输入字典名称" v-trim />
      </el-form-item>
      <el-form-item label="备注" prop="remark">
        <el-input v-model="form.remark" type="textarea" placeholder="请输入备注" :rows="3" v-trim maxlength="500"/>
      </el-form-item>
    </el-form>
  </GlobalAlertWindow>
  </GlobalWindow>
</template>
<script>
import BaseOpera from '@/components/base/BaseOpera'
import GlobalAlertWindow from '@/components/common/GlobalAlertWindow'
import GlobalWindow from '@/components/common/GlobalWindow'
export default {
  name: 'OperaDictWindow',
  extends: BaseOpera,
  components: { GlobalAlertWindow },
  components: { GlobalWindow },
  data () {
    return {
      // è¡¨å•数据
admin/src/views/business/goodsBrand.vue
@@ -49,6 +49,18 @@
        <el-table-column prop="name" label="品牌名称" min-width="100px"></el-table-column>
        <el-table-column prop="sortnum" label="排序码(升序)" min-width="100px"></el-table-column>
        <el-table-column prop="createDate" label="创建时间" min-width="100px"></el-table-column>
        <el-table-column prop="status" label="状态" min-width="100px">
          <template slot-scope="{row}">
            <el-switch
                v-model="row.status"
                :active-value="1"
                :inactive-value="0"
                active-color="#13ce66"
                inactive-color="#ff4949"
                @change="statusChange(row)"
            ></el-switch>
          </template>
        </el-table-column>
        <el-table-column
          v-if="containPermissions(['business:productlabel:update', 'business:productlabel:delete'])"
          label="操作"
@@ -101,6 +113,20 @@
      'field.main': 'id'
    })
    this.search()
  },
  methods: {
    statusChange (row) {
      this.api.updateById({ id: row.id, status: row.status })
        .then(() => {
          this.$message.success('操作成功')
        })
        .catch(e => {
          this.$message.error('操作成功')
        })
        .then(() => {
          this.handlePageChange()
        })
    }
  }
}
</script>
admin/src/views/business/goodsLabels.vue
@@ -49,6 +49,18 @@
        <el-table-column prop="name" label="分类名称" min-width="100px"></el-table-column>
        <el-table-column prop="sortnum" label="排序码(升序)" min-width="100px"></el-table-column>
        <el-table-column prop="createDate" label="创建时间" min-width="100px"></el-table-column>
        <el-table-column prop="status" label="状态" min-width="100px">
          <template slot-scope="{row}">
            <el-switch
                v-model="row.status"
                :active-value="1"
                :inactive-value="0"
                active-color="#13ce66"
                inactive-color="#ff4949"
                @change="statusChange(row)"
            ></el-switch>
          </template>
        </el-table-column>
        <el-table-column
          v-if="containPermissions(['business:productlabel:update', 'business:productlabel:delete'])"
          label="操作"
@@ -101,6 +113,20 @@
      'field.main': 'id'
    })
    this.search()
  },
  methods: {
    statusChange (row) {
      this.api.updateById({ id: row.id, status: row.status })
          .then(() => {
            this.$message.success('操作成功')
          })
          .catch(e => {
            this.$message.error('操作成功')
          })
          .then(() => {
            this.handlePageChange()
          })
    }
  }
}
</script>
admin/src/views/business/labelsBrand.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,120 @@
<template>
  <TableLayout :permissions="['business:labels:query']">
    <!-- æœç´¢è¡¨å• -->
    <el-form ref="searchForm" slot="search-form" :model="searchForm" label-width="100px" inline>
      <el-form-item label="适用品牌名称" prop="name">
        <el-input v-model="searchForm.name" placeholder="请输入适用品牌名称" @keypress.enter.native="search"></el-input>
      </el-form-item>
      <section>
        <el-button type="primary" @click="search">搜索</el-button>
        <el-button @click="reset">重置</el-button>
      </section>
    </el-form>
    <!-- è¡¨æ ¼å’Œåˆ†é¡µ -->
    <template v-slot:table-wrap>
      <ul class="toolbar" v-permissions="['business:labels:create', 'business:labels:delete']">
        <li><el-button type="primary" @click="$refs.operaLabelsWindow.open('新建适用品牌信息表',null,searchForm.type)" icon="el-icon-plus" v-permissions="['business:labels:create']">新建</el-button></li>
        <li><el-button  type="danger" @click="deleteByIdInBatch" icon="el-icon-delete" v-permissions="['business:labels:delete']">删除</el-button></li>
      </ul>
      <el-table
        v-loading="isWorking.search"
        :data="tableData.list"
        border
        stripe
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55"></el-table-column>
        <el-table-column prop="name" label="适用品牌名称" min-width="100px"></el-table-column>
        <el-table-column prop="imgurlfull" label="展示图" align="center" min-width="100px">
          <template slot-scope="{row}">
            <el-image style="max-width: 100px;max-height: 50px;" v-if="row.imgFullurl" :src="row.imgFullurl" :preview-src-list="[row.imgFullurl]"></el-image>
          </template>
        </el-table-column>
        <el-table-column prop="sortnum" label="排序码" min-width="100px"></el-table-column>
        <el-table-column prop="editDate" label="最近时间" min-width="100px"></el-table-column>
        <el-table-column prop="status" label="状态" min-width="100px">
          <template slot-scope="{row}">
            <el-switch
                v-model="row.status"
                :active-value="1"
                :inactive-value="0"
                active-color="#13ce66"
                inactive-color="#ff4949"
                @change="statusChange(row)"
            ></el-switch>
          </template>
        </el-table-column>
        <el-table-column
          v-if="containPermissions(['business:labels:update', 'business:labels:delete'])"
          label="操作"
          min-width="120"
          fixed="right"
        >
          <template slot-scope="{row}">
            <el-button type="text" @click="$refs.operaLabelsWindow.open('编辑适用品牌信息表', row,searchForm.type)" icon="el-icon-edit" v-permissions="['business:labels:update']">编辑</el-button>
            <el-button style="color: red" type="text" @click="deleteById(row)" icon="el-icon-delete" v-permissions="['business:labels:delete']">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination
        @size-change="handleSizeChange"
        @current-change="handlePageChange"
        :pagination="tableData.pagination"
      >
      </pagination>
    </template>
    <!-- æ–°å»º/修改 -->
    <OperaLabelsWindow ref="operaLabelsWindow" @success="handlePageChange"/>
  </TableLayout>
</template>
<script>
import BaseTable from '@/components/base/BaseTable'
import TableLayout from '@/layouts/TableLayout'
import Pagination from '@/components/common/Pagination'
import OperaLabelsWindow from '@/components/business/OperaLabelsZhuanquWindow'
import { updateById } from '@/api/business/goods'
export default {
  name: 'Labels',
  extends: BaseTable,
  components: { TableLayout, Pagination, OperaLabelsWindow },
  data () {
    return {
      // æœç´¢
      searchForm: {
        name: '',
        type: 14
      },
      labels: []
    }
  },
  provide () {
    return {
      labels: () => this.labels
    }
  },
  created () {
    this.config({
      module: '适用品牌信息表',
      api: '/business/labels',
      'field.id': 'id',
      'field.main': 'id'
    })
    this.search()
  },
  methods: {
    statusChange (row) {
      this.api.updateById({ id: row.id, status: row.status })
        .then(() => {
          this.$message.success('操作成功')
        })
        .catch(e => {
          this.$message.error('操作成功')
        })
        .then(() => {
          this.handlePageChange()
        })
    }
  }
}
</script>
admin/src/views/business/labelsBrandSerial.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,139 @@
<template>
  <TableLayout :permissions="['business:labels:query']">
    <!-- æœç´¢è¡¨å• -->
    <el-form ref="searchForm" slot="search-form" :model="searchForm" label-width="100px" inline>
      <el-form-item label="品牌系列名称" prop="name">
        <el-input v-model="searchForm.name" placeholder="请输入品牌系列名称" @keypress.enter.native="search"></el-input>
      </el-form-item>
      <el-form-item label="所属品牌" prop="parentId">
        <el-select  v-model="searchForm.parentId"  placeholder="请选择所属品牌" @change="search" >
          <el-option
              v-for="item in labels"
              :key="item.id"
              :value="item.id"
              :label="item.name"
          ></el-option>
        </el-select>
      </el-form-item>
      <section>
        <el-button type="primary" @click="search">搜索</el-button>
        <el-button @click="reset">重置</el-button>
      </section>
    </el-form>
    <!-- è¡¨æ ¼å’Œåˆ†é¡µ -->
    <template v-slot:table-wrap>
      <ul class="toolbar" v-permissions="['business:labels:create', 'business:labels:delete']">
        <li><el-button type="primary" @click="$refs.operaLabelsWindow.open('新建品牌系列信息表',null,searchForm.type)" icon="el-icon-plus" v-permissions="['business:labels:create']">新建</el-button></li>
        <li><el-button type="danger"  @click="deleteByIdInBatch" icon="el-icon-delete" v-permissions="['business:labels:delete']">删除</el-button></li>
      </ul>
      <el-table
        v-loading="isWorking.search"
        :data="tableData.list"
        border
        stripe
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55"></el-table-column>
        <el-table-column prop="name" label="品牌系列名称" min-width="100px"></el-table-column>
        <el-table-column prop="parentName" label="所属品牌" min-width="100px"></el-table-column>
        <el-table-column prop="imgurlfull" label="展示图" align="center" min-width="100px">
          <template slot-scope="{row}">
            <el-image style="max-width: 100px;max-height: 50px;" v-if="row.imgFullurl" :src="row.imgFullurl" :preview-src-list="[row.imgFullurl]"></el-image>
          </template>
        </el-table-column>
        <el-table-column prop="sortnum" label="排序码" min-width="100px"></el-table-column>
        <el-table-column prop="editDate" label="最近时间" min-width="100px"></el-table-column>
        <el-table-column prop="status" label="状态" min-width="100px">
          <template slot-scope="{row}">
            <el-switch
                v-model="row.status"
                :active-value="1"
                :inactive-value="0"
                active-color="#13ce66"
                inactive-color="#ff4949"
                @change="statusChange(row)"
            ></el-switch>
          </template>
        </el-table-column>
        <el-table-column
          v-if="containPermissions(['business:labels:update', 'business:labels:delete'])"
          label="操作"
          min-width="120"
          fixed="right"
        >
          <template slot-scope="{row}">
            <el-button type="text" @click="$refs.operaLabelsWindow.open('编辑品牌系列信息表', row,searchForm.type)" icon="el-icon-edit" v-permissions="['business:labels:update']">编辑</el-button>
            <el-button style="color: red" type="text" @click="deleteById(row)" icon="el-icon-delete" v-permissions="['business:labels:delete']">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination
        @size-change="handleSizeChange"
        @current-change="handlePageChange"
        :pagination="tableData.pagination"
      >
      </pagination>
    </template>
    <!-- æ–°å»º/修改 -->
    <OperaLabelsWindow ref="operaLabelsWindow" @success="handlePageChange"/>
  </TableLayout>
</template>
<script>
import BaseTable from '@/components/base/BaseTable'
import TableLayout from '@/layouts/TableLayout'
import Pagination from '@/components/common/Pagination'
import OperaLabelsWindow from '@/components/business/OperaLabelsZhuanquWindow'
import { findAll as labelList } from '@/api/business/labels'
export default {
  name: 'Labels',
  extends: BaseTable,
  components: { TableLayout, Pagination, OperaLabelsWindow },
  data () {
    return {
      // æœç´¢
      labels: [],
      searchForm: {
        name: '',
        parentId: null,
        type: 15
      }
    }
  },
  provide() {
    return {
      labels: () => this.labels
    }
  },
  created () {
    this.config({
      module: '品牌系列信息表',
      api: '/business/labels',
      'field.id': 'id',
      'field.main': 'id'
    })
    this.loadLabels()
    this.search()
  },
  methods: {
    loadLabels () {
      labelList({type: 14})
        .then(res => {
          this.labels = res
        })
    },
    statusChange (row) {
      this.api.updateById({ id: row.id, status: row.status })
          .then(() => {
            this.$message.success('操作成功')
          })
          .catch(e => {
            this.$message.error('操作成功')
          })
          .then(() => {
            this.handlePageChange()
          })
    }
  }
}
</script>
admin/src/views/business/labelsZhuanqu.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,120 @@
<template>
  <TableLayout :permissions="['business:labels:query']">
    <!-- æœç´¢è¡¨å• -->
    <el-form ref="searchForm" slot="search-form" :model="searchForm" label-width="100px" inline>
      <el-form-item label="专区名称" prop="name">
        <el-input v-model="searchForm.name" placeholder="请输入名称" @keypress.enter.native="search"></el-input>
      </el-form-item>
      <section>
        <el-button type="primary" @click="search">搜索</el-button>
        <el-button @click="reset">重置</el-button>
      </section>
    </el-form>
    <!-- è¡¨æ ¼å’Œåˆ†é¡µ -->
    <template v-slot:table-wrap>
      <ul class="toolbar" v-permissions="['business:labels:create', 'business:labels:delete']">
        <li><el-button type="primary" @click="$refs.operaLabelsWindow.open('新建专区信息表',null,searchForm.type)" icon="el-icon-plus" v-permissions="['business:labels:create']">新建</el-button></li>
        <li><el-button type="danger" @click="deleteByIdInBatch" icon="el-icon-delete" v-permissions="['business:labels:delete']">删除</el-button></li>
      </ul>
      <el-table
        v-loading="isWorking.search"
        :data="tableData.list"
        border
        stripe
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55"></el-table-column>
        <el-table-column prop="name" label="专区名称" min-width="100px"></el-table-column>
        <el-table-column prop="imgurlfull" label="展示图" align="center" min-width="100px">
          <template slot-scope="{row}">
            <el-image v-if="row.imgFullurl" style="max-width: 100px;max-height: 50px;" :src="row.imgFullurl" :preview-src-list="[row.imgFullurl]"></el-image>
          </template>
        </el-table-column>
        <el-table-column prop="goodsNum" label="商品数量" align="center" min-width="100px"></el-table-column>
        <el-table-column prop="sortnum" label="排序码" min-width="100px"></el-table-column>
        <el-table-column prop="editDate" label="最近时间" min-width="100px"></el-table-column>
        <el-table-column prop="status" label="状态" min-width="100px">
          <template slot-scope="{row}">
            <el-switch
                v-model="row.status"
                :active-value="1"
                :inactive-value="0"
                active-color="#13ce66"
                inactive-color="#ff4949"
                @change="statusChange(row)"
            ></el-switch>
          </template>
        </el-table-column>
        <el-table-column
          v-if="containPermissions(['business:labels:update', 'business:labels:delete'])"
          label="操作"
          min-width="120"
          fixed="right"
        >
          <template slot-scope="{row}">
            <el-button type="text" @click="$refs.operaLabelsWindow.open('编辑专区信息表', row,searchForm.type)" icon="el-icon-edit" v-permissions="['business:labels:update']">编辑</el-button>
            <el-button style="color: red" type="text" @click="deleteById(row)" icon="el-icon-delete" v-permissions="['business:labels:delete']">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination
        @size-change="handleSizeChange"
        @current-change="handlePageChange"
        :pagination="tableData.pagination"
      >
      </pagination>
    </template>
    <!-- æ–°å»º/修改 -->
    <OperaLabelsWindow ref="operaLabelsWindow" @success="handlePageChange"/>
  </TableLayout>
</template>
<script>
import BaseTable from '@/components/base/BaseTable'
import TableLayout from '@/layouts/TableLayout'
import Pagination from '@/components/common/Pagination'
import OperaLabelsWindow from '@/components/business/OperaLabelsZhuanquWindow'
export default {
  name: 'Labels',
  extends: BaseTable,
  components: { TableLayout, Pagination, OperaLabelsWindow },
  data () {
    return {
      // æœç´¢
      searchForm: {
        name: '',
        type: 12
      },
      labels:[]
    }
  },
  provide() {
    return {
      labels: () => this.labels
    }
  },
  created () {
    this.config({
      module: '专区信息表',
      api: '/business/labels',
      'field.id': 'id',
      'field.main': 'id'
    })
    this.search()
  },
  methods: {
    statusChange (row) {
      this.api.updateById({ id: row.id, status: row.status })
          .then(() => {
            this.$message.success('操作成功')
          })
          .catch(e => {
            this.$message.error('操作成功')
          })
          .then(() => {
            this.handlePageChange()
          })
    }
  },
}
</script>
server/dmmall_service/src/main/java/com/doumee/core/utils/Constants.java
@@ -17,6 +17,8 @@
    public static final int TWO = 2 ;
    public static final int THREE = 3 ;
    public static final int FOUR = 4 ;
    public static final String LABELS_IMG ="LABELS_IMG" ;
    /**
     * mq tag
     */
server/dmmall_service/src/main/java/com/doumee/dao/system/model/SystemDictData.java
@@ -33,6 +33,8 @@
    @ApiModelProperty(value = "数据值")
    @NotBlank(message = "数据值不能为空", groups = {OperaType.Create.class, OperaType.Update.class})
    private String code;
    @ApiModelProperty(value = "备注")
    private String remark;
    @ApiModelProperty(value = "数据标签")
    @NotBlank(message = "数据标签不能为空", groups = {OperaType.Create.class, OperaType.Update.class})
server/dmmall_service/src/main/java/com/doumee/service/business/impl/LabelsServiceImpl.java
@@ -290,12 +290,17 @@
        IPage<Labels> result =  labelsJoinMapper.selectJoinPage(page,Labels.class, queryWrapper);
     /*   String resourcePath=systemDictDataBiz.queryByCode(Constants.OSS, Constants.RESOURCE_PATH).getCode();*/
        if(org.apache.commons.collections.CollectionUtils.isNotEmpty(result.getRecords())){
            String path = systemDictDataBiz.queryByCode(Constants.OSS,Constants.RESOURCE_PATH).getCode()
                    + systemDictDataBiz.queryByCode(Constants.OSS,Constants.LABELS_IMG).getCode();
            for(Labels model:result.getRecords()){
               if(model.getParentId()==null){
                   model.setTypeLevel(0);
               }else{
                   model.setTypeLevel(1);
               }
               if(StringUtils.isNotBlank(model.getImgurl())){
                   model.setImgFullurl(path + model.getImgurl());
               }
               if(Constants.equalsInteger(model.getType(),Constants.LabelsType.BIG_AREA.getKey())){
                    //如果是大区信息,查询所有绑定额省份信息
                    model.setAreaList(areasMapper.selectList(new LambdaQueryWrapper<Areas>()
server/dmmall_service/src/main/resources/mappers/SystemDictDataMapper.xml
@@ -16,7 +16,7 @@
  </resultMap>
  <select id="selectManageList" parameterType="com.doumee.dao.system.dto.QuerySystemDictDataDTO" resultMap="SystemDictDataListVO">
    SELECT
      dict_data.`ID`, dict_data.`DICT_ID`, dict_data.`CODE`, dict_data.`LABEL`, dict_data.`SORT`, dict_data.`DISABLED`, dict_data.`CREATE_TIME`, dict_data.`UPDATE_TIME`, dict_data.`CREATE_USER`, dict_data.`UPDATE_USER`,
      dict_data.`ID`, dict_data.`remark`, dict_data.`DICT_ID`, dict_data.`CODE`, dict_data.`LABEL`, dict_data.`SORT`, dict_data.`DISABLED`, dict_data.`CREATE_TIME`, dict_data.`UPDATE_TIME`, dict_data.`CREATE_USER`, dict_data.`UPDATE_USER`,
      create_user.ID CREATE_USER_ID, create_user.`USERNAME` CREATE_USER_NAME,
      update_user.ID UPDETE_USER_ID, update_user.`USERNAME` UPDATE_USER_NAME
    FROM SYSTEM_DICT_DATA dict_data