Bladeren bron

添加产品及文档页面

yangg 8 maanden geleden
bovenliggende
commit
63b364c155
38 gewijzigde bestanden met toevoegingen van 3856 en 11 verwijderingen
  1. 1 1
      ui/.env.development
  2. 111 0
      ui/src/components/Tinymce/components/EditorImage.vue
  3. 59 0
      ui/src/components/Tinymce/dynamicLoadScript.js
  4. 249 0
      ui/src/components/Tinymce/index.vue
  5. 7 0
      ui/src/components/Tinymce/plugins.js
  6. 1 0
      ui/src/components/Tinymce/tinymce.min.js
  7. 6 0
      ui/src/components/Tinymce/toolbar.js
  8. 173 0
      ui/src/views/ProductMent/Category/index.vue
  9. 466 0
      ui/src/views/ProductMent/ProductManagement.vue
  10. 402 0
      ui/src/views/ProductMent/newProduct/index.vue
  11. 224 0
      ui/src/views/ProductMent/specMent/index.vue
  12. 247 0
      ui/src/views/ProductMent/sysCategory/index.vue
  13. 173 0
      ui/src/views/ProductMent/worksCategory/index.vue
  14. 3 2
      ui/src/views/system/document/components/dataList.vue
  15. 1 1
      ui/src/views/system/document/components/dataSearch.vue
  16. 1 1
      ui/src/views/system/document/create.vue
  17. 3 2
      ui/src/views/system/document/temList/components/dataList.vue
  18. 3 2
      ui/src/views/system/document/temList/components/dataSearch.vue
  19. 2 2
      ui/src/views/system/document/temList/temList.vue
  20. 11 0
      ui/src/views/system/template/category/components/dataInfo.scss
  21. 181 0
      ui/src/views/system/template/category/components/dataInfo.vue
  22. 55 0
      ui/src/views/system/template/category/components/dataList.scss
  23. 443 0
      ui/src/views/system/template/category/components/dataList.vue
  24. 3 0
      ui/src/views/system/template/category/components/dataSearch.scss
  25. 98 0
      ui/src/views/system/template/category/components/dataSearch.vue
  26. 3 0
      ui/src/views/system/template/category/components/index.js
  27. 4 0
      ui/src/views/system/template/category/search.scss
  28. 39 0
      ui/src/views/system/template/category/search.vue
  29. 11 0
      ui/src/views/system/template/components/dataInfo.scss
  30. 177 0
      ui/src/views/system/template/components/dataInfo.vue
  31. 55 0
      ui/src/views/system/template/components/dataList.scss
  32. 335 0
      ui/src/views/system/template/components/dataList.vue
  33. 3 0
      ui/src/views/system/template/components/dataSearch.scss
  34. 256 0
      ui/src/views/system/template/components/dataSearch.vue
  35. 3 0
      ui/src/views/system/template/components/index.js
  36. 4 0
      ui/src/views/system/template/search.scss
  37. 43 0
      ui/src/views/system/template/search.vue
  38. 0 0
      微信存储/WeChat Files/wxid_iwkr69dui1bt12/FileStorage/File/2024-11/index.vue

+ 1 - 1
ui/.env.development

@@ -5,7 +5,7 @@ VUE_APP_TITLE = 瑞赢科技管理系统
 ENV = 'development'
 
 # 瑞赢科技管理系统/开发环境
-VUE_APP_BASE_API = 'http://120.46.190.49:8080'
+VUE_APP_BASE_API = 'http://120.46.190.49:8885'
 
 # 路由懒加载
 VUE_CLI_BABEL_TRANSPILE_MODULES = true

+ 111 - 0
ui/src/components/Tinymce/components/EditorImage.vue

@@ -0,0 +1,111 @@
+<template>
+  <div class="upload-container">
+    <el-button :style="{background:color,borderColor:color}" icon="el-icon-upload" size="mini" type="primary" @click=" dialogVisible=true">
+      upload
+    </el-button>
+    <el-dialog :visible.sync="dialogVisible">
+      <el-upload
+        :multiple="true"
+        :file-list="fileList"
+        :show-file-list="true"
+        :on-remove="handleRemove"
+        :on-success="handleSuccess"
+        :before-upload="beforeUpload"
+        class="editor-slide-upload"
+        action="https://httpbin.org/post"
+        list-type="picture-card"
+      >
+        <el-button size="small" type="primary">
+          Click upload
+        </el-button>
+      </el-upload>
+      <el-button @click="dialogVisible = false">
+        Cancel
+      </el-button>
+      <el-button type="primary" @click="handleSubmit">
+        Confirm
+      </el-button>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+// import { getToken } from 'api/qiniu'
+
+export default {
+  name: 'EditorSlideUpload',
+  props: {
+    color: {
+      type: String,
+      default: '#1890ff'
+    }
+  },
+  data() {
+    return {
+      dialogVisible: false,
+      listObj: {},
+      fileList: []
+    }
+  },
+  methods: {
+    checkAllSuccess() {
+      return Object.keys(this.listObj).every(item => this.listObj[item].hasSuccess)
+    },
+    handleSubmit() {
+      const arr = Object.keys(this.listObj).map(v => this.listObj[v])
+      if (!this.checkAllSuccess()) {
+        this.$message('Please wait for all images to be uploaded successfully. If there is a network problem, please refresh the page and upload again!')
+        return
+      }
+      this.$emit('successCBK', arr)
+      this.listObj = {}
+      this.fileList = []
+      this.dialogVisible = false
+    },
+    handleSuccess(response, file) {
+      const uid = file.uid
+      const objKeyArr = Object.keys(this.listObj)
+      for (let i = 0, len = objKeyArr.length; i < len; i++) {
+        if (this.listObj[objKeyArr[i]].uid === uid) {
+          this.listObj[objKeyArr[i]].url = response.files.file
+          this.listObj[objKeyArr[i]].hasSuccess = true
+          return
+        }
+      }
+    },
+    handleRemove(file) {
+      const uid = file.uid
+      const objKeyArr = Object.keys(this.listObj)
+      for (let i = 0, len = objKeyArr.length; i < len; i++) {
+        if (this.listObj[objKeyArr[i]].uid === uid) {
+          delete this.listObj[objKeyArr[i]]
+          return
+        }
+      }
+    },
+    beforeUpload(file) {
+      const _self = this
+      const _URL = window.URL || window.webkitURL
+      const fileName = file.uid
+      this.listObj[fileName] = {}
+      return new Promise((resolve, reject) => {
+        const img = new Image()
+        img.src = _URL.createObjectURL(file)
+        img.onload = function() {
+          _self.listObj[fileName] = { hasSuccess: false, uid: file.uid, width: this.width, height: this.height }
+        }
+        resolve(true)
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.editor-slide-upload {
+  margin-bottom: 20px;
+  ::v-deep .el-upload--picture-card {
+    width: 100%;
+  }
+}
+</style>

+ 59 - 0
ui/src/components/Tinymce/dynamicLoadScript.js

@@ -0,0 +1,59 @@
+let callbacks = []
+
+function loadedTinymce() {
+  // to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2144
+  // check is successfully downloaded script
+  return window.tinymce
+}
+
+const dynamicLoadScript = (src, callback) => {
+  const existingScript = document.getElementById(src)
+  const cb = callback || function() {}
+
+  if (!existingScript) {
+    const script = document.createElement('script')
+    script.src = src // src url for the third-party library being loaded.
+    script.id = src
+    document.body.appendChild(script)
+    callbacks.push(cb)
+    const onEnd = 'onload' in script ? stdOnEnd : ieOnEnd
+    onEnd(script)
+  }
+
+  if (existingScript && cb) {
+    if (loadedTinymce()) {
+      cb(null, existingScript)
+    } else {
+      callbacks.push(cb)
+    }
+  }
+
+  function stdOnEnd(script) {
+    script.onload = function() {
+      // this.onload = null here is necessary
+      // because even IE9 works not like others
+      this.onerror = this.onload = null
+      for (const cb of callbacks) {
+        cb(null, script)
+      }
+      callbacks = null
+    }
+    script.onerror = function() {
+      this.onerror = this.onload = null
+      cb(new Error('Failed to load ' + src), script)
+    }
+  }
+
+  function ieOnEnd(script) {
+    script.onreadystatechange = function() {
+      if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
+      this.onreadystatechange = null
+      for (const cb of callbacks) {
+        cb(null, script) // there is no way to catch loading errors in IE8
+      }
+      callbacks = null
+    }
+  }
+}
+
+export default dynamicLoadScript

+ 249 - 0
ui/src/components/Tinymce/index.vue

@@ -0,0 +1,249 @@
+<template>
+  <div :class="{fullscreen:fullscreen}" class="tinymce-container" :style="{width:containerWidth}">
+    <textarea :id="tinymceId" class="tinymce-textarea" />
+<!--  <div class="editor-custom-btn-container">
+      <editorImage color="#1890ff" class="editor-upload-btn" @successCBK="imageSuccessCBK" />
+    </div> -->
+  </div>
+</template>
+
+<script>
+/**
+ * docs:
+ * https://panjiachen.github.io/vue-element-admin-site/feature/component/rich-editor.html#tinymce
+ */
+// import editorImage from './components/EditorImage'
+import plugins from './plugins'
+import toolbar from './toolbar'
+import load from './dynamicLoadScript'
+
+// why use this cdn, detail see https://github.com/PanJiaChen/tinymce-all-in-one
+const tinymceCDN = 'https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.3/tinymce.min.js'
+// const tinymceCDN = '/js/tinymce.min.js'
+
+export default {
+  name: 'Tinymce',
+  // components: { editorImage },
+  props: {
+    id: {
+      type: String,
+      default: function() {
+        return 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
+      }
+    },
+    value: {
+      type: String,
+      default: ''
+    },
+    toolbar: {
+      type: Array,
+      required: false,
+      default() {
+        return []
+      }
+    },
+    menubar: {
+      type: String,
+      default: 'file edit insert view format table'
+    },
+    height: {
+      type: [Number, String],
+      required: false,
+      default: 360
+    },
+    width: {
+      type: [Number, String],
+      required: false,
+      default: 'auto'
+    }
+  },
+  data() {
+    return {
+      hasChange: false,
+      hasInit: false,
+      tinymceId: this.id,
+      fullscreen: false,
+      languageTypeList: {
+        'en': 'en',
+        'zh': 'zh_CN',
+        'es': 'es_MX',
+        'ja': 'ja'
+      }
+    }
+  },
+  computed: {
+    containerWidth() {
+      const width = this.width
+      if (/^[\d]+(\.[\d]+)?$/.test(width)) { // matches `100`, `'100'`
+        return `${width}px`
+      }
+      return width
+    }
+  },
+  watch: {
+    value(val) {
+      if (!this.hasChange && this.hasInit) {
+        this.$nextTick(() =>
+          window.tinymce.get(this.tinymceId).setContent(val || ''))
+      }
+    }
+  },
+  mounted() {
+    this.init()
+  },
+  activated() {
+    if (window.tinymce) {
+      this.initTinymce()
+    }
+  },
+  deactivated() {
+    this.destroyTinymce()
+  },
+  destroyed() {
+    this.destroyTinymce()
+  },
+  methods: {
+    init() {
+      // dynamic load tinymce from cdn
+      load(tinymceCDN, (err) => {
+        if (err) {
+          this.$message.error(err.message)
+          return
+        }
+        this.initTinymce()
+      })
+    },
+    initTinymce() {
+      const _this = this
+      window.tinymce.init({
+        selector: `#${this.tinymceId}`,
+        language: this.languageTypeList['en'],
+        height: this.height,
+        body_class: 'panel-body ',
+        object_resizing: false,
+        toolbar: this.toolbar.length >= 0 ? this.toolbar : toolbar,
+        menubar: this.menubar,
+        plugins: plugins,
+        end_container_on_empty_block: true,
+        powerpaste_word_import: 'clean',
+        code_dialog_height: 450,
+        code_dialog_width: 1000,
+        advlist_bullet_styles: 'square',
+        advlist_number_styles: 'default',
+        imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'],
+        default_link_target: '_blank',
+        link_title: false,
+        nonbreaking_force_tab: true, // inserting nonbreaking space &nbsp; need Nonbreaking Space Plugin
+        init_instance_callback: editor => {
+          if (_this.value) {
+            editor.setContent(_this.value)
+          }
+          _this.hasInit = true
+          editor.on('NodeChange Change KeyUp SetContent', () => {
+            this.hasChange = true
+            this.$emit('input', editor.getContent())
+          })
+        },
+        setup(editor) {
+          editor.on('FullscreenStateChanged', (e) => {
+            _this.fullscreen = e.state
+          })
+        },
+        // it will try to keep these URLs intact
+        // https://www.tiny.cloud/docs-3x/reference/configuration/Configuration3x@convert_urls/
+        // https://stackoverflow.com/questions/5196205/disable-tinymce-absolute-to-relative-url-conversions
+        convert_urls: false
+        // 整合七牛上传
+        // images_dataimg_filter(img) {
+        //   setTimeout(() => {
+        //     const $image = $(img);
+        //     $image.removeAttr('width');
+        //     $image.removeAttr('height');
+        //     if ($image[0].height && $image[0].width) {
+        //       $image.attr('data-wscntype', 'image');
+        //       $image.attr('data-wscnh', $image[0].height);
+        //       $image.attr('data-wscnw', $image[0].width);
+        //       $image.addClass('wscnph');
+        //     }
+        //   }, 0);
+        //   return img
+        // },
+        // images_upload_handler(blobInfo, success, failure, progress) {
+        //   progress(0);
+        //   const token = _this.$store.getters.token;
+        //   getToken(token).then(response => {
+        //     const url = response.data.qiniu_url;
+        //     const formData = new FormData();
+        //     formData.append('token', response.data.qiniu_token);
+        //     formData.append('key', response.data.qiniu_key);
+        //     formData.append('file', blobInfo.blob(), url);
+        //     upload(formData).then(() => {
+        //       success(url);
+        //       progress(100);
+        //     })
+        //   }).catch(err => {
+        //     failure('出现未知问题,刷新页面,或者联系程序员')
+        //     console.log(err);
+        //   });
+        // },
+      })
+    },
+    destroyTinymce() {
+      const tinymce = window.tinymce.get(this.tinymceId)
+      if (this.fullscreen) {
+        tinymce.execCommand('mceFullScreen')
+      }
+
+      if (tinymce) {
+        tinymce.destroy()
+      }
+    },
+    setContent(value) {
+      window.tinymce.get(this.tinymceId).setContent(value)
+    },
+    getContent() {
+      window.tinymce.get(this.tinymceId).getContent()
+    },
+    imageSuccessCBK(arr) {
+      arr.forEach(v => window.tinymce.get(this.tinymceId).insertContent(`<img class="wscnph" src="${v.url}" >`))
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.tinymce-container {
+  position: relative;
+  line-height: normal;
+  width:100%;
+}
+
+.tinymce-container {
+  ::v-deep {
+    .mce-fullscreen {
+      z-index: 10000;
+    }
+  }
+}
+
+.tinymce-textarea {
+  visibility: hidden;
+  z-index: -1;
+}
+
+.editor-custom-btn-container {
+  position: absolute;
+  right: 4px;
+  top: 4px;
+  /*z-index: 2005;*/
+}
+
+.fullscreen .editor-custom-btn-container {
+  z-index: 10000;
+  position: fixed;
+}
+
+.editor-upload-btn {
+  display: inline-block;
+}
+</style>

+ 7 - 0
ui/src/components/Tinymce/plugins.js

@@ -0,0 +1,7 @@
+// Any plugins you want to use has to be imported
+// Detail plugins list see https://www.tinymce.com/docs/plugins/
+// Custom builds see https://www.tinymce.com/download/custom-builds/
+
+const plugins = ['advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount']
+
+export default plugins

File diff suppressed because it is too large
+ 1 - 0
ui/src/components/Tinymce/tinymce.min.js


+ 6 - 0
ui/src/components/Tinymce/toolbar.js

@@ -0,0 +1,6 @@
+// Here is a list of the toolbar
+// Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
+
+const toolbar = ['searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent  blockquote undo redo removeformat subscript superscript code codesample', 'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen']
+
+export default toolbar

+ 173 - 0
ui/src/views/ProductMent/Category/index.vue

@@ -0,0 +1,173 @@
+<template>
+    <div class="category-container">
+      <!-- 顶部操作区 -->
+      <div class="operation-area">
+        <el-button type="primary" @click="handleAdd">新建产品类别</el-button>
+        <el-input
+          v-model="searchQuery"
+          placeholder="请输入搜索内容"
+          style="width: 200px; margin-left: 16px"
+          @keyup.enter.native="handleSearch"
+        >
+          <el-button slot="append" icon="el-icon-search" @click="handleSearch"></el-button>
+        </el-input>
+      </div>
+  
+      <!-- 表格区域 -->
+      <el-table :data="tableData"  style="width: 100%; margin-top: 20px">
+        <el-table-column prop="categoryId" label="产品类别编号" width="180"></el-table-column>
+        <el-table-column prop="categoryName" label="产品类别" width="180"></el-table-column>
+        <el-table-column prop="remark" label="备注"></el-table-column>
+        <el-table-column prop="skuCount" label="关联sku数"></el-table-column>
+        <el-table-column label="操作" width="250">
+          <template slot-scope="scope">
+            <el-button size="mini" @click="handleView(scope.row)">查看</el-button>
+            <el-button size="mini" type="primary" @click="handleEdit(scope.row)">编辑</el-button>
+            <el-button size="mini" type="danger" @click="handleDelete(scope.row)">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+  
+      <!-- 分页 -->
+      <el-pagination
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+        :current-page="pagination.currentPage"
+        :page-sizes="[10, 20, 50, 100]"
+        :page-size="pagination.pageSize"
+        layout="total, sizes, prev, pager, next, jumper"
+        :total="pagination.total"
+        style="margin-top: 20px; text-align: right"
+      >
+      </el-pagination>
+  
+      <!-- 新增/编辑对话框 -->
+      <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="500px">
+        <el-form :model="form" :rules="rules" ref="form" label-width="100px">
+          <el-form-item label="类别编号" prop="categoryId">
+            <el-input v-model="form.categoryId"></el-input>
+          </el-form-item>
+          <el-form-item label="类别名称" prop="categoryName">
+            <el-input v-model="form.categoryName"></el-input>
+          </el-form-item>
+          <el-form-item label="备注" prop="remark">
+            <el-input type="textarea" v-model="form.remark"></el-input>
+          </el-form-item>
+        </el-form>
+        <div slot="footer">
+          <el-button @click="dialogVisible = false">取 消</el-button>
+          <el-button type="primary" @click="submitForm">确 定</el-button>
+        </div>
+      </el-dialog>
+    </div>
+  </template>
+  
+  <script>
+  export default {
+    name: 'CategoryManagement',
+    data() {
+      return {
+        searchQuery: '',
+        tableData: [
+          {
+            categoryId: 'ysp',
+            categoryName: '音视频',
+            remark: '',
+            skuCount: 5
+          }
+        ],
+        pagination: {
+          currentPage: 1,
+          pageSize: 10,
+          total: 0
+        },
+        dialogVisible: false,
+        dialogTitle: '',
+        form: {
+          categoryId: '',
+          categoryName: '',
+          remark: ''
+        },
+        rules: {
+          categoryId: [
+            { required: true, message: '请输入类别编号', trigger: 'blur' }
+          ],
+          categoryName: [
+            { required: true, message: '请输入类别名称', trigger: 'blur' }
+          ]
+        }
+      }
+    },
+    methods: {
+      handleSearch() {
+        // 实现搜索逻辑
+        console.log('搜索关键词:', this.searchQuery)
+        this.loadData()
+      },
+      handleAdd() {
+        this.dialogTitle = '新增产品类别'
+        this.form = {
+          categoryId: '',
+          categoryName: '',
+          remark: ''
+        }
+        this.dialogVisible = true
+      },
+      handleEdit(row) {
+        this.dialogTitle = '编辑产品类别'
+        this.form = { ...row }
+        this.dialogVisible = true
+      },
+      handleDelete(row) {
+        this.$confirm('确认删除该产品类别?', '提示', {
+          type: 'warning'
+        }).then(() => {
+          // 实现删除逻辑
+          console.log('删除:', row)
+          this.$message.success('删除成功')
+          this.loadData()
+        }).catch(() => {})
+      },
+      handleView(row) {
+        // 实现查看逻辑
+        console.log('查看:', row)
+      },
+      handleSizeChange(val) {
+        this.pagination.pageSize = val
+        this.loadData()
+      },
+      handleCurrentChange(val) {
+        this.pagination.currentPage = val
+        this.loadData()
+      },
+      submitForm() {
+        this.$refs.form.validate((valid) => {
+          if (valid) {
+            // 实现表单提交逻辑
+            console.log('表单数据:', this.form)
+            this.dialogVisible = false
+            this.$message.success('保存成功')
+            this.loadData()
+          }
+        })
+      },
+      loadData() {
+        // 实现数据加载逻辑
+        console.log('加载数据,当前页:', this.pagination.currentPage, '每页数量:', this.pagination.pageSize)
+      }
+    },
+    created() {
+      this.loadData()
+    }
+  }
+  </script>
+  
+  <style scoped>
+  .category-container {
+    padding: 20px;
+  }
+  .operation-area {
+    display: flex;
+    align-items: center;
+  }
+  </style>

+ 466 - 0
ui/src/views/ProductMent/ProductManagement.vue

@@ -0,0 +1,466 @@
+<template>
+  <div class="product-management">
+    <!-- 左侧产品分类 -->
+    <div class="category-sidebar">
+      <div class="category-header">
+        <span>请选择产品分类</span>
+        <el-button type="primary" size="small" @click="handleAddCategory"
+          >新建分类</el-button
+        >
+      </div>
+
+      <el-tree :data="categoryData" node-key="id" default-expand-all>
+        <span class="custom-tree-node" slot-scope="{ node, data }">
+          <span>{{ node.label }}</span>
+          <span class="operations">
+            <i class="el-icon-plus" @click="handleAdd(data)"></i>
+            <i class="el-icon-minus" @click="handleDelete(node, data)"></i>
+            <i class="el-icon-edit" @click="handleEdit(data)"></i>
+          </span>
+        </span>
+      </el-tree>
+    </div>
+
+    <!-- 右侧产品列表 -->
+    <div class="product-content">
+      <div class="content-header">
+        <!--  <div class="breadcrumb">首页—产品库—产品管理</div> -->
+        <div class="search-area">
+          <el-input
+            v-model="searchKeyword"
+            placeholder="请输入关键字搜索"
+            class="search-input"
+          >
+            <el-button slot="append" icon="el-icon-search"></el-button>
+          </el-input>
+          <el-button type="primary" @click="handleAddProduct"
+            >新建产品</el-button
+          >
+        </div>
+      </div>
+
+      <el-table :data="productList">
+        <el-table-column prop="oaNumber" label="OA编号" />
+        <el-table-column prop="productCode" label="产品编号" />
+        <el-table-column prop="productName" label="产品名称" />
+        <el-table-column prop="description" label="产品描述" />
+        <el-table-column prop="productType" label="产品型号" />
+        <el-table-column prop="length" label="长宽比" />
+        <el-table-column prop="resolution" label="刷新率" />
+        <el-table-column prop="screenMaterial" label="屏幕材质" />
+        <el-table-column label="操作" width="200">
+          <template slot-scope="scope">
+            <el-button size="mini" @click="handleEditProduct(scope.row)"
+              >编辑</el-button
+            >
+            <el-button
+              size="mini"
+              type="danger"
+              @click="handleDeleteProduct(scope.row)"
+              >删除</el-button
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+      <!-- 添加分页组件 -->
+      <div class="pagination-container">
+        <el-pagination
+          @current-change="handleCurrentChange"
+          :current-page="pagination.currentPage"
+          :page-size="pagination.pageSize"
+          :total="pagination.total"
+          layout="total, prev, pager, next"
+        >
+        </el-pagination>
+      </div>
+    </div>
+
+    <!-- 添加分类对话框 -->
+    <el-dialog
+      :title="dialogType === 'add' ? '新增分类' : '编辑分类'"
+      :visible.sync="categoryDialogVisible"
+      width="500px"
+    >
+      <el-form :model="categoryForm" label-width="80px">
+        <el-form-item label="分类名称">
+          <el-input
+            v-model="categoryForm.label"
+            placeholder="请输入分类名称"
+          ></el-input>
+        </el-form-item>
+      </el-form>
+      <span slot="footer">
+        <el-button @click="categoryDialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="handleCategorySubmit"
+          >确 定</el-button
+        >
+      </span>
+    </el-dialog>
+
+    <!-- 添加产品对话框 -->
+    <el-dialog
+      :title="dialogType === 'add' ? '新增产品' : '编辑产品'"
+      :visible.sync="productDialogVisible"
+      width="650px"
+    >
+      <el-form :model="productForm" label-width="100px">
+        <el-form-item label="OA编号">
+          <el-input v-model="productForm.oaNumber"></el-input>
+        </el-form-item>
+        <el-form-item label="产品编号">
+          <el-input v-model="productForm.productCode"></el-input>
+        </el-form-item>
+        <el-form-item label="产品名称">
+          <el-input v-model="productForm.productName"></el-input>
+        </el-form-item>
+        <el-form-item label="产品描述">
+          <el-input
+            type="textarea"
+            v-model="productForm.description"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="产品型号">
+          <el-input v-model="productForm.productType"></el-input>
+        </el-form-item>
+        <el-form-item label="长宽比">
+          <el-input v-model="productForm.length"></el-input>
+        </el-form-item>
+        <el-form-item label="刷新率">
+          <el-input v-model="productForm.resolution"></el-input>
+        </el-form-item>
+        <el-form-item label="屏幕材质">
+          <el-input v-model="productForm.screenMaterial"></el-input>
+        </el-form-item>
+      </el-form>
+      <span slot="footer">
+        <el-button @click="productDialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="handleProductSubmit">确 定</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+  
+  <script>
+export default {
+  name: "ProductManagement",
+  data() {
+    return {
+      searchKeyword: "",
+      categoryData: [
+        {
+          id: 1,
+          label: "LED产品",
+          children: [],
+        },
+        {
+          id: 2,
+          label: "LCD产品",
+          children: [],
+        },
+        {
+          id: 3,
+          label: "集成产品",
+          children: [
+            {
+              id: 31,
+              label: "集成产品A",
+            },
+            {
+              id: 32,
+              label: "集成产品B",
+            },
+            {
+              id: 33,
+              label: "集成产品C",
+            },
+          ],
+        },
+      ],
+      productList: [
+        {
+          oaNumber: "12345668",
+          productCode: "DLP11443",
+          productName: "DLP高级拼接屏",
+          description: "",
+          productType: "",
+          length: "",
+          resolution: "",
+          screenMaterial: "",
+        },
+      ],
+      // 添加对话框控制变量
+      categoryDialogVisible: false,
+      productDialogVisible: false,
+      dialogType: "add", // 'add' 或 'edit'
+
+      // 表单数据
+      categoryForm: {
+        label: "",
+        parentId: null,
+      },
+
+      productForm: {
+        oaNumber: "",
+        productCode: "",
+        productName: "",
+        description: "",
+        productType: "",
+        length: "",
+        resolution: "",
+        screenMaterial: "",
+        categoryId: null,
+      },
+
+      // 当前选中的分类
+      currentCategory: null,
+
+      // 分页参数
+      pagination: {
+        currentPage: 1,
+        pageSize: 10,
+        total: 0,
+      },
+    };
+  },
+  mounted() {
+    this.fetchCategoryList();
+    this.fetchProductList();
+  },
+  methods: {
+    // 获取分类列表
+    async fetchCategoryList() {
+      try {
+        // const { data } = await this.$api.category.getList()
+        // this.categoryData = data
+        // 模拟API调用
+        console.log("获取分类列表");
+      } catch (error) {
+        this.$message.error("获取分类列表失败");
+      }
+    },
+
+    // 获取产品列表
+    async fetchProductList() {
+      try {
+        // const params = {
+        //   categoryId: this.currentCategory?.id,
+        //   keyword: this.searchKeyword,
+        //   page: this.pagination.currentPage,
+        //   pageSize: this.pagination.pageSize
+        // }
+        // const { data, total } = await this.$api.product.getList(params)
+        // this.productList = data
+        // this.pagination.total = total
+        // 模拟API调用
+        console.log("获取产品列表");
+      } catch (error) {
+        this.$message.error("获取产品列表失败");
+      }
+    },
+
+    // 分类相关方法
+    handleAddCategory() {
+      this.dialogType = "add";
+      this.categoryForm = { label: "", parentId: null };
+      this.categoryDialogVisible = true;
+    },
+    /* 新增产品分类 */
+    handleAdd(data) {
+      this.dialogType = "add";
+      this.categoryForm = { label: "", parentId: data.id };
+      this.categoryDialogVisible = true;
+    },
+    /* 编辑产品分类 */
+    handleEdit(data) {
+      this.dialogType = "edit";
+      this.categoryForm = { ...data };
+      this.categoryDialogVisible = true;
+    },
+
+    async handleCategorySubmit() {
+      try {
+        if (!this.categoryForm.label.trim()) {
+          return this.$message.warning("请输入分类名称");
+        }
+
+        if (this.dialogType === "add") {
+          // await this.$api.category.create(this.categoryForm)
+          this.$message.success("添加分类成功");
+        } else {
+          // await this.$api.category.update(this.categoryForm)
+          this.$message.success("编辑分类成功");
+        }
+
+        this.categoryDialogVisible = false;
+        this.fetchCategoryList();
+      } catch (error) {
+        this.$message.error("操作失败");
+      }
+    },
+    /* 删除产品分类 */
+    async handleDelete(node, data) {
+      try {
+        await this.$confirm("确认删除该分类吗?删除后无法恢复", "提示", {
+          type: "warning",
+        });
+
+        // await this.$api.category.delete(data.id)
+        this.$message.success("删除成功");
+        this.fetchCategoryList();
+      } catch (error) {
+        if (error !== "cancel") {
+          this.$message.error("删除失败");
+        }
+      }
+    },
+
+    // 产品相关方法
+    handleAddProduct() {
+       this.$router.push("ProductMent/newProduct/index")
+     /*  this.dialogType = "add";
+      this.productForm = {
+        oaNumber: "",
+        productCode: "",
+        productName: "",
+        description: "",
+        productType: "",
+        length: "",
+        resolution: "",
+        screenMaterial: "",
+        categoryId: this.currentCategory?.id,
+      };
+      this.productDialogVisible = true; */
+    },
+    /* 编辑产品 */
+    handleEditProduct(row) {
+      this.dialogType = "edit";
+      this.productForm = { ...row };
+      this.productDialogVisible = true;
+    },
+
+    async handleProductSubmit() {
+      try {
+        if (!this.productForm.productName.trim()) {
+          return this.$message.warning("请输入产品名称");
+        }
+
+        if (this.dialogType === "add") {
+          // await this.$api.product.create(this.productForm)
+          this.$message.success("添加产品成功");
+        } else {
+          // await this.$api.product.update(this.productForm)
+          this.$message.success("编辑产品成功");
+        }
+
+        this.productDialogVisible = false;
+        this.fetchProductList();
+      } catch (error) {
+        this.$message.error("操作失败");
+      }
+    },
+    /* 删除产品列表 */
+    async handleDeleteProduct(row) {
+      try {
+        await this.$confirm("确认删除该产品吗?删除后无法恢复", "提示", {
+          type: "warning",
+        });
+
+        // await this.$api.product.delete(row.id)
+        this.$message.success("删除成功");
+        this.fetchProductList();
+      } catch (error) {
+        if (error !== "cancel") {
+          this.$message.error("删除失败");
+        }
+      }
+    },
+
+    // 搜索和分页
+    handleSearch() {
+      this.pagination.currentPage = 1;
+      this.fetchProductList();
+    },
+
+    handleCurrentChange(page) {
+      this.pagination.currentPage = page;
+      this.fetchProductList();
+    },
+
+    // 分类选择
+    handleNodeClick(data) {
+      this.currentCategory = data;
+      this.pagination.currentPage = 1;
+      this.fetchProductList();
+    },
+  },
+};
+</script>
+  
+  <style scoped>
+.product-management {
+  display: flex;
+  height: 100%;
+}
+
+.category-sidebar {
+  width: 250px;
+  border-right: 1px solid #ebeef5;
+  padding: 20px;
+}
+
+.category-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+}
+
+.product-content {
+  flex: 1;
+  padding: 20px;
+}
+
+.content-header {
+  margin-bottom: 20px;
+}
+
+.search-area {
+  display: flex;
+  justify-content: space-between;
+  margin-top: 20px;
+}
+
+.search-input {
+  width: 300px;
+}
+
+.custom-tree-node {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding-right: 8px;
+}
+
+.operations {
+  display: none;
+}
+
+.custom-tree-node:hover .operations {
+  display: inline-block;
+}
+
+.operations i {
+  margin-left: 8px;
+  cursor: pointer;
+}
+
+.breadcrumb {
+  font-size: 14px;
+  color: #606266;
+}
+/* .pagination-container {
+  margin-top: 20px;
+  text-align: right;
+} */
+</style>

+ 402 - 0
ui/src/views/ProductMent/newProduct/index.vue

@@ -0,0 +1,402 @@
+<template>
+  <div class="product-container">
+    <!-- 产品基本信息表单 -->
+    <el-form
+      :model="productForm"
+      :rules="rules"
+      ref="productForm"
+      label-width="100px"
+    >
+      <el-tabs v-model="activeTab">
+        <el-tab-pane label="产品基本信息" name="basic">
+          <el-form-item label="工程类别" prop="projectType">
+            <el-select v-model="productForm.projectType" placeholder="请选择">
+              <el-option
+                v-for="item in projectTypes"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+
+          <el-form-item label="系统类别" prop="systemType">
+            <el-select v-model="productForm.systemType" placeholder="请选择">
+              <el-option
+                v-for="item in systemTypes"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+
+          <el-form-item label="产品类别">
+            <el-select v-model="productForm.productType" placeholder="请选择">
+              <el-option
+                v-for="item in productTypes"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+
+          <el-form-item label="产品名称">
+            <el-input v-model="productForm.productName" placeholder="请输入" />
+          </el-form-item>
+          <!-- 新增规格表单部分 -->
+          <div class="specs-form">
+            <div class="specs-header">
+              <span>产品规格及型号</span>
+              <div class="spec-tags">
+                <el-button-group>
+                  <el-button
+                    size="small"
+                    :type="activeSpecs.aspectRatio ? 'primary' : ''"
+                    @click="toggleSpec('aspectRatio')"
+                    >长宽比</el-button
+                  >
+                  <el-button
+                    size="small"
+                    :type="activeSpecs.refreshRate ? 'primary' : ''"
+                    @click="toggleSpec('refreshRate')"
+                    >刷新率</el-button
+                  >
+                  <el-button
+                    size="small"
+                    :type="activeSpecs.resolution ? 'primary' : ''"
+                    @click="toggleSpec('resolution')"
+                    >分辨率</el-button
+                  >
+                  <el-button
+                    size="small"
+                    :type="activeSpecs.material ? 'primary' : ''"
+                    @click="toggleSpec('material')"
+                    >屏幕材质</el-button
+                  >
+                  <el-button
+                    size="small"
+                    icon="el-icon-plus"
+                    @click="addNewSpec"
+                  ></el-button>
+                </el-button-group>
+              </div>
+            </div>
+
+            <!-- 长宽比输入 -->
+            <el-form-item label="长宽比:" v-if="activeSpecs.aspectRatio">
+              <el-input
+                v-model="specForm.aspectRatio.width"
+                style="width: 100px"
+              ></el-input>
+              <span class="ratio-separator">:</span>
+              <el-input
+                v-model="specForm.aspectRatio.height"
+                style="width: 100px"
+              ></el-input>
+              <el-button
+                type="text"
+                icon="el-icon-plus"
+                @click="addAspectRatio"
+              ></el-button>
+              <el-button
+                type="text"
+                icon="el-icon-minus"
+                @click="removeAspectRatio"
+              ></el-button>
+            </el-form-item>
+
+            <!-- 刷新率选择 -->
+            <el-form-item label="刷新率:" v-if="activeSpecs.refreshRate">
+              <el-select v-model="specForm.refreshRate" placeholder="复选等级">
+                <el-option
+                  v-for="item in refreshRateOptions"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                >
+                </el-option>
+              </el-select>
+              <el-button
+                type="text"
+                icon="el-icon-minus"
+                @click="removeRefreshRate"
+              ></el-button>
+            </el-form-item>
+
+            <!-- 分辨率选择 -->
+            <el-form-item label="分辨率:" v-if="activeSpecs.resolution">
+              <el-select v-model="specForm.resolution" placeholder="复选等级">
+                <el-option
+                  v-for="item in resolutionOptions"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                >
+                </el-option>
+              </el-select>
+              <el-button
+                type="text"
+                icon="el-icon-minus"
+                @click="removeResolution"
+              ></el-button>
+            </el-form-item>
+
+            <!-- 屏幕材质选择 -->
+            <el-form-item label="屏幕材质:" v-if="activeSpecs.material">
+              <el-select v-model="specForm.material" placeholder="复选等级">
+                <el-option
+                  v-for="item in materialOptions"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                >
+                </el-option>
+              </el-select>
+              <el-button
+                type="text"
+                icon="el-icon-minus"
+                @click="removeMaterial"
+              ></el-button>
+            </el-form-item>
+
+            <el-button type="primary" @click="generateSpec">生成</el-button>
+          </div>
+
+          <!-- 规格列表表格 -->
+          <el-table
+            :data="specsList"
+            border
+            style="width: 100%; margin-top: 20px"
+          >
+            <el-table-column prop="oaNumber" label="OA编号" />
+            <el-table-column prop="productCode" label="产品编号" />
+            <el-table-column prop="productName" label="产品名称" />
+            <el-table-column prop="description" label="产品描述" />
+            <el-table-column prop="model" label="产品型号" />
+            <el-table-column prop="aspectRatio" label="长宽比" />
+            <el-table-column prop="refreshRate" label="刷新率" />
+            <el-table-column prop="material" label="屏幕材质" />
+            <el-table-column label="操作" width="150">
+              <template slot-scope="scope">
+                <el-button
+                  type="text"
+                  size="small"
+                  @click="handleAdd(scope.row)"
+                  >添加</el-button
+                >
+                <el-button
+                  type="text"
+                  size="small"
+                  @click="handleDelete(scope.$index)"
+                  >删除</el-button
+                >
+              </template>
+            </el-table-column>
+          </el-table>
+
+          <div class="button-group">
+            <el-button type="primary" @click="batchAdd">批量添加</el-button>
+          </div>
+        </el-tab-pane>
+
+        <!-- 规格及型号标签页 -->
+        <el-tab-pane label="规格及型号" name="specs"> </el-tab-pane>
+      </el-tabs>
+    </el-form>
+  </div>
+</template>
+  
+  <script>
+export default {
+  name: "NewProduct",
+  data() {
+    return {
+      activeTab: "basic",
+      productForm: {
+        projectType: "",
+        systemType: "",
+        productType: "",
+        productName: "",
+      },
+      // 规格相关数据
+      specs: {
+        aspectRatio: { width: "", height: "" },
+        refreshRate: "",
+        resolution: "",
+        material: "",
+      },
+      specsList: [], // 规格列表
+      rules: {
+        projectType: [
+          { required: true, message: "请选择工程类别", trigger: "change" },
+        ],
+        systemType: [
+          { required: true, message: "请选择系统类别", trigger: "change" },
+        ],
+      },
+      // 新增数据
+      activeSpecs: {
+        aspectRatio: false,
+        refreshRate: false,
+        resolution: false,
+        material: false,
+      },
+      specForm: {
+        aspectRatio: {
+          width: "19",
+          height: "6",
+        },
+        refreshRate: "",
+        resolution: "",
+        material: "",
+      },
+      refreshRateOptions: [
+        { value: "60Hz", label: "60Hz" },
+        { value: "120Hz", label: "120Hz" },
+        { value: "144Hz", label: "144Hz" },
+      ],
+      resolutionOptions: [
+        { value: "1080p", label: "1080p" },
+        { value: "2K", label: "2K" },
+        { value: "4K", label: "4K" },
+      ],
+      materialOptions: [
+        { value: "LED", label: "LED" },
+        { value: "LCD", label: "LCD" },
+        { value: "OLED", label: "OLED" },
+      ],
+    };
+  },
+  computed: {
+    hasAspectRatio() {
+      return this.specs.aspectRatio.width || this.specs.aspectRatio.height;
+    },
+  },
+  methods: {
+    // 添加规格
+    addSpec(type) {
+      if (type === "aspectRatio") {
+        this.specs.aspectRatio = { width: "19", height: "6" };
+      }
+      // 其他规格类型处理...
+    },
+
+    // 移除规格
+    removeSpec(type) {
+      if (type === "aspectRatio") {
+        this.specs.aspectRatio = { width: "", height: "" };
+      }
+    },
+
+    // 添加到列表
+    addToList(row) {
+      this.specsList.push({
+        oaNumber: "12345668",
+        productCode: "DLP11443",
+        productName: "DLP高级拼接屏",
+        ...row,
+      });
+    },
+
+    // 从列表中移除
+    removeFromList(index) {
+      this.specsList.splice(index, 1);
+    },
+
+    // 批量添加
+    batchAdd() {
+      // 实现批量添加逻辑
+    },
+
+    // 保存所有数据
+    saveAll() {
+      this.$refs.productForm.validate((valid) => {
+        if (valid) {
+          // 实现保存逻辑
+          console.log("保存数据", this.productForm, this.specsList);
+        }
+      });
+    },
+    // 切换规格显示状态
+    toggleSpec(type) {
+      this.activeSpecs[type] = !this.activeSpecs[type];
+    },
+
+    // 添加新规格
+    addNewSpec() {
+      // 实现添加新规格的逻辑
+    },
+
+    // 生成规格
+    generateSpec() {
+      const newSpec = {
+        oaNumber: "12345668",
+        productCode: "DLP11443",
+        productName: "DLP高级拼接屏",
+        aspectRatio: `${this.specForm.aspectRatio.width}:${this.specForm.aspectRatio.height}`,
+        refreshRate: this.specForm.refreshRate,
+        resolution: this.specForm.resolution,
+        material: this.specForm.material,
+      };
+      this.specsList.push(newSpec);
+    },
+
+    // 处理添加操作
+    handleAdd(row) {
+      // 实现添加逻辑
+    },
+
+    // 处理删除操作
+    handleDelete(index) {
+      this.specsList.splice(index, 1);
+    },
+  },
+};
+</script>
+  
+  <style scoped>
+.product-container {
+  padding: 20px;
+}
+
+.specs-container {
+  margin-top: 20px;
+}
+
+.specs-header {
+  margin-bottom: 20px;
+}
+
+.button-container {
+  margin-top: 20px;
+  text-align: center;
+}
+.specs-form {
+  margin-top: 20px;
+  padding: 20px;
+  border: 1px solid #EBEEF5;
+  border-radius: 4px;
+}
+
+.specs-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+}
+
+.ratio-separator {
+  margin: 0 10px;
+}
+
+.button-group {
+  margin-top: 20px;
+  text-align: right;
+}
+
+.spec-tags {
+  margin-bottom: 15px;
+}
+</style>

+ 224 - 0
ui/src/views/ProductMent/specMent/index.vue

@@ -0,0 +1,224 @@
+<template>
+    <div class="spec-container">
+      <!-- 顶部操作区 -->
+      <div class="operation-area">
+        <el-button type="primary" @click="handleAdd">新建规格</el-button>
+        <el-input
+          v-model="searchQuery"
+          placeholder="请输入规格编号或名称"
+          style="width: 200px; margin-left: 16px"
+          @keyup.enter.native="handleSearch"
+        >
+          <el-button slot="append" icon="el-icon-search" @click="handleSearch"></el-button>
+        </el-input>
+      </div>
+  
+      <!-- 表格区域 -->
+      <el-table :data="tableData"  style="width: 100%; margin-top: 20px">
+        <el-table-column prop="specCode" label="规格编号" width="120"></el-table-column>
+        <el-table-column prop="specName" label="规格名称" width="120"></el-table-column>
+        <el-table-column prop="specType" label="规格值类型" width="120">
+          <template slot-scope="scope">
+            <el-tag :type="scope.row.specType === '输入' ? 'primary' : scope.row.specType === '单选' ? 'success' : 'warning'">
+              {{ scope.row.specType }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="specValue" label="规格值" width="180"></el-table-column>
+        <el-table-column prop="category" label="所属分类"></el-table-column>
+        <el-table-column label="操作" width="250">
+          <template slot-scope="scope">
+            <el-button size="mini" @click="handleView(scope.row)">查看</el-button>
+            <el-button size="mini" type="primary" @click="handleEdit(scope.row)">编辑</el-button>
+            <el-button size="mini" type="danger" @click="handleDelete(scope.row)">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+  
+      <!-- 分页 -->
+      <el-pagination
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+        :current-page="pagination.currentPage"
+        :page-sizes="[10, 20, 50, 100]"
+        :page-size="pagination.pageSize"
+        layout="total, sizes, prev, pager, next, jumper"
+        :total="pagination.total"
+        style="margin-top: 20px; text-align: right"
+      >
+      </el-pagination>
+  
+      <!-- 新增/编辑对话框 -->
+      <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="500px">
+        <el-form :model="form" :rules="rules" ref="form" label-width="100px">
+          <el-form-item label="规格编号" prop="specCode">
+            <el-input v-model="form.specCode"></el-input>
+          </el-form-item>
+          <el-form-item label="规格名称" prop="specName">
+            <el-input v-model="form.specName"></el-input>
+          </el-form-item>
+          <el-form-item label="规格值类型" prop="specType">
+            <el-select v-model="form.specType" style="width: 100%">
+              <el-option label="输入" value="输入"></el-option>
+              <el-option label="单选" value="单选"></el-option>
+              <el-option label="复选" value="复选"></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="规格值" prop="specValue">
+            <el-input v-model="form.specValue" type="textarea" 
+              placeholder="多个值请用逗号分隔"></el-input>
+          </el-form-item>
+          <el-form-item label="所属分类" prop="category">
+            <el-select v-model="form.category" style="width: 100%">
+              <el-option label="全部" value="全部"></el-option>
+              <el-option label="LCD,LED" value="LCD,LED"></el-option>
+              <el-option label="DLP" value="DLP"></el-option>
+            </el-select>
+          </el-form-item>
+        </el-form>
+        <div slot="footer">
+          <el-button @click="dialogVisible = false">取 消</el-button>
+          <el-button type="primary" @click="submitForm">确 定</el-button>
+        </div>
+      </el-dialog>
+    </div>
+  </template>
+  
+  <script>
+  export default {
+    name: 'SpecManagement',
+    data() {
+      return {
+        searchQuery: '',
+        tableData: [
+          {
+            specCode: 'ckb',
+            specName: '长宽比',
+            specType: '输入',
+            specValue: '',
+            category: '全部'
+          },
+          {
+            specCode: 'sxl',
+            specName: '刷新率',
+            specType: '单选',
+            specValue: '75, 100, 120',
+            category: 'LCD,LED'
+          },
+          {
+            specCode: 'pmcz',
+            specName: '屏幕材质',
+            specType: '复选',
+            specValue: '有机玻璃, 树脂',
+            category: 'DLP'
+          },
+          {
+            specCode: 'whfs',
+            specName: '维护方式',
+            specType: '单选',
+            specValue: '前维护, 后维护',
+            category: ''
+          }
+        ],
+        pagination: {
+          currentPage: 1,
+          pageSize: 10,
+          total: 4
+        },
+        dialogVisible: false,
+        dialogTitle: '',
+        form: {
+          specCode: '',
+          specName: '',
+          specType: '',
+          specValue: '',
+          category: ''
+        },
+        rules: {
+          specCode: [
+            { required: true, message: '请输入规格编号', trigger: 'blur' }
+          ],
+          specName: [
+            { required: true, message: '请输入规格名称', trigger: 'blur' }
+          ],
+          specType: [
+            { required: true, message: '请选择规格值类型', trigger: 'change' }
+          ]
+        }
+      }
+    },
+    methods: {
+      handleSearch() {
+        // 实现搜索逻辑
+        console.log('搜索关键词:', this.searchQuery)
+        this.loadData()
+      },
+      handleAdd() {
+        this.dialogTitle = '新增规格'
+        this.form = {
+          specCode: '',
+          specName: '',
+          specType: '',
+          specValue: '',
+          category: ''
+        }
+        this.dialogVisible = true
+      },
+      handleEdit(row) {
+        this.dialogTitle = '编辑规格'
+        this.form = { ...row }
+        this.dialogVisible = true
+      },
+      handleDelete(row) {
+        this.$confirm('确认删除该规格?', '提示', {
+          type: 'warning'
+        }).then(() => {
+          // 实现删除逻辑
+          console.log('删除:', row)
+          this.$message.success('删除成功')
+          this.loadData()
+        }).catch(() => {})
+      },
+      handleView(row) {
+        // 实现查看逻辑
+        console.log('查看:', row)
+      },
+      handleSizeChange(val) {
+        this.pagination.pageSize = val
+        this.loadData()
+      },
+      handleCurrentChange(val) {
+        this.pagination.currentPage = val
+        this.loadData()
+      },
+      submitForm() {
+        this.$refs.form.validate((valid) => {
+          if (valid) {
+            // 实现表单提交逻辑
+            console.log('表单数据:', this.form)
+            this.dialogVisible = false
+            this.$message.success('保存成功')
+            this.loadData()
+          }
+        })
+      },
+      loadData() {
+        // 实现数据加载逻辑
+        console.log('加载数据,当前页:', this.pagination.currentPage, '每页数量:', this.pagination.pageSize)
+      }
+    },
+    created() {
+      this.loadData()
+    }
+  }
+  </script>
+  
+  <style scoped>
+  .spec-container {
+    padding: 20px;
+  }
+  .operation-area {
+    display: flex;
+    align-items: center;
+  }
+  </style>

+ 247 - 0
ui/src/views/ProductMent/sysCategory/index.vue

@@ -0,0 +1,247 @@
+<template>
+    <div class="system-category-container">
+      <!-- 顶部操作区 -->
+      <div class="operation-area">
+        <el-button type="primary" @click="handleAdd">新建系统类别</el-button>
+        <el-input
+          v-model="searchQuery"
+          placeholder="请输入系统类别编号或名称"
+          style="width: 200px; margin-left: 16px"
+          @keyup.enter.native="handleSearch"
+        >
+          <el-button slot="append" icon="el-icon-search" @click="handleSearch"></el-button>
+        </el-input>
+      </div>
+  
+      <!-- 表格区域 -->
+      <el-table 
+        :data="tableData" 
+         
+        style="width: 100%; margin-top: 20px"
+        v-loading="loading"
+      >
+        <el-table-column prop="systemCode" label="系统类别编号" width="180"></el-table-column>
+        <el-table-column prop="systemName" label="系统类别名称" width="180"></el-table-column>
+        <el-table-column prop="remark" label="备注"></el-table-column>
+        <el-table-column prop="productCount" label="产品数" width="120"></el-table-column>
+        <el-table-column label="操作" width="250" fixed="right">
+          <template slot-scope="scope">
+            <el-button size="mini" @click="handleView(scope.row)">查看</el-button>
+            <el-button size="mini" type="primary" @click="handleEdit(scope.row)">编辑</el-button>
+            <el-button size="mini" type="danger" @click="handleDelete(scope.row)">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+  
+      <!-- 分页 -->
+      <el-pagination
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+        :current-page="pagination.currentPage"
+        :page-sizes="[10, 20, 50, 100]"
+        :page-size="pagination.pageSize"
+        layout="total, sizes, prev, pager, next, jumper"
+        :total="pagination.total"
+        style="margin-top: 20px; text-align: right"
+      >
+      </el-pagination>
+  
+      <!-- 新增/编辑对话框 -->
+      <el-dialog 
+        :title="dialogTitle" 
+        :visible.sync="dialogVisible" 
+        width="500px"
+        :close-on-click-modal="false"
+      >
+        <el-form 
+          :model="form" 
+          :rules="rules" 
+          ref="form" 
+          label-width="120px"
+          :validate-on-rule-change="false"
+        >
+          <el-form-item label="系统类别编号" prop="systemCode">
+            <el-input v-model="form.systemCode" :disabled="dialogTitle === '编辑系统类别'"></el-input>
+          </el-form-item>
+          <el-form-item label="系统类别名称" prop="systemName">
+            <el-input v-model="form.systemName"></el-input>
+          </el-form-item>
+          <el-form-item label="备注" prop="remark">
+            <el-input type="textarea" v-model="form.remark" rows="3"></el-input>
+          </el-form-item>
+        </el-form>
+        <div slot="footer">
+          <el-button @click="cancelForm">取 消</el-button>
+          <el-button type="primary" @click="submitForm" :loading="submitLoading">确 定</el-button>
+        </div>
+      </el-dialog>
+  
+      <!-- 查看详情对话框 -->
+      <el-dialog title="查看系统类别" :visible.sync="viewDialogVisible" width="500px">
+        <el-descriptions :column="1" border>
+          <el-descriptions-item label="系统类别编号">{{ viewForm.systemCode }}</el-descriptions-item>
+          <el-descriptions-item label="系统类别名称">{{ viewForm.systemName }}</el-descriptions-item>
+          <el-descriptions-item label="备注">{{ viewForm.remark || '-' }}</el-descriptions-item>
+          <el-descriptions-item label="产品数">{{ viewForm.productCount }}</el-descriptions-item>
+        </el-descriptions>
+      </el-dialog>
+    </div>
+  </template>
+  
+  <script>
+  export default {
+    name: 'SystemCategoryManagement',
+    data() {
+      return {
+        searchQuery: '',
+        loading: false,
+        submitLoading: false,
+        tableData: [
+          {
+            systemCode: 'pjxs',
+            systemName: '拼接显示',
+            remark: '',
+            productCount: 500
+          }
+        ],
+        pagination: {
+          currentPage: 1,
+          pageSize: 10,
+          total: 1
+        },
+        dialogVisible: false,
+        viewDialogVisible: false,
+        dialogTitle: '',
+        form: {
+          systemCode: '',
+          systemName: '',
+          remark: ''
+        },
+        viewForm: {
+          systemCode: '',
+          systemName: '',
+          remark: '',
+          productCount: 0
+        },
+        rules: {
+          systemCode: [
+            { required: true, message: '请输入系统类别编号', trigger: 'blur' },
+            { min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'blur' }
+          ],
+          systemName: [
+            { required: true, message: '请输入系统类别名称', trigger: 'blur' },
+            { min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' }
+          ]
+        }
+      }
+    },
+    methods: {
+      async loadData() {
+        this.loading = true
+        try {
+          // 这里调用实际的API
+          // const res = await getSystemCategoryList({
+          //   page: this.pagination.currentPage,
+          //   pageSize: this.pagination.pageSize,
+          //   query: this.searchQuery
+          // })
+          // this.tableData = res.data.list
+          // this.pagination.total = res.data.total
+        } catch (error) {
+          this.$message.error('加载数据失败')
+        } finally {
+          this.loading = false
+        }
+      },
+      handleSearch() {
+        this.pagination.currentPage = 1
+        this.loadData()
+      },
+      handleAdd() {
+        this.dialogTitle = '新建系统类别'
+        this.form = {
+          systemCode: '',
+          systemName: '',
+          remark: ''
+        }
+        this.dialogVisible = true
+        this.$nextTick(() => {
+          this.$refs.form.clearValidate()
+        })
+      },
+      handleEdit(row) {
+        this.dialogTitle = '编辑系统类别'
+        this.form = { ...row }
+        this.dialogVisible = true
+        this.$nextTick(() => {
+          this.$refs.form.clearValidate()
+        })
+      },
+      handleView(row) {
+        this.viewForm = { ...row }
+        this.viewDialogVisible = true
+      },
+      handleDelete(row) {
+        this.$confirm('确认删除该系统类别?删除后不可恢复', '提示', {
+          type: 'warning',
+          confirmButtonText: '确定',
+          cancelButtonText: '取消'
+        }).then(async () => {
+          try {
+            // await deleteSystemCategory(row.systemCode)
+            this.$message.success('删除成功')
+            this.loadData()
+          } catch (error) {
+            this.$message.error('删除失败')
+          }
+        }).catch(() => {})
+      },
+      handleSizeChange(val) {
+        this.pagination.pageSize = val
+        this.loadData()
+      },
+      handleCurrentChange(val) {
+        this.pagination.currentPage = val
+        this.loadData()
+      },
+      cancelForm() {
+        this.dialogVisible = false
+        this.$refs.form.clearValidate()
+      },
+      async submitForm() {
+        this.$refs.form.validate(async (valid) => {
+          if (valid) {
+            this.submitLoading = true
+            try {
+              // if (this.dialogTitle === '新建系统类别') {
+              //   await createSystemCategory(this.form)
+              // } else {
+              //   await updateSystemCategory(this.form)
+              // }
+              this.$message.success('保存成功')
+              this.dialogVisible = false
+              this.loadData()
+            } catch (error) {
+              this.$message.error('保存失败')
+            } finally {
+              this.submitLoading = false
+            }
+          }
+        })
+      }
+    },
+    created() {
+      this.loadData()
+    }
+  }
+  </script>
+  
+  <style scoped>
+  .system-category-container {
+    padding: 20px;
+  }
+  .operation-area {
+    display: flex;
+    align-items: center;
+  }
+  </style>

+ 173 - 0
ui/src/views/ProductMent/worksCategory/index.vue

@@ -0,0 +1,173 @@
+<template>
+    <div class="project-category-container">
+      <!-- 顶部操作区 -->
+      <div class="operation-area">
+        <el-button type="primary" @click="handleAdd">新建工程类别</el-button>
+        <el-input
+          v-model="searchQuery"
+          placeholder="请输入工程类别编号或名称"
+          style="width: 200px; margin-left: 16px"
+          @keyup.enter.native="handleSearch"
+        >
+          <el-button slot="append" icon="el-icon-search" @click="handleSearch"></el-button>
+        </el-input>
+      </div>
+  
+      <!-- 表格区域 -->
+      <el-table :data="tableData"  style="width: 100%; margin-top: 20px">
+        <el-table-column prop="projectCode" label="工程类别编号" width="180"></el-table-column>
+        <el-table-column prop="projectName" label="工程类别名称" width="180"></el-table-column>
+        <el-table-column prop="remark" label="备注"></el-table-column>
+        <el-table-column prop="productCount" label="产品数" width="120"></el-table-column>
+        <el-table-column label="操作" width="250">
+          <template slot-scope="scope">
+            <el-button size="mini" @click="handleView(scope.row)">查看</el-button>
+            <el-button size="mini" type="primary" @click="handleEdit(scope.row)">编辑</el-button>
+            <el-button size="mini" type="danger" @click="handleDelete(scope.row)">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+  
+      <!-- 分页 -->
+      <el-pagination
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+        :current-page="pagination.currentPage"
+        :page-sizes="[10, 20, 50, 100]"
+        :page-size="pagination.pageSize"
+        layout="total, sizes, prev, pager, next, jumper"
+        :total="pagination.total"
+        style="margin-top: 20px; text-align: right"
+      >
+      </el-pagination>
+  
+      <!-- 新增/编辑对话框 -->
+      <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="500px">
+        <el-form :model="form" :rules="rules" ref="form" label-width="120px">
+          <el-form-item label="工程类别编号" prop="projectCode">
+            <el-input v-model="form.projectCode"></el-input>
+          </el-form-item>
+          <el-form-item label="工程类别名称" prop="projectName">
+            <el-input v-model="form.projectName"></el-input>
+          </el-form-item>
+          <el-form-item label="备注" prop="remark">
+            <el-input type="textarea" v-model="form.remark"></el-input>
+          </el-form-item>
+        </el-form>
+        <div slot="footer">
+          <el-button @click="dialogVisible = false">取 消</el-button>
+          <el-button type="primary" @click="submitForm">确 定</el-button>
+        </div>
+      </el-dialog>
+    </div>
+  </template>
+  
+  <script>
+  export default {
+    name: 'ProjectCategoryManagement',
+    data() {
+      return {
+        searchQuery: '',
+        tableData: [
+          {
+            projectCode: 'ysp',
+            projectName: '音视频',
+            remark: '',
+            productCount: 5
+          }
+        ],
+        pagination: {
+          currentPage: 1,
+          pageSize: 10,
+          total: 1
+        },
+        dialogVisible: false,
+        dialogTitle: '',
+        form: {
+          projectCode: '',
+          projectName: '',
+          remark: ''
+        },
+        rules: {
+          projectCode: [
+            { required: true, message: '请输入工程类别编号', trigger: 'blur' }
+          ],
+          projectName: [
+            { required: true, message: '请输入工程类别名称', trigger: 'blur' }
+          ]
+        }
+      }
+    },
+    methods: {
+      handleSearch() {
+        // 实现搜索逻辑
+        console.log('搜索关键词:', this.searchQuery)
+        this.loadData()
+      },
+      handleAdd() {
+        this.dialogTitle = '新增工程类别'
+        this.form = {
+          projectCode: '',
+          projectName: '',
+          remark: ''
+        }
+        this.dialogVisible = true
+      },
+      handleEdit(row) {
+        this.dialogTitle = '编辑工程类别'
+        this.form = { ...row }
+        this.dialogVisible = true
+      },
+      handleDelete(row) {
+        this.$confirm('确认删除该工程类别?', '提示', {
+          type: 'warning'
+        }).then(() => {
+          // 实现删除逻辑
+          console.log('删除:', row)
+          this.$message.success('删除成功')
+          this.loadData()
+        }).catch(() => {})
+      },
+      handleView(row) {
+        // 实现查看逻辑
+        console.log('查看:', row)
+      },
+      handleSizeChange(val) {
+        this.pagination.pageSize = val
+        this.loadData()
+      },
+      handleCurrentChange(val) {
+        this.pagination.currentPage = val
+        this.loadData()
+      },
+      submitForm() {
+        this.$refs.form.validate((valid) => {
+          if (valid) {
+            // 实现表单提交逻辑
+            console.log('表单数据:', this.form)
+            this.dialogVisible = false
+            this.$message.success('保存成功')
+            this.loadData()
+          }
+        })
+      },
+      loadData() {
+        // 实现数据加载逻辑
+        console.log('加载数据,当前页:', this.pagination.currentPage, '每页数量:', this.pagination.pageSize)
+      }
+    },
+    created() {
+      this.loadData()
+    }
+  }
+  </script>
+  
+  <style scoped>
+  .project-category-container {
+    padding: 20px;
+  }
+  .operation-area {
+    display: flex;
+    align-items: center;
+  }
+  </style>

+ 3 - 2
ui/src/views/system/document/components/dataList.vue

@@ -180,11 +180,12 @@ export default {
 
     //编辑
     btnEdit(e) {
-      let _this = this;
+      this.$router.push("system/document/create?templateId=" + e + "&type=module");
+      /* let _this = this;
       let a = document.createElement("a");
       a.href = "#/document/create?articleId=" + e+"&type=document"; // 使用 hash
       a.target = "_blank";
-      a.click();
+      a.click(); */
 
        //this.$router.push({path:"/document/create",query:{articleId:e}})
     },

+ 1 - 1
ui/src/views/system/document/components/dataSearch.vue

@@ -125,7 +125,7 @@ export default {
     },
     /* 创建文档 */
     addDocument() {
-      this.$router.push('system/document/create');
+      this.$router.push('system/document/create?type=document');
       /* let _this = this;
       let a = document.createElement("a");
       a.href = "#/document/create?type=document"; // 使用 hash

+ 1 - 1
ui/src/views/system/document/create.vue

@@ -1405,7 +1405,7 @@ export default {
 
         // 解析文档数据
         const documentData = res.data.data ? JSON.parse(res.data.data) : [];
-
+        console.log(documentData);
         const updatedComs = await Promise.all(
           documentData.map(async (docEl) => {
             if (!docEl || !docEl.id) {

+ 3 - 2
ui/src/views/system/document/temList/components/dataList.vue

@@ -174,11 +174,12 @@ export default {
 
     //编辑
     btnEdit(e) {
-      let _this = this;
+      this.$router.push('system/document/create?articleId=' + e);
+      /* let _this = this;
       let a = document.createElement("a");
       a.href = "#/document/create?articleId=" + e;
       a.target = "_blank";
-      a.click();
+      a.click(); */
 
        //_this.$router.push({path:"/document/create",query:{articleId:e}})
     },

+ 3 - 2
ui/src/views/system/document/temList/components/dataSearch.vue

@@ -99,11 +99,12 @@ export default{
     },
     /* 创建模版 */
     addDocument(){
-      let _this = this;
+      this.$router.push('system/document/create');
+  /*     let _this = this;
       let a = document.createElement("a");
       a.href = "#/document/create"; // 使用 hash
       a.target = "_blank";
-      a.click();
+      a.click(); */
       //this.$router.push('/document/create');
     }
   }

+ 2 - 2
ui/src/views/system/document/temList/temList.vue

@@ -34,9 +34,9 @@ export default {
   },
   methods: {
     checkAuth(path) {
-      if (this.roleInfo.is_admin == 1) {
+     /*  if (this.roleInfo.is_admin == 1) {
         return true;
-      }
+      } */
       /* let auth=this.authList.filter(o=>o.type==999 && o.path==path);
           if(auth.length>0){
             return true;

+ 11 - 0
ui/src/views/system/template/category/components/dataInfo.scss

@@ -0,0 +1,11 @@
+ .sub-imgs{
+    padding:0px;
+    margin:0px;
+      li{
+        float:left;
+        margin-right:10px;
+        width:100px;
+        height:100px;
+        list-style: none;
+      }
+  }

+ 181 - 0
ui/src/views/system/template/category/components/dataInfo.vue

@@ -0,0 +1,181 @@
+<template>
+  <div class="data-info">
+    <el-card>
+      <el-form :model="dataForm" ref="dataFormRef" label-width="120px">
+        <el-form-item label="父级分类:">
+          <el-select
+            v-model="dataForm.parent_id"
+            placeholder="请选择你级分类"
+            size="large"
+            clearable
+            style="width: 100%"
+          >
+            <el-option
+              v-for="item in parentList"
+              :key="item.id"
+              :label="item.name"
+              :value="item.id"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="分类名称:">
+          <el-input v-model="dataForm.name"></el-input>
+        </el-form-item>
+        <!-- <el-form-item label="分类介绍:">
+           <el-input type="textarea" v-model="dataForm.intro"></el-input>
+       </el-form-item> -->
+        <el-form-item label="分类状态:">
+          <el-select
+            v-model="dataForm.status"
+            placeholder="请选择分类状态"
+            size="large"
+            style="width: 100%"
+          >
+            <el-option
+              v-for="item in statusOptions"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+    </el-card>
+    <div style="text-align: right; margin-top: 20px">
+      <el-button type="warning" @click="btnSave">确认保存</el-button>
+    </div>
+  </div>
+</template>
+
+<script>
+import {
+  createTemplateCategory,
+  updateTemplateCategory,
+  getTemplateCategoryInfo,
+  searchTemplateCategory,
+} from "@/api/template";
+export default {
+  emits: ["onClose", "onSearch"],
+  props: {
+    id: {
+      type: Number,
+      default: 0,
+    },
+  },
+  watch: {
+    id: {
+      handler(v) {
+        let _this = this;
+        if (v == null || v <= 0) return;
+        _this.getInfo(v);
+      },
+      immediate: true,
+      deep: true,
+    },
+  },
+  data() {
+    return {
+      activeName: "base",
+      currentCategory: [],
+      dataForm: {
+        id: 0,
+        name: "",
+        parent_id: 0,
+        intro: "",
+        status: 5,
+      },
+      parentList: [],
+      statusOptions: [
+        {
+          value: "",
+          label: "请选择状态",
+        },
+        {
+          value: 5,
+          label: "启用",
+        },
+        {
+          value: 6,
+          label: "停用",
+        },
+      ],
+    };
+  },
+
+  mounted() {
+    this.initParentCategory();
+  },
+  methods: {
+    resetForm() {
+      // 重置所有表单字段
+      this.dataForm = {}; // 或者设置为初始值
+      // 如果使用 el-form,可以调用其 resetFields 方法
+      this.$refs.dataFormRef.resetFields();
+    },
+    initParentCategory() {
+      let _this = this;
+      searchTemplateCategory({
+        page: 1,
+        pageSize: 999,
+        parent_id: 0,
+        status: 5,
+      }).then((res) => {
+        if (res.status != 200) return;
+        _this.parentList.push({ id: 0, name: "父级分类" });
+     /*    for (var i = 0; i < res.data.dataList.length; i++) {
+          _this.parentList.push({
+            id: res.data.dataList[i].id,
+            name: res.data.dataList[i].name,
+          });
+        } */
+      });
+    },
+    //保存更新
+    btnSave(e) {
+      let _this = this;
+      if (_this.dataForm.id > 0) {
+        updateTemplateCategory(_this.dataForm).then((res) => {
+          if (res.status != 200) return;
+          _this.$alert("模板类别信息更新成功");
+          _this.$emit("onSearch");
+          _this.$emit("onClose");
+        });
+      } else {
+        createTemplateCategory(_this.dataForm).then((res) => {
+          if (res.status != 200) return;
+          _this.$alert("模板类别信息创建成功");
+          _this.$emit("onSearch");
+          _this.$emit("onClose");
+        });
+      }
+    },
+
+    //产品详情
+    getInfo(id) {
+      let _this = this;
+      let par = {
+        id: id,
+      };
+      getTemplateCategoryInfo(par).then((res) => {
+        if (!res) return;
+        if (res.status != 200) return;
+        res.data.parent_id = Number(res.data.parent_id);
+        _this.dataForm = res.data;
+      });
+    },
+
+    onChangeStatus(e) {
+      this.dataForm.status = e;
+    },
+    //修改分类信息
+    onChangeCategory(e) {
+      let _this = this;
+      _this.dataForm.categoryId = e;
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+@import "./dataInfo.scss";
+</style>

+ 55 - 0
ui/src/views/system/template/category/components/dataList.scss

@@ -0,0 +1,55 @@
+
+.data-list{
+
+
+  .btns{
+    display:flex;
+    flex-direction: row;
+  }
+
+
+
+
+  .page-info{
+    display:flex;
+    flex-direction: row;
+    margin-top:10px;
+    .opt{
+      width:50%;
+      display:flex;
+      flex-direction:row;
+      justify-content: flex-start;
+      align-items: center;
+
+      .pick{
+        width:100px;
+
+      }
+      .section{
+        margin-left:10px;
+      }
+    }
+
+    .page-data{
+
+      display:flex;
+      flex-direction: row;
+      justify-content: space-between;
+      align-items: center;
+      width:100%;
+      .page-item{
+          width:100%;
+          // border:1px solid red;
+      }
+      .page-opt{
+        width:100%;
+        // border:1px solid red;
+        display: flex;
+        justify-content: flex-end;
+      }
+    }
+
+
+  }
+
+}

+ 443 - 0
ui/src/views/system/template/category/components/dataList.vue

@@ -0,0 +1,443 @@
+<template>
+  <div
+    class="data-list"
+    v-loading="tableLoading"
+    element-loading-text="加载中..."
+    element-loading-spinner="el-icon-loading"
+  >
+    <el-table
+      ref="dataTable"
+      :data="dataList"
+      stripe
+      lazy
+      :load="loadData"
+      row-key="id"
+      :tree-props="{ children: 'child', hasChildren: 'hasChildren' }"
+      show-overflow-tooltip
+      style="width: 100%"
+      header-row-class-name="headerBg"
+      empty-text="没有分类信息"
+    >
+      <el-table-column prop="id" label="ID" width="180" />
+      <el-table-column
+        prop="name"
+        label="分类名称"
+        align="left"
+        min-width="180"
+      >
+      </el-table-column>
+      <el-table-column prop="createTime" label="创建时间" align="center" />
+      <el-table-column prop="status" label="分类状态" align="center">
+        <template #default="scope">
+          <div v-if="scope.row.status == 5">启用</div>
+          <div v-if="scope.row.status == 6">停用</div>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" fixed="right" align="center" width="300">
+        <template #default="scope">
+          <div class="btns">
+            <el-button type="primary" size="small" @click="Subclass(scope.row)"
+              ><svg-icon icon-class="edit" />创建子类</el-button
+            >
+            <el-button type="primary" size="small" @click="btnEdit(scope.row)"
+              ><svg-icon icon-class="edit" />编辑</el-button
+            >
+            <el-button
+              type="danger"
+              size="small"
+              @click="btnDelete(scope.row.id)"
+              ><svg-icon icon-class="delete" />删除</el-button
+            >
+          </div>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <div class="page-info">
+      <el-pagination
+        :currentPage="queryForm.page"
+        :page-size="queryForm.pageSize"
+        :total="recordCount"
+        :page-count="pageTotal"
+        background
+        layout="prev, pager, next"
+        @current-change="ChangePage"
+      >
+      </el-pagination>
+    </div>
+
+    <el-dialog
+      :visible.sync="SubclassVisible"
+      append-to-body
+      v-el-drag-dialog
+      width="50%"
+      custom-class="prod-verify"
+      title="创建子类"
+      @closed="handleSubClosed"
+    >
+      <!--       <dataInfo
+        :id="currentDataId"
+        @onClose="onClose"
+        ref="currentInfoRef"
+        @onSearch="search"
+      ></dataInfo> -->
+      <el-card>
+        <el-form :model="dataForm" ref="dataFormRef" label-width="120px">
+          <!-- <el-form-item label="父级分类:">
+            <el-select
+              v-model="dataForm.parent_id"
+              placeholder="请选择你级分类"
+              size="large"
+              clearable
+              style="width: 100%"
+            >
+              <el-option
+                v-for="item in parentList"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id"
+              />
+            </el-select>
+          </el-form-item> -->
+          <el-form-item label="分类名称:">
+            <el-input v-model="dataForm.name"></el-input>
+          </el-form-item>
+          <!-- <el-form-item label="分类介绍:">
+           <el-input type="textarea" v-model="dataForm.intro"></el-input>
+       </el-form-item> -->
+          <el-form-item label="分类状态:">
+            <el-select
+              v-model="dataForm.status"
+              placeholder="请选择分类状态"
+              size="large"
+              style="width: 100%"
+            >
+              <el-option
+                v-for="item in statusOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+        </el-form>
+      </el-card>
+      <div style="text-align: right; margin-top: 20px">
+        <el-button type="warning" @click="btnSave">确认保存</el-button>
+      </div>
+    </el-dialog>
+    <el-dialog
+      :visible.sync="dialogVisible"
+      append-to-body
+      v-el-drag-dialog
+      width="50%"
+      custom-class="prod-verify"
+      title="编辑分类"
+      @closed="handleDialogClosed"
+    >
+      <dataInfo
+        :id="currentDataId"
+        @onClose="onClose"
+        ref="currentInfoRef"
+        @onSearch="search"
+      ></dataInfo>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  searchTemplateCategory,
+  deleteTemplateCategory,
+  createTemplateCategory,
+  updateTemplateCategory,
+  getTemplateCategoryInfo,
+} from "@/api/template";
+import dataInfo from "./dataInfo.vue";
+import elDragDialog from "@/directive/el-drag-dialog";
+import Vue from "vue";
+export default {
+  components: {
+    dataInfo,
+  },
+  directives: { elDragDialog },
+  props: {
+    queryForm: {
+      type: Object,
+      default: () => {
+        return {
+          page: 1,
+          pageSize: 10,
+          name: "",
+          parent_id: 0,
+          sign: "",
+        };
+      },
+    },
+  },
+  watch: {
+    queryForm: {
+      handler: function (val) {
+        this.search();
+      },
+      immediate: true, //立即执行
+      deep: true,
+    },
+  },
+  data() {
+    return {
+      dialogVisible: false, //控制产品审核
+      currentDataId: 0,
+      recordCount: 0,
+      pageTotal: 1,
+      dataList: [],
+      currentData: {},
+      activeName: "base",
+      currentCategory: [],
+      tableLoading: false,
+      dataForm: {
+        id: 0,
+        name: "",
+        parent_id: 0,
+        intro: "",
+        status: 5,
+      },
+      parentList: [],
+      statusOptions: [
+        {
+          value: "",
+          label: "请选择状态",
+        },
+        {
+          value: 5,
+          label: "启用",
+        },
+        {
+          value: 6,
+          label: "停用",
+        },
+      ],
+      SubclassVisible: false,
+      expandedRows: new Set(),
+    };
+  },
+  mounted() {
+    this.search();
+    this.initParentCategory();
+  },
+  methods: {
+    /* 弹窗 */
+    initParentCategory() {
+      let _this = this;
+      searchTemplateCategory({
+        page: 1,
+        pageSize: 999,
+        parent_id: 0,
+        status: 5,
+      }).then((res) => {
+        if (res.status != 200) return;
+        _this.parentList.push({ id: 0, name: "父级分类" });
+        /* for (var i = 0; i < res.data.dataList.length; i++) {
+          _this.parentList.push({
+            id: res.data.dataList[i].id,
+            name: res.data.dataList[i].name,
+          });
+        } */
+      });
+    },
+    //保存更新
+    btnSave(e) {
+      let _this = this;
+      if (_this.dataForm.id > 0) {
+        updateTemplateCategory(_this.dataForm).then((res) => {
+          if (res.status != 200) return;
+          _this.$message.success("模板类别信息更新成功");
+          _this.SubclassVisible = false;
+          _this.search();
+          _this.refreshAndExpandParent();
+        });
+      } else {
+        createTemplateCategory(_this.dataForm).then((res) => {
+          if (res.status != 200) return;
+          _this.$message.success("模板类别信息创建成功");
+          _this.SubclassVisible = false;
+          _this.search();
+          _this.refreshAndExpandParent();
+        });
+      }
+    },
+    refreshAndExpandParent() {
+      const parentId = this.dataForm.parent_id;
+      this.expandedRows.add(parentId);
+      this.search(); // 这里已经重新加载了数据
+      this.$nextTick(() => {
+        // 使用 $refs 来访问 el-table 组件
+        const table = this.$refs.dataTable;
+        if (table) {
+          // 找到父行并展开
+          const parentRow = this.dataList.find((row) => row.id === parentId);
+          if (parentRow) {
+            table.toggleRowExpansion(parentRow, true);
+          }
+        }
+      });
+    },
+
+    //产品详情
+    getInfo(id) {
+      let _this = this;
+      let par = {
+        id: id,
+      };
+      getTemplateCategoryInfo(par).then((res) => {
+        if (!res) return;
+        if (res.status != 200) return;
+        res.data.parent_id = Number(res.data.parent_id);
+        _this.dataForm = res.data;
+      });
+    },
+
+    onChangeStatus(e) {
+      this.dataForm.status = e;
+    },
+    //修改分类信息
+    onChangeCategory(e) {
+      let _this = this;
+      _this.dataForm.categoryId = e;
+    },
+
+    /* 创建子类 */
+    Subclass(item) {
+      this.dataForm.parent_id = item.id;
+      //this.dataForm.child_count=item.child_count
+      this.SubclassVisible = true;
+    },
+    handleSubClosed() {
+      this.dataForm = {
+        name: "",
+        intro: "",
+        status: 5,
+      };
+    },
+    handleDialogClosed() {
+      // 清空 dataInfo 组件内的表单
+      if (this.$refs.dataInfoRef) {
+        this.$refs.dataInfoRef.resetForm(); // 假设 dataInfo 组件有一个 resetForm 方法
+      }
+    },
+    btnView(e) {
+      let _this = this;
+      _this.queryForm.parent_id = e;
+      _this.search();
+
+      // _this.$router.push({path:"/template/category/search",params:{parent_id:e}});
+      // location.href="?parent_id="+e;
+    },
+    loadData(row, node, resolve) {
+      setTimeout(() => {
+        searchTemplateCategory({ parent_id: row.id }).then((res) => {
+          if (res.data.length == 0) {
+            this.$message.warning("暂无数据!");
+          }
+          res.data.map((el) => {
+            if (el.child_count > 0) {
+              el.hasChildren = true;
+            } else {
+              el.hasChildren = false;
+            }
+          });
+          resolve(res.data);
+          this.expandedRows.add(row.id);
+        });
+
+        /*    resolve(row.children); */
+      }, 0);
+    },
+
+    btnDelete(e) {
+      let _this = this;
+      let par = {
+        id: e,
+      };
+      _this.queryForm.name = "";
+      _this
+        .$confirm("您是否确认删除该记录?", "提示", {
+          confirmButtonText: "确认",
+          cancelButtonText: "取消",
+          type: "warning",
+        })
+        .then((res) => {
+          deleteTemplateCategory(par).then((res) => {
+            _this.search();
+          });
+        })
+        .catch(() => {});
+    },
+
+    searchData() {
+      let _this = this;
+      _this.dialogVisible = false;
+      _this.search();
+    },
+
+    //编辑
+    btnEdit(e) {
+      let _this = this;
+      _this.currentDataId = e.id;
+      _this.dialogVisible = true;
+    },
+
+    onClose() {
+      let _this = this;
+      _this.currentDataId = 0;
+      _this.dialogVisible = false;
+      _this.search();
+    },
+
+    //搜索
+    search() {
+      let _this = this;
+      _this.dataList = [];
+      _this.tableLoading = true;
+      searchTemplateCategory(_this.queryForm)
+        .then((res) => {
+          if (!res) {
+            _this.tableLoading = false;
+            return;
+          }
+          const newDataList = res.data.dataList.map((el) => {
+            if (el.child_count > 0) {
+              el.hasChildren = true;
+            } else {
+              el.hasChildren = false;
+            }
+          });
+          _this.dataList = res.data.dataList;
+          _this.recordCount = res.data.totalRecord;
+          _this.pageTotal = res.data.totalPage;
+          _this.$forceUpdate();
+
+          // 使用 nextTick 确保 DOM 已更新
+          _this.$nextTick(() => {
+            // 这里可以添加任何需要在 DOM 更新后执行的操作
+            console.log("View updated");
+            _this.tableLoading = false;
+          });
+        })
+        .catch(() => {
+          _this.tableLoading = false;
+        });
+    },
+    //修改分页
+    ChangePage(e) {
+      let _this = this;
+      _this.queryForm.page = e;
+      _this.search();
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+@import "./dataList.scss";
+</style>

+ 3 - 0
ui/src/views/system/template/category/components/dataSearch.scss

@@ -0,0 +1,3 @@
+.data-search{ 
+  padding:20px 10px 0px 10px;
+}

+ 98 - 0
ui/src/views/system/template/category/components/dataSearch.vue

@@ -0,0 +1,98 @@
+<template>
+  <div class="data-search">
+    <el-form :inline="true" :model="queryForm" class="demo-form-inline">
+
+        <el-form-item label="分类名称:">
+          <el-input v-model="queryForm.name" placeholder="请选择分类名称"></el-input>
+        </el-form-item>
+        <el-form-item label="分类状态:">
+          <el-select v-model="queryForm.status" class="m-2" placeholder="请选择分类状态" size="large">
+              <el-option
+                v-for="item in statusOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+        </el-form-item>
+
+        <el-form-item>
+          <el-button type="primary" @click="onSubmit">  <svg-icon icon-class="search"/> 搜索</el-button>
+          <el-button type="success" @click="onCreate" >  <svg-icon icon-class="edit"/> 创建分类</el-button>
+        </el-form-item>
+      </el-form>
+
+
+
+    <el-dialog  :visible.sync="dialogVisible" append-to-body v-el-drag-dialog  width="50%" custom-class="prod-verify" title="创建分类">
+         <dataInfo @onClose="onClose"></dataInfo>
+     </el-dialog>
+
+  </div>
+</template>
+
+<script>
+import dataInfo from './dataInfo.vue';
+import elDragDialog from '@/directive/el-drag-dialog'
+export default{
+  components:{
+    dataInfo,
+  },
+  directives: { elDragDialog },
+  props:{
+    queryForm:{
+        type:Object,
+        default:()=>{
+          return {
+             page:1,
+             pageSize:10,
+             name:'',
+             parent_id:0,
+             status:'',
+          }
+        }
+    },
+  },
+  data(){
+    return{
+        statusOptions:[
+          {
+            value:'',
+            label:"请选择状态"
+          },
+          {
+            value:5,
+            label:'启用'
+          },
+          {
+            value:6,
+            label:"停用"
+          },
+        ],
+        dialogVisible:false,
+    }
+  },
+  created() {
+
+  },
+  methods:{
+
+    onCreate(e){
+      this.dialogVisible=true;
+    },
+    onClose(e){
+      this.dialogVisible=false;
+      this.onSubmit();
+    },
+    //搜索
+    onSubmit(){
+      this.queryForm.isUpdate=!this.queryForm.isUpdate;
+      this.$emit("bindSetQuery",this.queryForm);
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+@import "./dataSearch.scss"
+</style>

+ 3 - 0
ui/src/views/system/template/category/components/index.js

@@ -0,0 +1,3 @@
+export { default as dataSearch } from './dataSearch'
+export { default as dataList } from './dataList'
+export { default as dataInfo } from './dataInfo'

+ 4 - 0
ui/src/views/system/template/category/search.scss

@@ -0,0 +1,4 @@
+.project-search{
+  padding:30px;
+  font-size:12px;
+}

+ 39 - 0
ui/src/views/system/template/category/search.vue

@@ -0,0 +1,39 @@
+<template>
+  <div class="project-search">
+    <dataSearch @bindSetQuery="setQuery"></dataSearch>
+    <dataList :queryForm="queryForm"></dataList>
+  </div>
+
+</template>
+
+<script>
+import {dataSearch,dataList} from "./components"
+export default{
+  components:{
+    dataSearch,
+    dataList,
+  },
+  data(){
+    return{
+      queryForm:{
+        page:1,
+        pageSize:10,
+        parent_id:0,
+        name:'',
+        status:'',
+      },
+    }
+  },
+  methods:{
+
+    setQuery(e){
+      this.queryForm=e;
+    }
+
+  }
+}
+</script>
+
+<style lang="scss">
+@import './search.scss'
+</style>

+ 11 - 0
ui/src/views/system/template/components/dataInfo.scss

@@ -0,0 +1,11 @@
+ .sub-imgs{
+    padding:0px;
+    margin:0px;
+      li{
+        float:left;
+        margin-right:10px;
+        width:100px;
+        height:100px;
+        list-style: none;
+      }
+  }

+ 177 - 0
ui/src/views/system/template/components/dataInfo.vue

@@ -0,0 +1,177 @@
+<template>
+  <div class="data-info">
+    <el-card>
+      <el-form :model="dataForm" label-width="120px">
+        <el-form-item label="组件类型:">
+          <el-select v-model="dataForm.type"  placeholder="请选择类型" size="large" @change="onChangeStatus" style="width:100%;">
+              <el-option
+                v-for="item in typeList"
+                :key="item.value"
+                :label="item.text"
+                :value="item.value"
+              />
+            </el-select>
+        </el-form-item>
+        <el-form-item label="组件名称:">
+          <el-input v-model="dataForm.title"></el-input>
+        </el-form-item>
+        <el-form-item label="产品状态:">
+          <el-select v-model="dataForm.statusName"  placeholder="请选择状态" size="large" @change="onChangeStatus" style="width:100%;">
+              <el-option
+                v-for="item in statusOptions"
+                :key="item.status"
+                :label="item.name"
+                :value="item.status"
+              />
+            </el-select>
+        </el-form-item>
+        <el-form-item label="说明介绍:">
+            <el-input type="textarea" v-model="dataForm.title"></el-input>
+        </el-form-item>
+
+        <el-form-item label="组件内容:" v-if="dataForm.type==1">
+            <Tinymce></Tinymce>
+        </el-form-item>
+
+      </el-form>
+
+    </el-card>
+
+
+      <div style="text-align:right; margin-top:20px;">
+          <el-button type="warning" @click="btnSave">确认保存</el-button>
+      </div>
+  </div>
+</template>
+
+<script>
+  import Tinymce from "@/components/Tinymce";
+  export default{
+    components:{
+      Tinymce
+    },
+    emits:['onClose'],
+    props:{
+      id:{
+        type:Number,
+        default:0
+      },
+    },
+    watch:{
+      id:{
+        handler(v){
+            let _this=this;
+            if(v==null || v<0)return;
+            _this.getInfo(v);
+        },
+        immediate: true,
+        deep: true
+      }
+    },
+    data(){
+      return{
+        activeName:'base',
+        currentCategory:[],
+        allCategories:[],
+        typeList:[
+          {
+            value:1,
+            text:'文本'
+          },
+          {
+            value:2,
+            text:"二维表"
+          }
+        ],
+        dataForm:{
+          type:1,
+          prod:{
+            items:[],
+          }
+        },
+        statusOptions:[
+          {
+            status:5,
+            name:'启用'
+          },
+          {
+            status:6,
+            name:'停用'
+          },
+
+        ],
+      }
+    },
+
+    mounted() {
+      let _this=this;
+      _this.initAllCategory();
+    },
+    methods:{
+      //保存更新
+      btnSave(e){
+          let _this=this;
+
+          if(_this.dataForm.title==''){
+            _this.$alert("产品标题不能为空");
+              return;
+          }
+
+         let dataForm={
+           id:_this.dataForm.id,
+           title:_this.dataForm.title,
+           status:_this.dataForm.status,
+           categoryId:_this.dataForm.categoryId,
+           sku:_this.dataForm.sku
+         };
+
+          // productUpdate(_this.dataForm).then(res=>{
+          //   if(!res)return;
+          //    _this.$alert("产品审核操作成功");
+          //    _this.$emit("bindUpdate");
+          // })
+      },
+
+      //产品详情
+      getInfo(id){
+          let _this=this;
+          let par={
+            id:id,
+          };
+          // productInfo(par).then(res=>{
+          //     if(!res)return;
+          //     if(res.status!=200)return;
+          //     _this.dataForm=res.data;
+          // })
+      },
+
+      onChangeStatus(e){
+          this.dataForm.status=e;
+      },
+      //修改分类信息
+      onChangeCategory(e){
+         let _this=this;
+         _this.dataForm.categoryId=e;
+      },
+      //初始化所有分类
+      initAllCategory(){
+          let _this=this;
+          let par={
+            page:1,
+            pageSize:9999,
+            status:1
+          };
+          // searchGoodsCategory().then(res=>{
+          //   if(!res)return;
+          //   if(res.status!=200)return;
+          //   _this.allCategories=res.data.data;
+          // })
+      }
+
+    }
+  }
+</script>
+
+<style lang="scss">
+ @import './dataInfo.scss'
+</style>

+ 55 - 0
ui/src/views/system/template/components/dataList.scss

@@ -0,0 +1,55 @@
+
+.data-list{
+
+
+  .btns{
+    display:flex;
+    flex-direction: row;
+  }
+ 
+
+
+
+  .page-info{
+    display:flex;
+    flex-direction: row;
+    margin-top:10px;
+    .opt{
+      width:50%;
+      display:flex;
+      flex-direction:row;
+      justify-content: flex-start;
+      align-items: center;
+
+      .pick{
+        width:100px;
+
+      }
+      .section{
+        margin-left:10px;
+      }
+    }
+
+    .page-data{
+
+      display:flex;
+      flex-direction: row;
+      justify-content: space-between;
+      align-items: center;
+      width:100%;
+      .page-item{
+          width:100%;
+          // border:1px solid red;
+      }
+      .page-opt{
+        width:100%;
+        // border:1px solid red;
+        display: flex;
+        justify-content: flex-end;
+      }
+    }
+
+
+  }
+
+}

+ 335 - 0
ui/src/views/system/template/components/dataList.vue

@@ -0,0 +1,335 @@
+<template>
+  <div class="data-list">
+    <el-table
+      :data="dataList"
+      header-row-class-name="headerBg"
+      empty-text="没有项目信息"
+      :max-height="tableMaxHeight"
+    >
+      <el-table-column prop="id" label="ID" align="center" width="80" />
+      <!--  <el-table-column prop="code" label="引用名" align="center" width="180"/> -->
+      <el-table-column prop="name" label="模块名称" align="left" />
+      <el-table-column prop="type_name" label="所属分类" align="left" />
+      <el-table-column prop="create_time" label="创建时间" align="center" />
+      <el-table-column prop="status" label="模板状态" align="center">
+        <template #default="scope">
+          <div v-if="scope.row.status == 5">启用</div>
+          <div v-if="scope.row.status == 6">停用</div>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" fixed="right" align="center" width="300">
+        <template #default="scope">
+          <div class="btns">
+            <el-button
+              type="primary"
+              size="small"
+              @click="btnEdit(scope.row.id)"
+              ><svg-icon icon-class="edit" />编辑模块</el-button
+            >
+            <el-button
+              type="primary"
+              size="small"
+              @click="EditorInfo(scope.row)"
+              ><svg-icon icon-class="edit" />修改信息</el-button
+            >
+            <el-button
+              type="danger"
+              size="small"
+              @click="btnDelete(scope.row.id)"
+              ><svg-icon icon-class="delete" />删除</el-button
+            ><!-- v-if="scope.row.auth.delete" -->
+          </div>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <div class="page-info">
+      <el-pagination
+        :currentPage="queryForm.page"
+        :page-size="queryForm.pageSize"
+        :total="recordCount"
+        :page-count="pageTotal"
+        background
+        layout="prev, pager, next"
+        @current-change="ChangePage"
+      >
+      </el-pagination>
+    </div>
+
+    <el-dialog
+      :visible.sync="dialogVisible"
+      append-to-body
+      v-el-drag-dialog
+      :close-on-click-modal="false"
+      width="30%"
+      custom-class="prod-verify"
+      title="修改模块信息"
+    >
+      <el-form
+        :model="moduleForm"
+        :rules="moduleRules"
+        ref="moduleRef"
+        label-position="left"
+        label-width="100px"
+      >
+        <el-form-item label="模块名称:" prop="name">
+          <el-input
+            style="width: 220px"
+            v-model="moduleForm.name"
+            placeholder="请选择模块名称"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="所属分类:" prop="category_id">
+          <el-cascader
+            v-model="moduleForm.category_id"
+            clearable
+            :options="categoryList"
+            :props="props"
+            :show-all-levels="false"
+            @change="onChangeCategory"
+            placeholder="请选择模块分类"
+          />
+          <!-- <el-select
+            v-model="moduleForm.category_id"
+            clearable
+            class="m-2"
+            placeholder="请选择分类"
+            size="large"
+          >
+            <el-option
+              v-for="item in categoryList"
+              :key="item.id"
+              :label="item.name"
+              :value="item.id"
+            />
+          </el-select> -->
+        </el-form-item>
+        <el-form-item label="模块状态:" prop="status">
+          <el-select
+            v-model="moduleForm.status"
+            class="m-2"
+            placeholder="请选择模板块态"
+            size="large"
+          >
+            <el-option
+              v-for="item in statusOptions"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="closeModule">取 消</el-button>
+        <el-button type="primary" @click="submitModule">确 定</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from "vuex";
+
+import { deleteTemplate, pageTemplate,getAllList,updateTemplate,treeCategory } from "@/api/template";
+import dataInfo from "./dataInfo.vue";
+import elDragDialog from "@/directive/el-drag-dialog";
+/* import Editor from "@/views/document/com/editor.vue"; */
+export default {
+  components: {
+    dataInfo,
+  },
+  directives: { elDragDialog },
+  props: {
+    queryForm: {
+      type: Object,
+      default: () => {
+        return {
+          page: 1,
+          pageSize: 10,
+          name: "",
+          sign: "",
+        };
+      },
+    },
+  },
+  watch: {
+    queryForm: {
+      handler: function (val) {
+        this.search();
+      },
+      // immediate: true,//立即执行
+      deep: true,
+    },
+  },
+  computed: {
+    ...mapGetters(["roleInfo", "authList"]),
+  },
+  data() {
+    return {
+      dialogVisible: false, //控制产品审核
+      currentDataId: 0,
+      recordCount: 0,
+      pageTotal: 1,
+      dataList: [],
+      currentData: {},
+      dialogVisible: false,
+      moduleForm: {
+        name: "",
+        status: 5,
+        category_id: "",
+      },
+      moduleRules: {
+        name: [{ required: true, message: "请输模块名称", trigger: "blur" }],
+        status: [{ required: true, message: "请选择状态", trigger: "change" }],
+        category_id: [
+          { required: true, message: "请选择分类", trigger: "change" },
+        ],
+      },
+      props: {
+        value: "id",
+        label: "name",
+        children: "children",
+        checkStrictly: true,
+      },
+      statusOptions: [
+        {
+          value: "",
+          label: "请选择状态",
+        },
+        {
+          value: 5,
+          label: "启用",
+        },
+        {
+          value: 6,
+          label: "停用",
+        },
+      ],
+      categoryList:[],
+      tableMaxHeight: 500, // Add this line
+    };
+  },
+  mounted() {
+    this.search();
+    this.initCategoryList();
+  },
+  methods: {
+    /* 选择模块分类 */
+    onChangeCategory(){},
+     /* 取消修改 */
+     closeModule() {
+      this.dialogVisible = false;
+      this.moduleForm = {
+        name: "",
+        status: 5,
+        category_id: "",
+      };
+    },
+    /* 确定修改模块*/
+    submitModule() {
+      this.$refs.moduleRef.validate((valid) => {
+        if (valid) {
+          updateTemplate(this.moduleForm).then((res) => {
+            if (res.status !== 200) return;
+            this.$message.success("修改成功!");
+            this.dialogVisible = false;
+            this.moduleForm = {
+              name: "",
+              status: 5,
+              category_id: "",
+            };
+            this.onSubmit()
+          });
+        }
+      });
+    },
+    /* 获取分类 */
+    async initCategoryList() {
+      let _this = this;
+      let res = await treeCategory();
+      this.categoryList = res.data; //this.processDataForCascader(res.data);
+    },
+
+    EditorInfo(item){
+      this.dialogVisible=true
+      this.moduleForm =item
+    },
+    checkAuth(path) {
+      if (this.roleInfo.is_admin == 1) {
+        return true;
+      }
+      let auth = this.authList.filter((o) => o.type == 999 && o.path == path);
+      if (auth.length > 0) {
+        return true;
+      }
+      return false;
+    },
+
+    btnDelete(e) {
+      let _this = this;
+      let par = {
+        id: e,
+      };
+      _this
+        .$confirm("您是否确认删除该记录?", "提示", {
+          confirmButtonText: "确认",
+          cancelButtonText: "取消",
+          type: "warning",
+        })
+        .then((res) => {
+          // console.log("AAA")
+          deleteTemplate(par).then((res) => {
+            _this.search();
+          });
+        })
+        .catch(() => {});
+    },
+
+    searchData() {
+      let _this = this;
+      _this.dialogVisible = false;
+      _this.search();
+    },
+
+    //编辑
+    btnEdit(e) {
+      this.$router.push("system/document/create?templateId=" + e + "&type=module");
+     /*  let _this = this;
+      var a = document.createElement("a");
+      a.href = "#/document/create?templateId=" + e + "&type=module";
+      a.target = "_blank";
+      a.click(); */
+      //this.$router.push({path:"/document/create",query:{templateId:e}})
+    },
+
+    handleClose() {
+      let _this = this;
+      _this.currentDataId = 0;
+      _this.dialogVisible = false;
+      _this.search();
+    },
+
+    //搜索
+    search() {
+      let _this = this;
+      pageTemplate(_this.queryForm).then((res) => {
+        if (!res) return;
+        _this.dataList = res.data.dataList;
+        _this.recordCount = res.data.totalRecord;
+        _this.pageTotal = res.data.totalPage;
+      });
+    },
+    //修改分页
+    ChangePage(e) {
+      let _this = this;
+      _this.queryForm.page = e;
+      _this.search();
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+@import "./dataList.scss";
+</style>

+ 3 - 0
ui/src/views/system/template/components/dataSearch.scss

@@ -0,0 +1,3 @@
+.data-search{ 
+  padding:20px 10px 0px 10px;
+}

+ 256 - 0
ui/src/views/system/template/components/dataSearch.vue

@@ -0,0 +1,256 @@
+<template>
+  <div class="data-search">
+    <el-form :inline="true" :model="queryForm" class="demo-form-inline">
+      <el-form-item label="模块名称:">
+        <el-input
+          v-model="queryForm.name"
+          placeholder="请选择模块名称"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="所属分类:">
+        <el-select
+          v-model="queryForm.category_id"
+          clearable
+          class="m-2"
+          placeholder="请选择分类"
+          size="large"
+        >
+          <el-option
+            v-for="item in categoryList"
+            :key="item.id"
+            :label="item.name"
+            :value="item.id"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="模块状态:">
+        <el-select
+          v-model="queryForm.status"
+          class="m-2"
+          placeholder="请选择模板块态"
+          size="large"
+        >
+          <el-option
+            v-for="item in statusOptions"
+            :key="item.value"
+            :label="item.label"
+            :value="item.value"
+          />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item>
+        <el-button type="primary" @click="onSubmit">
+          <svg-icon icon-class="search" /> 搜索</el-button
+        >
+        <el-button type="success" @click="onCreate">
+          <svg-icon icon-class="edit" /> 创建模块</el-button
+        >
+      </el-form-item>
+    </el-form>
+    <el-dialog
+      :visible.sync="dialogVisible"
+      append-to-body
+      v-el-drag-dialog
+      :close-on-click-modal="false"
+      width="30%"
+      custom-class="prod-verify"
+      title="创建模块"
+    >
+      <el-form
+        :model="moduleForm"
+        :rules="moduleRules"
+        ref="moduleRef"
+        label-position="right"
+        label-width="100px"
+      >
+        <el-form-item label="模块名称:" prop="name">
+          <el-input
+            style="width: 220px"
+            v-model="moduleForm.name"
+            placeholder="请选择模块名称"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="所属分类:" prop="category_id">
+          <el-cascader
+            v-model="moduleForm.category_id"
+            clearable
+            :options="categoryList"
+            :props="props"
+            :show-all-levels="false"
+            @change="onChangeCategory"
+            placeholder="请选择模块分类"
+          />
+          <!-- <el-select
+            v-model="moduleForm.category_id"
+            clearable
+            class="m-2"
+            placeholder="请选择分类"
+            size="large"
+          >
+            <el-option
+              v-for="item in categoryList"
+              :key="item.id"
+              :label="item.name"
+              :value="item.id"
+            />
+          </el-select> -->
+        </el-form-item>
+        <el-form-item label="模块状态:" prop="status">
+          <el-select
+            v-model="moduleForm.status"
+            class="m-2"
+            placeholder="请选择模板块态"
+            size="large"
+          >
+            <el-option
+              v-for="item in statusOptions"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="closeModule">取 消</el-button>
+        <el-button type="primary" @click="submitModule">确 定</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import dataInfo from "./dataInfo.vue";
+import elDragDialog from "@/directive/el-drag-dialog";
+import {
+  searchTemplateCategory,
+  createTemplate,
+  getAllList,
+  treeCategory
+} from "@/api/template";
+export default {
+  components: {
+    dataInfo,
+  },
+  directives: { elDragDialog },
+  props: {
+    queryForm: {
+      type: Object,
+      default: () => {
+        return {
+          page: 1,
+          pageSize: 10,
+          name: "",
+          category_id: "",
+          status: "",
+        };
+      },
+    },
+  },
+  data() {
+    return {
+      statusOptions: [
+        {
+          value: "",
+          label: "请选择状态",
+        },
+        {
+          value: 5,
+          label: "启用",
+        },
+        {
+          value: 6,
+          label: "停用",
+        },
+      ],
+      categoryList: [],
+      dialogVisible: false,
+      moduleForm: {
+        name: "",
+        status: 5,
+        category_id: "",
+      },
+      props: {
+        value: "id",
+        label: "name",
+        children: "children",
+        checkStrictly: true,
+      },
+      moduleRules: {
+        name: [{ required: true, message: "请输模块名称", trigger: "blur" }],
+        status: [{ required: true, message: "请选择状态", trigger: "change" }],
+        category_id: [
+          { required: true, message: "请选择分类", trigger: "change" },
+        ],
+      },
+    };
+  },
+  mounted() {
+    this.initCategoryList();
+  },
+  methods: {
+    onChangeCategory(){},
+    /* 取消新增 */
+    closeModule() {
+      this.dialogVisible = false;
+      this.moduleForm = {
+        name: "",
+        status: 5,
+        category_id: "",
+      };
+    },
+    /* 确定新增模块*/
+    submitModule() {
+      this.$refs.moduleRef.validate((valid) => {
+        if (valid) {
+          this.moduleForm.category_id = this.moduleForm.category_id[this.moduleForm.category_id.length - 1];
+          createTemplate(this.moduleForm).then((res) => {
+            if (res.status !== 200) return;
+            this.$message.success("创建成功!");
+            this.dialogVisible = false;
+            this.moduleForm = {
+              name: "",
+              status: 5,
+              category_id: "",
+            };
+            this.onSubmit();
+          });
+        }
+      });
+    },
+    /* 获取分类 */
+    async initCategoryList() {
+      let _this = this;
+      let res = await treeCategory();
+      this.categoryList = res.data; //this.processDataForCascader(res.data);
+    },
+    /*    initCategory() {
+      let _this = this;
+      searchTemplateCategory({ page: 1, pageSize: 999, status: 5 }).then(
+        (res) => {
+          if (res.status != 200) return;
+          _this.categoryList = res.data.dataList;
+        }
+      );
+    }, */
+    onCreate(e) {
+      this.dialogVisible = true;
+      /* let _this = this;
+      var a = document.createElement("a");
+      a.href = "#/document/create?type=module";
+      a.target = "_blank";
+      a.click(); */
+    },
+
+    //搜索
+    onSubmit() {
+      this.$emit("bindSetQuery", this.$props.queryForm);
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+@import "./dataSearch.scss";
+</style>

+ 3 - 0
ui/src/views/system/template/components/index.js

@@ -0,0 +1,3 @@
+export { default as dataSearch } from './dataSearch'
+export { default as dataList } from './dataList'
+export { default as dataInfo } from './dataInfo'

+ 4 - 0
ui/src/views/system/template/search.scss

@@ -0,0 +1,4 @@
+.project-search{
+  padding:30px;
+  font-size:12px;
+}

+ 43 - 0
ui/src/views/system/template/search.vue

@@ -0,0 +1,43 @@
+<template>
+  <div class="project-search">
+    <dataSearch @bindSetQuery="setQuery"></dataSearch>
+    <dataList :queryForm="queryForm"></dataList>
+  </div>
+
+</template>
+
+<script>
+import {dataSearch,dataList} from "./components"
+export default{
+  components:{
+    dataSearch,
+    dataList,
+  },
+  data(){
+    return{
+        queryForm:{
+          page:1,
+          pageSize:10,
+          name:'',
+          parent_id:0,
+          status:'',
+        },
+    }
+  },
+
+  mounted() {
+    this.queryForm.parent_id=this.$route.query.parent_id==undefined?0:this.$route.query.parent_id;
+  },
+  methods:{
+
+    setQuery(e){
+      this.queryForm=e;
+    }
+
+  }
+}
+</script>
+
+<style lang="scss">
+@import './search.scss'
+</style>

+ 0 - 0
微信存储/WeChat Files/wxid_iwkr69dui1bt12/FileStorage/File/2024-11/index.vue


Some files were not shown because too many files changed in this diff