zcy 4 лет назад
Родитель
Сommit
da6fe3e07f

+ 1 - 0
package.json

@@ -14,6 +14,7 @@
     "test:ci": "npm run lint && npm run test:unit"
   },
   "dependencies": {
+    "ant-design-vue": "^1.7.8",
     "axios": "0.18.1",
     "core-js": "3.6.5",
     "element-ui": "2.13.2",

+ 60 - 0
src/assets/less/common.less

@@ -0,0 +1,60 @@
+/*列表上方操作按钮区域*/
+.ant-card-body .table-operator {
+  margin-bottom: 8px;
+}
+/** Button按钮间距 */
+.table-operator .ant-btn {
+  margin: 0 8px 8px 0;
+}
+.table-operator .ant-btn-group .ant-btn {
+  margin: 0;
+}
+
+.table-operator .ant-btn-group .ant-btn:last-child {
+  margin: 0 8px 8px 0;
+}
+/*列表td的padding设置 可以控制列表大小*/
+.ant-table-tbody .ant-table-row td {
+  padding-top: 15px;
+  padding-bottom: 15px;
+}
+
+/*列表页面弹出modal*/
+.ant-modal-cust-warp {
+  height: 100%
+}
+
+/*弹出modal Y轴滚动条*/
+.ant-modal-cust-warp .ant-modal-body {
+  height: calc(100% - 110px) !important;
+  overflow-y: auto
+}
+
+/*弹出modal 先有content后有body 故滚动条控制在body上*/
+.ant-modal-cust-warp .ant-modal-content {
+  height: 90% !important;
+  overflow-y: hidden
+}
+/*列表中有图片的加这个样式 参考用户管理*/
+.anty-img-wrap {
+  height: 25px;
+  position: relative;
+}
+.anty-img-wrap > img {
+  max-height: 100%;
+}
+/*列表中范围查询样式*/
+.query-group-cust{width: calc(50% - 10px)}
+.query-group-split-cust:before{content:"~";width: 20px;display: inline-block;text-align: center}
+
+
+/*erp风格子表外框padding设置*/
+.ant-card-wider-padding.cust-erp-sub-tab>.ant-card-body{padding:5px 12px}
+
+/* 内嵌子表背景颜色 */
+.j-inner-table-wrapper /deep/ .ant-table-expanded-row .ant-table-wrapper .ant-table-tbody .ant-table-row {
+  background-color: #FFFFFF;
+}
+
+/**隐藏样式-modal确定按钮 */
+.jee-hidden{display: none}

+ 1 - 1
src/layout/components/AppMain.vue

@@ -38,7 +38,7 @@ export default {
 .hasTagsView {
   .app-main {
     /* 84 = navbar + tags-view = 50 + 34 */
-    min-height: calc(100vh - 84px);
+    min-height: calc(100vh);
   }
 
   .fixed-header+.app-main {

+ 3 - 0
src/main.js

@@ -7,6 +7,8 @@ import 'normalize.css/normalize.css' // a modern alternative to CSS resets
 import Element from 'element-ui'
 import './styles/element-variables.scss'
 import enLang from 'element-ui/lib/locale/lang/en'// 如果使用中文语言包请默认支持,无需额外引入,请删除该依赖
+import Antd from 'ant-design-vue'
+import 'ant-design-vue/dist/antd.css'
 
 import '@/styles/index.scss' // global css
 
@@ -19,6 +21,7 @@ import './permission' // permission control
 import './utils/error-log' // error log
 
 import * as filters from './filters' // global filters
+Vue.use(Antd)
 
 /**
  * If you don't want to use mock-server

+ 96 - 2
src/mixin/listMixin.js

@@ -3,10 +3,12 @@
  * 高级查询按钮调用 superQuery方法  高级查询组件ref定义为superQueryModal
  * data中url定义 list为查询列表  delete为删除单条记录  deleteBatch为批量删除
  */
+import Vue from 'vue'
 import { filterObj } from '@/utils/util'
 import { postAction, getAction } from '@/api/request'
+import store from '@/store'
 
-export const JeecgListMixin = {
+export const listMixin = {
   data() {
     return {
       /* 查询条件-请不要在queryParam中声明非字符串值的属性 */
@@ -57,6 +59,11 @@ export const JeecgListMixin = {
     }
   },
   computed: {
+    // token header
+    tokenHeader() {
+      const head = { 'Authorization': store.getters.token }
+      return head
+    }
   },
   methods: {
     loadData(arg) {
@@ -70,7 +77,7 @@ export const JeecgListMixin = {
       }
       var params = this.getQueryParams()// 查询条件
       this.loading = true
-      getAction(this.url.list, params).then((res) => {
+      postAction(this.url.list, params).then((res) => {
         if (res.success) {
           // update-begin---author:zhangyafei    Date:20201118  for:适配不分页的数据列表------------
           this.dataSource = res.result.records || res.result
@@ -244,6 +251,93 @@ export const JeecgListMixin = {
       this.$refs.modalForm.edit(record)
       this.$refs.modalForm.title = '详情'
       this.$refs.modalForm.disableSubmit = true
+    },
+    /* 导出 */
+    handleExportXls2() {
+      const paramsStr = encodeURI(JSON.stringify(this.getQueryParams()))
+      const url = ``
+      window.location.href = url
+    },
+    handleExportXls(fileName) {
+      if (!fileName || typeof fileName !== 'string') {
+        fileName = '导出文件'
+      }
+      const param = this.getQueryParams()
+      if (this.selectedRowKeys && this.selectedRowKeys.length > 0) {
+        param['selections'] = this.selectedRowKeys.join(',')
+      }
+      console.log('导出参数', param)
+      downFile(this.url.exportXlsUrl, param).then((data) => {
+        if (!data) {
+          this.$message.warning('文件下载失败')
+          return
+        }
+        if (typeof window.navigator.msSaveBlob !== 'undefined') {
+          window.navigator.msSaveBlob(new Blob([data], { type: 'application/vnd.ms-excel' }), fileName + '.xls')
+        } else {
+          const url = window.URL.createObjectURL(new Blob([data], { type: 'application/vnd.ms-excel' }))
+          const link = document.createElement('a')
+          link.style.display = 'none'
+          link.href = url
+          link.setAttribute('download', fileName + '.xls')
+          document.body.appendChild(link)
+          link.click()
+          document.body.removeChild(link) // 下载完成移除元素
+          window.URL.revokeObjectURL(url) // 释放掉blob对象
+        }
+      })
+    },
+    /* 导入 */
+    handleImportExcel(info) {
+      this.loading = true
+      if (info.file.status !== 'uploading') {
+        console.log(info.file, info.fileList)
+      }
+      if (info.file.status === 'done') {
+        this.loading = false
+        if (info.file.response.success) {
+          // this.$message.success(`${info.file.name} 文件上传成功`);
+          if (info.file.response.code === 201) {
+            const { message, result: { msg, fileUrl, fileName }} = info.file.response
+            const href = fileUrl
+            this.$warning({
+              title: message,
+              content: (<div>
+                <span>{msg}</span><br/>
+                <span>具体详情请 <a href={href} target='_blank' download={fileName}>点击下载</a> </span>
+              </div>
+              )
+            })
+          } else {
+            this.$message.success(info.file.response.message || `${info.file.name} 文件上传成功`)
+          }
+          this.loadData()
+        } else {
+          this.$message.error(`${info.file.name} ${info.file.response.message}.`)
+        }
+      } else if (info.file.status === 'error') {
+        this.loading = false
+        if (info.file.response.status === 500) {
+          const data = info.file.response
+          const token = store.getters.token
+          if (token && data.message.includes('Token失效')) {
+            this.$error({
+              title: '登录已过期',
+              content: '很抱歉,登录已过期,请重新登录',
+              okText: '重新登录',
+              mask: false,
+              onOk: () => {
+                store.dispatch('Logout').then(() => {
+                  Vue.ls.remove(ACCESS_TOKEN)
+                  window.location.reload()
+                })
+              }
+            })
+          }
+        } else {
+          this.$message.error(`文件上传失败: ${info.file.msg} `)
+        }
+      }
     }
   }
 }

+ 17 - 1
src/router/index.js

@@ -101,7 +101,23 @@ export const constantRoutes = [
       }
     ]
   },
-
+  {
+    path: '/basics',
+    component: Layout,
+    redirect: '/basics/pillar',
+    name: 'basics',
+    meta: {
+      title: '基础数据管理'
+    },
+    children: [
+      {
+        path: 'pillar',
+        component: () => import('@/views/basics/pillar/index'), // Parent router-view
+        name: 'pillar',
+        meta: { title: '支柱数据管理' }
+      }
+    ]
+  },
   {
     path: 'external-link',
     component: Layout,

+ 77 - 0
src/utils/util.js

@@ -0,0 +1,77 @@
+
+export function timeFix() {
+  const time = new Date()
+  const hour = time.getHours()
+  return hour < 9 ? '早上好' : (hour <= 11 ? '上午好' : (hour <= 13 ? '中午好' : (hour < 20 ? '下午好' : '晚上好')))
+}
+
+export function welcome() {
+  const arr = ['休息一会儿吧', '准备吃什么呢?', '要不要打一把 DOTA', '我猜你可能累了']
+  const index = Math.floor((Math.random() * arr.length))
+  return arr[index]
+}
+
+/**
+ * 触发 window.resize
+ */
+export function triggerWindowResizeEvent() {
+  const event = document.createEvent('HTMLEvents')
+  event.initEvent('resize', true, true)
+  event.eventType = 'message'
+  window.dispatchEvent(event)
+}
+
+/**
+ * 过滤对象中为空的属性
+ * @param obj
+ * @returns {*}
+ */
+export function filterObj(obj) {
+  if (!(typeof obj === 'object')) {
+    return
+  }
+
+  for (const key in obj) {
+    if (obj.hasOwnProperty(key) &&
+      (obj[key] == null || obj[key] == undefined || obj[key] === '')) {
+      delete obj[key]
+    }
+  }
+  return obj
+}
+
+/**
+ * 时间格式化
+ * @param value
+ * @param fmt
+ * @returns {*}
+ */
+export function formatDate(value, fmt) {
+  const regPos = /^\d+(\.\d+)?$/
+  if (regPos.test(value)) {
+    // 如果是数字
+    const getDate = new Date(value)
+    const o = {
+      'M+': getDate.getMonth() + 1,
+      'd+': getDate.getDate(),
+      'h+': getDate.getHours(),
+      'm+': getDate.getMinutes(),
+      's+': getDate.getSeconds(),
+      'q+': Math.floor((getDate.getMonth() + 3) / 3),
+      'S': getDate.getMilliseconds()
+    }
+    if (/(y+)/.test(fmt)) {
+      fmt = fmt.replace(RegExp.$1, (getDate.getFullYear() + '').substr(4 - RegExp.$1.length))
+    }
+    for (const k in o) {
+      if (new RegExp('(' + k + ')').test(fmt)) {
+        fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
+      }
+    }
+    return fmt
+  } else {
+    // TODO
+    value = value.trim()
+    return value.substr(0, fmt.length)
+  }
+}

+ 174 - 0
src/views/basics/pillar/index.vue

@@ -0,0 +1,174 @@
+<template>
+  <a-card :bordered="false" class="card-area">
+
+    <!-- 查询区域 -->
+    <div class="table-page-search-wrapper">
+      <!-- 搜索区域 -->
+      <a-form layout="inline" @keyup.enter.native="searchQuery">
+        <a-row :gutter="24">
+          <a-col :md="6" :sm="8">
+            <a-form-item label="名称" :label-col="{span: 5}" :wrapper-col="{span: 18, offset: 1}">
+              <a-input v-model="queryParam.roleName" placeholder="请输入名称查询" />
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="8">
+            <a-form-item label="创建时间" :label-col="{span: 5}" :wrapper-col="{span: 18, offset: 1}">
+              <a-input v-model="queryParam.roleName" placeholder="请输入名称查询" />
+            </a-form-item>
+          </a-col>
+          <span class="table-page-search-submitButtons">
+            <a-col :md="6" :sm="24">
+              <a-button type="primary" @click="searchQuery">查询</a-button>
+              <a-button style="margin-left: 8px" @click="searchReset">重置</a-button>
+            </a-col>
+          </span>
+        </a-row>
+      </a-form>
+    </div>
+
+    <!-- 操作按钮区域 -->
+    <div class="table-operator" style="margin-top: 5px">
+      <a-button type="primary" icon="plus" @click="handleAdd">新增</a-button>
+      <a-button type="primary" icon="download" @click="handleExportXls('角色信息')">导出</a-button>
+      <a-upload name="file" :show-upload-list="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
+        <a-button type="primary" icon="import">导入</a-button>
+      </a-upload>
+
+      <a-dropdown v-if="selectedRowKeys.length > 0">
+        <a-menu slot="overlay">
+          <a-menu-item key="1" @click="batchDel"><a-icon type="delete" />删除</a-menu-item>
+        </a-menu>
+        <a-button style="margin-left: 8px">
+          批量操作 <a-icon type="down" />
+        </a-button>
+      </a-dropdown>
+    </div>
+
+    <!-- table区域-begin -->
+    <div>
+      <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
+        <i class="anticon anticon-info-circle ant-alert-icon" /> 已选择&nbsp;<a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项&nbsp;&nbsp;
+        <a style="margin-left: 24px" @click="onClearSelected">清空</a>
+      </div>
+
+      <a-table
+        ref="table"
+        size="middle"
+        bordered
+        row-key="id"
+        :columns="columns"
+        :data-source="dataSource"
+        :pagination="ipagination"
+        :loading="loading"
+        :row-selection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
+        @change="handleTableChange"
+      >
+
+        <span slot="action" slot-scope="text, record">
+          <a @click="handleEdit(record)">编辑</a>
+          <a-divider type="vertical" />
+          <a-dropdown>
+            <a class="ant-dropdown-link">
+              更多 <a-icon type="down" />
+            </a>
+            <a-menu slot="overlay">
+              <a-menu-item>
+                <a @click="handlePerssion(record.id)">授权</a>
+              </a-menu-item>
+              <a-menu-item>
+                <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
+                  <a>删除</a>
+                </a-popconfirm>
+              </a-menu-item>
+            </a-menu>
+          </a-dropdown>
+        </span>
+      </a-table>
+    </div>
+    <!-- table区域-end -->
+    <!-- 表单区域 -->
+  </a-card>
+</template>
+<script>
+import { listMixin } from '@/mixin/listMixin'
+export default {
+  name: 'RoleList',
+  components: {
+  },
+  mixins: [listMixin],
+  data() {
+    return {
+      description: '角色管理页面',
+      // 查询条件
+      queryParam: { roleName: '' },
+      // 表头
+      columns: [
+        {
+          title: '#',
+          dataIndex: '',
+          key: 'rowIndex',
+          width: 60,
+          align: 'center',
+          customRender: function(t, r, index) {
+            return parseInt(index) + 1
+          }
+        },
+        {
+          title: '角色名称',
+          align: 'center',
+          dataIndex: 'roleName'
+        },
+        {
+          title: '角色编码',
+          align: 'center',
+          dataIndex: 'roleCode'
+        },
+        {
+          title: '备注',
+          align: 'center',
+          dataIndex: 'description'
+        },
+        {
+          title: '创建时间',
+          dataIndex: 'createTime',
+          align: 'center',
+          sorter: true
+        },
+        {
+          title: '更新时间',
+          dataIndex: 'updateTime',
+          align: 'center',
+          sorter: true
+        },
+        {
+          title: '操作',
+          dataIndex: 'action',
+          align: 'center',
+          scopedSlots: { customRender: 'action' }
+        }
+      ],
+      url: {
+        list: '/business/bus/zzdzxx/list',
+        delete: '/sys/role/delete',
+        deleteBatch: '/sys/role/deleteBatch',
+        exportXlsUrl: '/sys/role/exportXls',
+        importExcelUrl: 'sys/role/importExcel'
+      }
+    }
+  },
+  computed: {
+    importExcelUrl: function() {
+      return `${this.url.importExcelUrl}`
+    }
+  },
+  methods: {
+    handlePerssion: function(roleId) {
+      // alert(roleId);
+      this.$refs.modalUserRole.show(roleId)
+    }
+  }
+}
+</script>
+<style scoped>
+  @import '~@/assets/less/common.less'
+</style>

+ 161 - 5
src/views/catenary/fault/index.vue

@@ -1,18 +1,174 @@
 <template>
-  <div class="app-container">
-  </div>
-</template>
+  <a-card :bordered="false" class="card-area">
 
-<script>
+    <!-- 查询区域 -->
+    <div class="table-page-search-wrapper">
+      <!-- 搜索区域 -->
+      <a-form layout="inline" @keyup.enter.native="searchQuery">
+        <a-row :gutter="24">
+          <a-col :md="6" :sm="8">
+            <a-form-item label="名称" :label-col="{span: 5}" :wrapper-col="{span: 18, offset: 1}">
+              <a-input v-model="queryParam.roleName" placeholder="请输入名称查询" />
+            </a-form-item>
+          </a-col>
+          <a-col :md="6" :sm="8">
+            <a-form-item label="创建时间" :label-col="{span: 5}" :wrapper-col="{span: 18, offset: 1}">
+              <a-input v-model="queryParam.roleName" placeholder="请输入名称查询" />
+            </a-form-item>
+          </a-col>
+          <span class="table-page-search-submitButtons">
+            <a-col :md="6" :sm="24">
+              <a-button type="primary" @click="searchQuery">查询</a-button>
+              <a-button style="margin-left: 8px" @click="searchReset">重置</a-button>
+            </a-col>
+          </span>
+        </a-row>
+      </a-form>
+    </div>
+
+    <!-- 操作按钮区域 -->
+    <div class="table-operator" style="margin-top: 5px">
+      <a-button type="primary" icon="plus" @click="handleAdd">新增</a-button>
+      <a-button type="primary" icon="download" @click="handleExportXls('角色信息')">导出</a-button>
+      <a-upload name="file" :show-upload-list="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
+        <a-button type="primary" icon="import">导入</a-button>
+      </a-upload>
+
+      <a-dropdown v-if="selectedRowKeys.length > 0">
+        <a-menu slot="overlay">
+          <a-menu-item key="1" @click="batchDel"><a-icon type="delete" />删除</a-menu-item>
+        </a-menu>
+        <a-button style="margin-left: 8px">
+          批量操作 <a-icon type="down" />
+        </a-button>
+      </a-dropdown>
+    </div>
+
+    <!-- table区域-begin -->
+    <div>
+      <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
+        <i class="anticon anticon-info-circle ant-alert-icon" /> 已选择&nbsp;<a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项&nbsp;&nbsp;
+        <a style="margin-left: 24px" @click="onClearSelected">清空</a>
+      </div>
+
+      <a-table
+        ref="table"
+        size="middle"
+        bordered
+        row-key="id"
+        :columns="columns"
+        :data-source="dataSource"
+        :pagination="ipagination"
+        :loading="loading"
+        :row-selection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
+        @change="handleTableChange"
+      >
 
+        <span slot="action" slot-scope="text, record">
+          <a @click="handleEdit(record)">编辑</a>
+          <a-divider type="vertical" />
+          <a-dropdown>
+            <a class="ant-dropdown-link">
+              更多 <a-icon type="down" />
+            </a>
+            <a-menu slot="overlay">
+              <a-menu-item>
+                <a @click="handlePerssion(record.id)">授权</a>
+              </a-menu-item>
+              <a-menu-item>
+                <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
+                  <a>删除</a>
+                </a-popconfirm>
+              </a-menu-item>
+            </a-menu>
+          </a-dropdown>
+        </span>
+      </a-table>
+    </div>
+    <!-- table区域-end -->
+    <!-- 表单区域 -->
+  </a-card>
+</template>
+<script>
+import { listMixin } from '@/mixin/listMixin'
 export default {
+  name: 'RoleList',
+  components: {
+  },
+  mixins: [listMixin],
   data() {
     return {
+      description: '角色管理页面',
+      // 查询条件
+      queryParam: { roleName: '' },
+      // 表头
+      columns: [
+        {
+          title: '#',
+          dataIndex: '',
+          key: 'rowIndex',
+          width: 60,
+          align: 'center',
+          customRender: function(t, r, index) {
+            return parseInt(index) + 1
+          }
+        },
+        {
+          title: '角色名称',
+          align: 'center',
+          dataIndex: 'roleName'
+        },
+        {
+          title: '角色编码',
+          align: 'center',
+          dataIndex: 'roleCode'
+        },
+        {
+          title: '备注',
+          align: 'center',
+          dataIndex: 'description'
+        },
+        {
+          title: '创建时间',
+          dataIndex: 'createTime',
+          align: 'center',
+          sorter: true
+        },
+        {
+          title: '更新时间',
+          dataIndex: 'updateTime',
+          align: 'center',
+          sorter: true
+        },
+        {
+          title: '操作',
+          dataIndex: 'action',
+          align: 'center',
+          scopedSlots: { customRender: 'action' }
+        }
+      ],
+      url: {
+        list: '/sys/role/list',
+        delete: '/sys/role/delete',
+        deleteBatch: '/sys/role/deleteBatch',
+        exportXlsUrl: '/sys/role/exportXls',
+        importExcelUrl: 'sys/role/importExcel'
+      }
     }
   },
-  created() {
+  computed: {
+    importExcelUrl: function() {
+      return `${this.url.importExcelUrl}`
+    }
   },
   methods: {
+    handlePerssion: function(roleId) {
+      // alert(roleId);
+      this.$refs.modalUserRole.show(roleId)
+    }
   }
 }
 </script>
+<style scoped>
+  @import '~@/assets/less/common.less'
+</style>