Przeglądaj źródła

Merge branch 'master' of https://gitee.ltd/pigx/pigx-ui into luckly_dev

huangxutao 6 lat temu
rodzic
commit
40c4555bd4

+ 3 - 1
package.json

@@ -10,13 +10,14 @@
   },
   "dependencies": {
     "@xkeshi/vue-qrcode": "^1.0.0",
+    "avue-form-design": "^1.1.1",
     "axios": "^0.18.0",
     "babel-polyfill": "^6.26.0",
     "classlist-polyfill": "^1.2.0",
     "clipboard": "^2.0.4",
     "crypto-js": "^3.1.9-1",
     "echarts": "^4.2.1",
-    "element-ui": "~2.10.0",
+    "element-ui": "^2.11.1",
     "js-cookie": "^2.2.0",
     "nprogress": "^0.2.0",
     "script-loader": "^0.7.2",
@@ -33,6 +34,7 @@
     "vuex": "^3.0.1"
   },
   "devDependencies": {
+    "@vue/cli-plugin-babel": "~3.8.0",
     "@vue/cli-service": "~3.8.4",
     "chai": "^4.1.2",
     "node-sass": "^4.9.0",

Plik diff jest za duży
+ 1 - 1
public/cdn/avue/index.css


Plik diff jest za duży
+ 3 - 3
public/cdn/avue/index.js


+ 7 - 0
src/api/daemon/sys-job.js

@@ -44,6 +44,13 @@ export function startJobRa(jobId) {
   })
 }
 
+export function runJobRa(jobId) {
+  return request({
+    url: '/job/sys-job/run-job/' + jobId,
+    method: 'post'
+  })
+}
+
 export function shutDownJobRa(jobId) {
   return request({
     url: '/job/sys-job/shutdown-job/' + jobId,

+ 56 - 0
src/api/gen/form.js

@@ -0,0 +1,56 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+import request from '@/router/axios'
+
+export function fetchList(query) {
+  return request({
+    url: '/gen/form/page',
+    method: 'get',
+    params: query
+  })
+}
+
+export function addObj(obj) {
+  return request({
+    url: '/gen/form',
+    method: 'post',
+    data: obj
+  })
+}
+
+export function getObj(id) {
+  return request({
+    url: '/gen/form/' + id,
+    method: 'get'
+  })
+}
+
+export function delObj(id) {
+  return request({
+    url: '/gen/form/' + id,
+    method: 'delete'
+  })
+}
+
+export function putObj(obj) {
+  return request({
+    url: '/gen/form',
+    method: 'put',
+    data: obj
+  })
+}

+ 19 - 2
src/api/gen/gen.js

@@ -77,16 +77,33 @@ export function handleDown(table) {
     data: table,
     responseType: 'arraybuffer'
   }).then((response) => { // 处理返回的文件流
-    const blob = new Blob([response.data], { type: 'application/zip' })
+    const blob = new Blob([response.data], {type: 'application/zip'})
     const filename = table.tableName + '.zip'
     const link = document.createElement('a')
     link.href = URL.createObjectURL(blob)
     link.download = filename
     document.body.appendChild(link)
     link.click()
-    window.setTimeout(function() {
+    window.setTimeout(function () {
       URL.revokeObjectURL(blob)
       document.body.removeChild(link)
     }, 0)
   })
 }
+
+
+export function getForm(tableName, dsId) {
+  return request({
+    url: '/gen/form/info',
+    params: {tableName: tableName, dsId: dsId},
+    method: 'get'
+  })
+}
+
+export function postForm(formInfo, tableName, dsId) {
+  return request({
+    url: '/gen/form/',
+    method: 'post',
+    data: Object.assign({formInfo, tableName, dsId})
+  })
+}

+ 1 - 1
src/config/env.js

@@ -3,7 +3,7 @@
 const env = process.env
 const baseUrl = ''
 // 图表库为avue和pig2套地址
-const iconfontVersion = ['567566_qo5lxgtishg', '667895_cg8sxwocfzr']
+const iconfontVersion = ['567566_qo5lxgtishg', '667895_v7uduh4zui']
 const iconfontUrl = '//at.alicdn.com/t/font_$key.css'
 const codeUrl = `${window.location.origin}/code`
 const actUrl = `${window.location.origin}/act/modeler.html?modelId=`

+ 30 - 23
src/const/crud/admin/client.js

@@ -65,53 +65,60 @@ export const tableOption = {
       trigger: 'blur'
     }]
   }, {
-    label: '授权模式',
-    prop: 'authorizedGrantTypes',
+    label: '自动放行',
+    prop: 'autoapprove',
     align: 'center',
-    overHidden: true,
+    type: 'radio',
+    border:true,
+    dicData: DIC.vaild,
     rules: [{
       required: true,
-      message: '请输入授权模式',
+      message: '请选择是否放行',
       trigger: 'blur'
     }]
   }, {
-    label: '回调地址',
-    prop: 'webServerRedirectUri',
-    align: 'center',
-    hide: true
-  }, {
-    label: '权限',
-    prop: 'authorities',
-    align: 'center',
-    hide: true
-  }, {
-    label: '自动放行',
-    prop: 'autoapprove',
+    label: '授权模式',
+    prop: 'authorizedGrantTypes',
+    type: 'checkbox',
+    dicUrl: '/admin/dict/type/grant_types',
     align: 'center',
-    type: 'radio',
-    dicData: DIC.vaild,
+    overHidden: true,
+    row: true,
+    span: 24,
     rules: [{
       required: true,
-      message: '请选择是否放行',
+      message: '请输入授权模式',
       trigger: 'blur'
     }]
   }, {
     label: '令牌时效',
+    type: 'number',
     prop: 'accessTokenValidity',
     align: 'center'
   }, {
     label: '刷新时效',
+    type: 'number',
     prop: 'refreshTokenValidity',
     align: 'center'
   }, {
-    label: '扩展信息',
-    prop: 'additionalInformation',
+    label: '回调地址',
+    prop: 'webServerRedirectUri',
     align: 'center',
     hide: true
   }, {
-    label: '资源ID',
-    prop: 'resourceIds',
+    label: '权限',
+    prop: 'authorities',
     align: 'center',
     hide: true
+  }, {
+    label: '扩展信息',
+    prop: 'additionalInformation',
+    align: 'center',
+    type: 'textarea',
+    placeholder: 'JSON格式数据',
+    hide: true,
+    minRows: 2,
+    row: true,
+    span: 24,
   }]
 }

+ 1 - 1
src/const/crud/admin/dict.js

@@ -44,7 +44,7 @@ export const tableOption = {
   }, {
     label: '字典类型',
     prop: 'system',
-    type: 'select',
+    type: 'radio',
     dicUrl: '/admin/dict/type/dict_type',
     addDisplay: false,
     editDisplay: false,

+ 3 - 1
src/const/crud/admin/tenant.js

@@ -41,6 +41,7 @@ export const tableOption = {
     },
     {
       label: '租户编号',
+      type: 'number',
       prop: 'code',
       rules: [{
         required: true,
@@ -75,7 +76,8 @@ export const tableOption = {
     {
       label: '状态',
       prop: 'status',
-      type: 'select',
+      type: 'radio',
+      border:true,
       dicUrl: '/admin/dict/type/status_type',
       search: true
     }

+ 12 - 9
src/const/crud/admin/user.js

@@ -14,7 +14,8 @@
  * this software without specific prior written permission.
  * Author: lengleng (wangiegie@gmail.com)
  */
-import { getDetails } from '@/api/admin/user'
+import {getDetails} from '@/api/admin/user'
+
 
 var validateUsername = (rule, value, callback) => {
   getDetails(value).then(response => {
@@ -57,13 +58,13 @@ export const tableOption = {
       required: true,
       message: '请输入用户名'
     },
-    {
-      min: 3,
-      max: 20,
-      message: '长度在 3 到 20 个字符',
-      trigger: 'blur'
-    },
-    { validator: validateUsername, trigger: 'blur' }
+      {
+        min: 3,
+        max: 20,
+        message: '长度在 3 到 20 个字符',
+        trigger: 'blur'
+      },
+      {validator: validateUsername, trigger: 'blur'}
     ]
   }, {
     label: '密码',
@@ -85,6 +86,7 @@ export const tableOption = {
     slot: true,
     span: 24,
     hide: true,
+    dataType:"number",
     rules: [{
       required: true,
       message: '请选择部门',
@@ -117,8 +119,9 @@ export const tableOption = {
   }, {
     label: '状态',
     prop: 'lockFlag',
-    type: 'select',
+    type: 'radio',
     slot: true,
+    border:true,
     span: 24,
     rules: [{
       required: true,

+ 56 - 0
src/const/crud/gen/form.js

@@ -0,0 +1,56 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+export const tableOption = {
+  border: true,
+  index: true,
+  indexLabel: '序号',
+  stripe: true,
+  menuAlign: 'center',
+  align: 'center',
+  viewBtn: true,
+  editBtn: false,
+  addBtn: false,
+  column: [
+    {
+      label: 'ID',
+      prop: 'id',
+      hide: true,
+    },
+    {
+      label: '表名称',
+      prop: 'tableName'
+    },
+    {
+      label: '创建时间',
+      prop: 'createTime',
+      type: 'datetime',
+      format: 'yyyy-MM-dd HH:mm:ss',
+      valueFormat: 'yyyy-MM-dd HH:mm:ss'
+    },
+    {
+      label: '表单信息',
+      prop: 'formInfo',
+      overHidden: true,
+      width: 500,
+      type: 'textarea',
+      minRows: 3,
+      row: true,
+      span: 24
+    }
+  ]
+}

+ 32 - 0
src/const/crud/gen/gen.js

@@ -16,6 +16,7 @@
  */
 
 export const tableOption = {
+  selection: true,
   border: true,
   index: true,
   stripe: true,
@@ -76,6 +77,37 @@ export const formOption = {
     }
   ]
 }
+export const formBatchOption = {
+  submitText: '生成',
+  column: [
+    {
+      label: '表名称',
+      prop: 'tableName',
+      disabled: true,
+      minRows: 2,
+      type: 'textarea',
+      row: true,
+      span: 24
+    },
+    {
+      label: '包名',
+      prop: 'packageName',
+      placeholder: '可为空,加载系统默认配置'
+    }, {
+      label: '作者',
+      prop: 'author',
+      placeholder: '可为空,加载系统默认配置'
+    }, {
+      label: '模块',
+      prop: 'moduleName',
+      placeholder: '可为空,加载系统默认配置'
+    }, {
+      label: '注释',
+      prop: 'comments',
+      placeholder: '可为空,加载表备注'
+    }
+  ]
+}
 
 export const tableDsOption = {
   border: true,

+ 5 - 1
src/const/iconList.js

@@ -37,7 +37,11 @@ export default [
       'icon-tuikuan',
       'icon-webicon14',
       'icon-shouyintai',
-      'icon-wenjianguanli'
+      'icon-wenjianguanli',
+      'icon-mysql',
+      'icon-shejiyukaifa-',
+      'icon-record',
+      'icon-biaodanbiaoqian'
     ]
   }
 ]

+ 3 - 1
src/main.js

@@ -15,17 +15,19 @@ import * as filters from './filters' // 全局filter
 import ElementUI from 'element-ui'
 import 'element-ui/lib/theme-chalk/index.css'
 import './styles/common.scss'
+import avueFormDesign from 'avue-form-design'
 import basicContainer from './components/basic-container/main'
 // 插件 json 展示
 import vueJsonTreeView from 'vue-json-tree-view'
 
 Vue.use(router)
 
+Vue.use(avueFormDesign);
 Vue.use(vueJsonTreeView)
 
 Vue.use(VueAxios, axios)
 
-Vue.use(ElementUI,{
+Vue.use(ElementUI, {
   size: 'medium',
   menuType: 'text'
 })

+ 119 - 112
src/page/index/index.vue

@@ -36,129 +36,136 @@
 </template>
 
 <script>
-import { mapGetters } from 'vuex'
-import tags from './tags'
-import top from './top/'
-import sidebar from './sidebar/'
-import admin from '@/util/admin'
-import { getStore } from '@/util/store.js'
-import * as SockJS from 'sockjs-client'
-import Stomp from 'stomp-websocket'
-import store from '@/store'
+  import {mapGetters} from 'vuex'
+  import tags from './tags'
+  import top from './top/'
+  import sidebar from './sidebar/'
+  import admin from '@/util/admin'
+  import {getStore} from '@/util/store.js'
+  import * as SockJS from 'sockjs-client'
+  import Stomp from 'stomp-websocket'
+  import store from '@/store'
 
-export default {
-  name: 'Index',
-  components: {
-    top,
-    tags,
-    sidebar
-  },
-  data() {
-    return {
-      // 刷新token锁
-      refreshLock: false,
-      // 刷新token的时间
-      refreshTime: '',
-      // 计时器
-      timer: ''
-    }
-  },
-  created() {
-    // 实时检测刷新token
-    this.refreshToken()
-  },
-  destroyed() {
-    clearInterval(this.refreshTime)
-    clearInterval(this.timer)
-    this.disconnect()
-  },
-  mounted() {
-    this.init()
-    this.initWebSocket()
-  },
-  computed: mapGetters(['userInfo', 'isLock', 'isCollapse', 'website', 'expires_in']),
-  methods: {
-    showCollapse() {
-      this.$store.commit('SET_COLLAPSE')
+  export default {
+    name: 'Index',
+    components: {
+      top,
+      tags,
+      sidebar
     },
-    // 屏幕检测
-    init() {
-      this.$store.commit('SET_SCREEN', admin.getScreen())
-      window.onresize = () => {
-        setTimeout(() => {
-          this.$store.commit('SET_SCREEN', admin.getScreen())
-        }, 0)
+    data() {
+      return {
+        // 刷新token锁
+        refreshLock: false,
+        // 刷新token的时间
+        refreshTime: '',
+        // 计时器
+        timer: ''
       }
     },
-    // 实时检测刷新token
-    refreshToken() {
-      this.refreshTime = setInterval(() => {
-        const token = getStore({
-          name: 'access_token',
-          debug: true
-        })
+    created() {
+      // 实时检测刷新token
+      this.refreshToken()
+    },
+    destroyed() {
+      clearInterval(this.refreshTime)
+      clearInterval(this.timer)
+      /*
+      * 默认关闭websocket,如需工作流通知,则开启
+      * this.disconnect()
+      */
 
-        if (this.validatenull(token)) {
-          return
+    },
+    mounted() {
+      this.init()
+      /*
+       * 默认关闭websocket,如需工作流通知,则开启
+       * this.initWebSocket()
+      */
+    },
+    computed: mapGetters(['userInfo', 'isLock', 'isCollapse', 'website', 'expires_in']),
+    methods: {
+      showCollapse() {
+        this.$store.commit('SET_COLLAPSE')
+      },
+      // 屏幕检测
+      init() {
+        this.$store.commit('SET_SCREEN', admin.getScreen())
+        window.onresize = () => {
+          setTimeout(() => {
+            this.$store.commit('SET_SCREEN', admin.getScreen())
+          }, 0)
         }
+      },
+      // 实时检测刷新token
+      refreshToken() {
+        this.refreshTime = setInterval(() => {
+          const token = getStore({
+            name: 'access_token',
+            debug: true
+          })
 
-        if (this.expires_in <= 1000 && !this.refreshLock) {
-          this.refreshLock = true
-          this.$store
-            .dispatch('RefreshToken')
-            .catch(() => {
-              clearInterval(this.refreshTime)
-            })
-          this.refreshLock = false
-        }
-        this.$store.commit('SET_EXPIRES_IN', this.expires_in - 10)
-      }, 10000)
-    },
-    initWebSocket() {
-      this.connection()
-      const self = this
-      // 断开重连机制,尝试发送消息,捕获异常发生时重连
-      this.timer = setInterval(() => {
-        try {
-          self.stompClient.send('test')
-        } catch (err) {
-          console.log('断线了: ' + err)
-          self.connection()
+          if (this.validatenull(token)) {
+            return
+          }
+
+          if (this.expires_in <= 1000 && !this.refreshLock) {
+            this.refreshLock = true
+            this.$store
+              .dispatch('RefreshToken')
+              .catch(() => {
+                clearInterval(this.refreshTime)
+              })
+            this.refreshLock = false
+          }
+          this.$store.commit('SET_EXPIRES_IN', this.expires_in - 10)
+        }, 10000)
+      },
+      initWebSocket() {
+        this.connection()
+        const self = this
+        // 断开重连机制,尝试发送消息,捕获异常发生时重连
+        this.timer = setInterval(() => {
+          try {
+            self.stompClient.send('test')
+          } catch (err) {
+            console.log('断线了: ' + err)
+            self.connection()
+          }
+        }, 5000)
+      },
+      connection() {
+        const token = store.getters.access_token
+        const TENANT_ID = getStore({name: 'tenantId'}) ? getStore({name: 'tenantId'}) : '1'
+        const headers = {
+          'Authorization': 'Bearer ' + token
         }
-      }, 5000)
-    },
-    connection() {
-      const token = store.getters.access_token
-      const TENANT_ID = getStore({ name: 'tenantId' }) ? getStore({ name: 'tenantId' }) : '1'
-      const headers = {
-        'Authorization': 'Bearer ' + token
-      }
-      // 建立连接对象
-      this.socket = new SockJS('/act/ws')// 连接服务端提供的通信接口,连接以后才可以订阅广播消息和个人消息
-      // 获取STOMP子协议的客户端对象
-      this.stompClient = Stomp.over(this.socket)
-      this.stompClient.debug = null
-      // 向服务器发起websocket连接
-      this.stompClient.connect(headers, () => {
-        this.stompClient.subscribe('/task/' + this.userInfo.username + '-' + TENANT_ID + '/remind', (msg) => { // 订阅服务端提供的某个topic;
-          this.$notify({
-            title: '协同提醒',
-            type: 'warning',
-            dangerouslyUseHTMLString: true,
-            message: msg.body + '任务,请及时处理',
-            offset: 60
+        // 建立连接对象
+        this.socket = new SockJS('/act/ws')// 连接服务端提供的通信接口,连接以后才可以订阅广播消息和个人消息
+        // 获取STOMP子协议的客户端对象
+        this.stompClient = Stomp.over(this.socket)
+        this.stompClient.debug = null
+        // 向服务器发起websocket连接
+        this.stompClient.connect(headers, () => {
+          this.stompClient.subscribe('/task/' + this.userInfo.username + '-' + TENANT_ID + '/remind', (msg) => { // 订阅服务端提供的某个topic;
+            this.$notify({
+              title: '协同提醒',
+              type: 'warning',
+              dangerouslyUseHTMLString: true,
+              message: msg.body + '任务,请及时处理',
+              offset: 60
+            })
           })
-        })
-      }, (err) => {
+        }, (err) => {
 
-      })
-    },
-    disconnect() {
-      if (this.stompClient != null) {
-        this.stompClient.disconnect()
-        console.log('Disconnected')
+        })
+      },
+      disconnect() {
+        if (this.stompClient != null) {
+          this.stompClient.disconnect()
+          console.log('Disconnected')
+        }
       }
     }
   }
-}
 </script>

+ 1 - 1
src/page/index/top/index.vue

@@ -66,7 +66,7 @@
         placement="bottom">
         <div class="top-bar__item">
           <i
-            :class="isFullScren?'icon-tuichuquanping':'icon-quanping'"
+            :class="isFullScren?'icon-zuixiaohua':'icon-quanpingzuidahua'"
             @click="handleScreen"/>
         </div>
       </el-tooltip>

+ 3 - 3
src/page/wel.vue

@@ -4,9 +4,9 @@
       <div class="banner-text">
         <span>
           <a href="https://avue.top/#/pay" target="_blank">
-            <img src="https://img.shields.io/badge/Avue-2.0.4-green.svg" alt="Build Status">
+            <img src="https://img.shields.io/badge/Avue-2.1.0-green.svg" alt="Build Status">
           </a>
-          <img src="https://img.shields.io/badge/Spring%20Boot-2.1.6.RELEASE-yellowgreen.svg" alt="Downloads">
+          <img src="https://img.shields.io/badge/Spring%20Boot-2.1.7.RELEASE-yellowgreen.svg" alt="Downloads">
           <img src="https://img.shields.io/badge/Spring%20Cloud-Greenwich.SR2-blue.svg" alt="Coverage Status">
         </span>
         <br>
@@ -15,7 +15,7 @@
             <el-collapse-item title="完整的微服务架构" name="1">
               <div>基于Spring Cloud Gateway</div>
               <div>基于Spring Cloud Greenwich.SR2</div>
-              <div>基于Spring Boot 2.1.6.RELEASE</div>
+              <div>基于Spring Boot 2.1.7.RELEASE</div>
             </el-collapse-item>
             <el-collapse-item title="完善的权限控制" name="2">
               <div>基于Spring Security OAuth实现鉴权体系;</div>

+ 1 - 1
src/permission.js

@@ -32,7 +32,7 @@ router.beforeEach((to, from, next) => {
     } else {
       if (store.getters.roles.length === 0) {
         store.dispatch('GetUserInfo').then(() => {
-          next({ ...to, replace: true })
+          next()
         }).catch(() => {
           store.dispatch('FedLogOut').then(() => {
             next({ path: '/login' })

+ 7 - 8
src/router/page/index.js

@@ -15,7 +15,7 @@ export default [{
   path: '/lock',
   name: '锁屏页',
   component: () =>
-      import(/* webpackChunkName: "page" */ '@/page/lock/index'),
+    import(/* webpackChunkName: "page" */ '@/page/lock/index'),
   meta: {
     keepAlive: true,
     isTab: false,
@@ -25,7 +25,7 @@ export default [{
 {
   path: '/404',
   component: () =>
-      import(/* webpackChunkName: "page" */ '@/components/error-page/404'),
+    import(/* webpackChunkName: "page" */ '@/components/error-page/404'),
   name: '404',
   meta: {
     keepAlive: true,
@@ -37,7 +37,7 @@ export default [{
 {
   path: '/403',
   component: () =>
-      import(/* webpackChunkName: "page" */ '@/components/error-page/403'),
+    import(/* webpackChunkName: "page" */ '@/components/error-page/403'),
   name: '403',
   meta: {
     keepAlive: true,
@@ -48,7 +48,7 @@ export default [{
 {
   path: '/500',
   component: () =>
-      import(/* webpackChunkName: "page" */ '@/components/error-page/500'),
+    import(/* webpackChunkName: "page" */ '@/components/error-page/500'),
   name: '500',
   meta: {
     keepAlive: true,
@@ -69,7 +69,7 @@ export default [{
     path: ':routerPath',
     name: 'iframe',
     component: () =>
-        import(/* webpackChunkName: "page" */ '@/components/iframe/main'),
+      import(/* webpackChunkName: "page" */ '@/components/iframe/main'),
     props: true
   }]
 },
@@ -81,11 +81,10 @@ export default [{
   path: '/authredirect',
   name: '授权页',
   component: () =>
-      import(/* webpackChunkName: "page" */ '@/page/login/authredirect'),
+    import(/* webpackChunkName: "page" */ '@/page/login/authredirect'),
   meta: {
     keepAlive: true,
     isTab: false,
     isAuth: false
   }
-}
-]
+}]

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

@@ -101,7 +101,7 @@ const user = {
       return new Promise((resolve, reject) => {
         getUserInfo().then((res) => {
           const data = res.data.data || {}
-          commit('SET_USERIFNO', data.sysUser)
+          commit('SET_USER_INFO', data.sysUser)
           commit('SET_ROLES', data.roles || [])
           commit('SET_PERMISSIONS', data.permissions || [])
           resolve(data)
@@ -201,7 +201,7 @@ const user = {
         type: 'session'
       })
     },
-    SET_USERIFNO: (state, userInfo) => {
+    SET_USER_INFO: (state, userInfo) => {
       state.userInfo = userInfo
     },
     SET_MENU: (state, menu) => {

+ 38 - 0
src/util/rule.js

@@ -0,0 +1,38 @@
+/**
+ * @desc  [自定义校验规则]
+ * @example
+ *  import { rule } from "@/util/rule";
+ *  rules: [
+ *     { validator: rule.emailValue, trigger: 'blur'}
+ *  ]
+ *
+ *  可参考: https://gitee.com/log4j/codes/lgfxz09bmt7ea3rdwnocs20
+ */
+
+export const rule = {
+  /**
+   * 校验 请输入中文、英文、数字包括下划线
+   * 名称校验
+   */
+  validatorNameCn(rule, value, callback) {
+    let acount = /^[\u4E00-\u9FA5A-Za-z0-9_]+$/
+    if (value && (!(acount).test(value))) {
+      callback(new Error('请输入中文、英文、数字包括下划线'))
+    } else {
+      callback()
+    }
+  },
+  /**
+   * 校验 请输入英文、数字包括下划线
+   * 名称校验
+   */
+  validatorName(rule, value, callback) {
+    let acount = /^[A-Z_]+$/
+    if (value && (!(acount).test(value))) {
+      callback(new Error('请输入大写英文、下划线'))
+    } else {
+      callback()
+    }
+  },
+  // 校验规则根据不同业务需求,不断拓展补充 ...
+}

+ 89 - 95
src/views/admin/client/index.vue

@@ -35,103 +35,97 @@
 </template>
 
 <script>
-import {
-  addObj,
-  delObj,
-  fetchList,
-  putObj
-} from '@/api/admin/client'
-import { tableOption } from '@/const/crud/admin/client'
-import { mapGetters } from 'vuex'
+    import {addObj, delObj, fetchList, putObj} from '@/api/admin/client'
+    import {tableOption} from '@/const/crud/admin/client'
+    import {mapGetters} from 'vuex'
 
-export default {
-  name: 'Client',
-  data() {
-    return {
-      tableData: [],
-      page: {
-        total: 0, // 总页数
-        currentPage: 1, // 当前页数
-        pageSize: 20 // 每页显示多少条
-      },
-      tableLoading: false,
-      tableOption: tableOption
+    export default {
+        name: 'Client',
+        data() {
+            return {
+                tableData: [],
+                page: {
+                    total: 0, // 总页数
+                    currentPage: 1, // 当前页数
+                    pageSize: 20 // 每页显示多少条
+                },
+                tableLoading: false,
+                tableOption: tableOption
+            }
+        },
+        created() {
+        },
+        mounted: function () {
+        },
+        computed: {
+            ...mapGetters(['permissions']),
+            permissionList() {
+                return {
+                    addBtn: this.vaildData(this.permissions.sys_client_add, false),
+                    delBtn: this.vaildData(this.permissions.sys_client_del, false),
+                    editBtn: this.vaildData(this.permissions.sys_client_edit, false)
+                }
+            }
+        },
+        methods: {
+            getList(page, params) {
+                this.tableLoading = true
+                fetchList(Object.assign({
+                    current: page.currentPage,
+                    size: page.pageSize
+                }, params)).then(response => {
+                    this.tableData = response.data.data.records
+                    this.page.total = response.data.data.total
+                    this.tableLoading = false
+                })
+            },
+            handleDelete: function (row, index) {
+                var _this = this
+                this.$confirm('是否确认删除ID为' + row.clientId, '提示', {
+                    confirmButtonText: '确定',
+                    cancelButtonText: '取消',
+                    type: 'warning'
+                }).then(function () {
+                    return delObj(row.clientId)
+                }).then(() => {
+                    _this.$message.success('删除成功')
+                    this.refreshChange()
+                }).catch(function () {
+                })
+            },
+            handleUpdate: function (row, index, done) {
+                row.authorizedGrantTypes = row.authorizedGrantTypes.join(',')
+                if (row.accessTokenValidity === 0) {
+                    row.accessTokenValidity = 60 * 60 * 12
+                }
+                if (row.refreshTokenValidity === 0) {
+                    row.refreshTokenValidity = 60 * 60 * 24 * 30
+                }
+                putObj(row).then(() => {
+                    this.$message.success('修改成功');
+                    this.refreshChange()
+                    done()
+                })`-`
+            },
+            handleSave: function (row, done) {
+                row.authorizedGrantTypes = row.authorizedGrantTypes.join(',')
+                if (row.accessTokenValidity === 0) {
+                    row.accessTokenValidity = 60 * 60 * 12
+                }
+                if (row.refreshTokenValidity === 0) {
+                    row.refreshTokenValidity = 60 * 60 * 24 * 30
+                }
+                addObj(row).then(() => {
+                    this.$message.success('添加成功');
+                    this.refreshChange()
+                    done()
+                })
+            },
+            refreshChange() {
+                this.getList(this.page)
+            }
+        }
     }
-  },
-  created() {
-  },
-  mounted: function() {
-  },
-  computed: {
-    ...mapGetters(['permissions']),
-    permissionList() {
-      return {
-        addBtn: this.vaildData(this.permissions.sys_client_add, false),
-        delBtn: this.vaildData(this.permissions.sys_client_del, false),
-        editBtn: this.vaildData(this.permissions.sys_client_edit, false)
-      }
-    }
-  },
-  methods: {
-    getList(page, params) {
-      this.tableLoading = true
-      fetchList(Object.assign({
-        current: page.currentPage,
-        size: page.pageSize
-      }, params)).then(response => {
-        this.tableData = response.data.data.records
-        this.page.total = response.data.data.total
-        this.tableLoading = false
-      })
-    },
-    handleDelete: function(row, index) {
-      var _this = this
-      this.$confirm('是否确认删除ID为' + row.clientId, '提示', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'warning'
-      }).then(function() {
-        return delObj(row.clientId)
-      }).then(() => {
-        _this.tableData.splice(index, 1)
-        _this.$message({
-          showClose: true,
-          message: '删除成功',
-          type: 'success'
-        })
-        this.refreshChange()
-      }).catch(function() {
-      })
-    },
-    handleUpdate: function(row, index, done) {
-      putObj(row).then(() => {
-        this.tableData.splice(index, 1, Object.assign({}, row))
-        this.$message({
-          showClose: true,
-          message: '修改成功',
-          type: 'success'
-        })
-        this.refreshChange()
-        done()
-      })
-    },
-    handleSave: function(row, done) {
-      addObj(row).then(() => {
-        this.tableData.push(Object.assign({}, row))
-        this.$message({
-          showClose: true,
-          message: '添加成功',
-          type: 'success'
-        })
-        this.refreshChange()
-        done()
-      })
-    },
-    refreshChange() {
-      this.getList(this.page)
-    }
-  }
-}
 </script>
 
 <style lang="scss" scoped>

+ 1 - 1
src/views/admin/dept/index.vue

@@ -70,7 +70,7 @@
                 prop="parentId">
                 <el-input
                   v-model="form.parentId"
-                  :disabled="formEdit"
+                  disabled
                   placeholder="请输入父级节点"/>
               </el-form-item>
               <el-form-item

+ 4 - 33
src/views/admin/role/index.vue

@@ -248,13 +248,7 @@ export default {
         return delObj(row.roleId)
       }).then(() => {
         this.getList(this.page)
-        this.list.splice(index, 1)
-        _this.$message({
-          showClose: true,
-          message: '删除成功',
-          type: 'success'
-        })
-      }).catch(function() {
+        this.$notify.success('删除成功')
       })
     },
     create(row, done, loading) {
@@ -264,12 +258,7 @@ export default {
       addObj(this.form).then(() => {
         this.getList(this.page)
         done()
-        this.$notify({
-          title: '成功',
-          message: '创建成功',
-          type: 'success',
-          duration: 2000
-        })
+        this.$notify.success('创建成功')
       }).catch(() => {
         loading()
       })
@@ -281,12 +270,7 @@ export default {
       putObj(this.form).then(() => {
         this.getList(this.page)
         done()
-        this.$notify({
-          title: '成功',
-          message: '修改成功',
-          type: 'success',
-          duration: 2000
-        })
+        this.$notify.success('修改成功')
       }).catch(() => {
         loading()
       })
@@ -296,20 +280,7 @@ export default {
       this.menuIds = this.$refs.menuTree.getCheckedKeys().join(',').concat(',').concat(this.$refs.menuTree.getHalfCheckedKeys().join(','))
       permissionUpd(roleId, this.menuIds).then(() => {
         this.dialogPermissionVisible = false
-        fetchMenuTree()
-          .then(response => {
-            this.form = response.data.data
-            return fetchRoleTree(roleId)
-          })
-          .then(response => {
-            this.checkedKeys = response.data.data
-            this.$notify({
-              title: '成功',
-              message: '修改成功',
-              type: 'success',
-              duration: 2000
-            })
-          })
+        this.$notify.success('修改成功')
       })
     }
   }

+ 184 - 177
src/views/admin/user/index.vue

@@ -130,186 +130,193 @@
 </template>
 
 <script>
-import { addObj, delObj, fetchList, putObj } from '@/api/admin/user'
-import { deptRoleList } from '@/api/admin/role'
-import { fetchTree } from '@/api/admin/dept'
-import { tableOption } from '@/const/crud/admin/user'
-import { mapGetters } from 'vuex'
+    import {addObj, delObj, fetchList, putObj} from '@/api/admin/user'
+    import {deptRoleList} from '@/api/admin/role'
+    import {fetchTree} from '@/api/admin/dept'
+    import {tableOption} from '@/const/crud/admin/user'
+    import {mapGetters} from 'vuex'
 
-export default {
-  name: 'SysUser',
-  data() {
-    return {
-      searchForm: {},
-      treeOption: {
-        nodeKey: 'id',
-        addBtn: false,
-        menu: false,
-        props: {
-          label: 'name',
-          value: 'id'
+    export default {
+        name: 'SysUser',
+        data() {
+            return {
+                searchForm: {},
+                treeOption: {
+                    nodeKey: 'id',
+                    addBtn: false,
+                    menu: false,
+                    props: {
+                        label: 'name',
+                        value: 'id'
+                    }
+                },
+                treeData: [],
+                option: tableOption,
+                treeDeptData: [],
+                checkedKeys: [],
+                roleProps: {
+                    label: 'roleName',
+                    value: 'roleId'
+                },
+                defaultProps: {
+                    label: 'name',
+                    value: 'id'
+                },
+                page: {
+                    total: 0, // 总页数
+                    currentPage: 1, // 当前页数
+                    pageSize: 20, // 每页显示多少条,
+                    isAsc: false// 是否倒序
+                },
+                list: [],
+                listLoading: true,
+                role: [],
+                form: {},
+                rolesOptions: []
+            }
+        },
+        computed: {
+            ...mapGetters(['permissions'])
+        },
+        watch: {
+            role() {
+                this.form.role = this.role
+            }
+        },
+        created() {
+            this.sys_user_add = this.permissions['sys_user_add']
+            this.sys_user_edit = this.permissions['sys_user_edit']
+            this.sys_user_del = this.permissions['sys_user_del']
+            this.init()
+        },
+        methods: {
+            init() {
+                fetchTree().then(response => {
+                    this.treeData = response.data.data
+                })
+            },
+            nodeClick(data) {
+                this.page.page = 1
+                this.getList(this.page, {deptId: data.id})
+            },
+            getList(page, params) {
+                this.listLoading = true
+                fetchList(Object.assign({
+                    current: page.currentPage,
+                    size: page.pageSize
+                }, params, this.searchForm)).then(response => {
+                    this.list = response.data.data.records
+                    this.page.total = response.data.data.total
+                    this.listLoading = false
+                })
+            },
+            getNodeData() {
+                deptRoleList().then(response => {
+                    this.rolesOptions = response.data.data
+                })
+            },
+            handleDept() {
+                fetchTree().then(response => {
+                    this.treeDeptData = response.data.data
+                })
+            },
+            handleFilter(param) {
+                this.searchForm = param
+                this.getList(this.page, param)
+            },
+            handleRefreshChange() {
+                this.getList(this.page)
+            },
+            handleCreate() {
+                this.$refs.crud.rowAdd()
+            },
+            handleOpenBefore(show, type) {
+                window.boxType = type
+                this.handleDept()
+                if (['edit', 'views'].includes(type)) {
+                    this.role = []
+                    for (var i = 0; i < this.form.roleList.length; i++) {
+                        this.role[i] = this.form.roleList[i].roleId
+                    }
+                    deptRoleList().then(response => {
+                        this.rolesOptions = response.data.data
+                    })
+                } else if (type === 'add') {
+                    this.role = []
+                }
+                show()
+            },
+            handleUpdate(row, index) {
+                console.log(row)
+                this.$refs.crud.rowEdit(row, index)
+                this.form.password = undefined
+            },
+            create(row, done, loading) {
+                if (this.form.phone.indexOf('*') > 0) {
+                    this.form.phone = undefined
+                }
+                addObj(this.form).then(() => {
+                    this.getList(this.page)
+                    done()
+                    this.$notify({
+                        title: '成功',
+                        message: '创建成功',
+                        type: 'success',
+                        duration: 2000
+                    })
+                }).catch(() => {
+                    loading()
+                })
+            },
+            update(row, index, done, loading) {
+                if (this.form.phone && this.form.phone.indexOf('*') > 0) {
+                    this.form.phone = undefined
+                }
+                putObj(this.form).then(() => {
+                    this.getList(this.page)
+                    done()
+                    this.$notify({
+                        title: '成功',
+                        message: '修改成功',
+                        type: 'success',
+                        duration: 2000
+                    })
+                }).catch(() => {
+                    loading()
+                })
+            },
+            deletes(row, index) {
+                this.$confirm(
+                    '此操作将永久删除该用户(用户名:' + row.username + '), 是否继续?',
+                    '提示',
+                    {
+                        confirmButtonText: '确定',
+                        cancelButtonText: '取消',
+                        type: 'warning'
+                    }
+                ).then(() => {
+                    delObj(row.userId)
+                        .then(() => {
+                            this.list.splice(index, 1)
+                            this.$notify({
+                                title: '成功',
+                                message: '删除成功',
+                                type: 'success',
+                                duration: 2000
+                            })
+                        })
+                        .cache(() => {
+                            this.$notify({
+                                title: '失败',
+                                message: '删除失败',
+                                type: 'error',
+                                duration: 2000
+                            })
+                        })
+                })
+            }
         }
-      },
-      treeData: [],
-      option: tableOption,
-      treeDeptData: [],
-      checkedKeys: [],
-      roleProps: {
-        label: 'roleName',
-        value: 'roleId'
-      },
-      defaultProps: {
-        label: 'name',
-        value: 'id'
-      },
-      page: {
-        total: 0, // 总页数
-        currentPage: 1, // 当前页数
-        pageSize: 20, // 每页显示多少条,
-        isAsc: false// 是否倒序
-      },
-      list: [],
-      listLoading: true,
-      role: [],
-      form: {},
-      rolesOptions: []
     }
-  },
-  computed: {
-    ...mapGetters(['permissions'])
-  },
-  watch: {
-    role() {
-      this.form.role = this.role
-    }
-  },
-  created() {
-    this.sys_user_add = this.permissions['sys_user_add']
-    this.sys_user_edit = this.permissions['sys_user_edit']
-    this.sys_user_del = this.permissions['sys_user_del']
-    this.init()
-  },
-  methods: {
-    init() {
-      fetchTree().then(response => {
-        this.treeData = response.data.data
-      })
-    },
-    nodeClick(data) {
-      this.page.page = 1
-      this.getList(this.page, { deptId: data.id })
-    },
-    getList(page, params) {
-      this.listLoading = true
-      fetchList(Object.assign({
-        current: page.currentPage,
-        size: page.pageSize
-      }, params, this.searchForm)).then(response => {
-        this.list = response.data.data.records
-        this.page.total = response.data.data.total
-        this.listLoading = false
-      })
-    },
-    getNodeData() {
-      deptRoleList().then(response => {
-        this.rolesOptions = response.data.data
-      })
-    },
-    handleDept() {
-      fetchTree().then(response => {
-        this.treeDeptData = response.data.data
-      })
-    },
-    handleFilter(param) {
-      this.searchForm = param
-      this.getList(this.page, param)
-    },
-    handleRefreshChange() {
-      this.getList(this.page)
-    },
-    handleCreate() {
-      this.$refs.crud.rowAdd()
-    },
-    handleOpenBefore(show, type) {
-      window.boxType = type
-      this.handleDept()
-      if (['edit', 'views'].includes(type)) {
-        this.role = []
-        for (var i = 0; i < this.form.roleList.length; i++) {
-          this.role[i] = this.form.roleList[i].roleId
-        }
-        deptRoleList().then(response => {
-          this.rolesOptions = response.data.data
-        })
-      } else if (type === 'add') {
-        this.role = []
-      }
-      show()
-    },
-    handleUpdate(row, index) {
-      this.$refs.crud.rowEdit(row, index)
-      this.form.password = undefined
-    },
-    create(row, done, loading) {
-      addObj(this.form).then(() => {
-        this.getList(this.page)
-        done()
-        this.$notify({
-          title: '成功',
-          message: '创建成功',
-          type: 'success',
-          duration: 2000
-        })
-      }).catch(() => {
-        loading()
-      })
-    },
-    update(row, index, done, loading) {
-      putObj(this.form).then(() => {
-        this.getList(this.page)
-        done()
-        this.$notify({
-          title: '成功',
-          message: '修改成功',
-          type: 'success',
-          duration: 2000
-        })
-      }).catch(() => {
-        loading()
-      })
-    },
-    deletes(row, index) {
-      this.$confirm(
-        '此操作将永久删除该用户(用户名:' + row.username + '), 是否继续?',
-        '提示',
-        {
-          confirmButtonText: '确定',
-          cancelButtonText: '取消',
-          type: 'warning'
-        }
-      ).then(() => {
-        delObj(row.userId)
-          .then(() => {
-            this.list.splice(index, 1)
-            this.$notify({
-              title: '成功',
-              message: '删除成功',
-              type: 'success',
-              duration: 2000
-            })
-          })
-          .cache(() => {
-            this.$notify({
-              title: '失败',
-              message: '删除失败',
-              type: 'error',
-              duration: 2000
-            })
-          })
-      })
-    }
-  }
-}
 </script>
 <style lang="scss">
   .user {

+ 3 - 1
src/views/admin/user/info.vue

@@ -130,6 +130,7 @@
 import { handleImg, openWindow } from '@/util/util'
 import { mapState } from 'vuex'
 import store from '@/store'
+import { getStore } from '@/util/store'
 import request from '@/router/axios'
 
 export default {
@@ -150,7 +151,8 @@ export default {
       avatarUrl: '',
       show: false,
       headers: {
-        Authorization: 'Bearer ' + store.getters.access_token
+        'Authorization': 'Bearer ' + store.getters.access_token,
+        'TENANT-ID': getStore({ name: 'tenantId' })
       },
       ruleForm2: {
         username: '',

+ 41 - 1
src/views/daemon/job-manage/index.vue

@@ -80,6 +80,7 @@
             icon="el-icon-caret-right"
             @click="handleStartJob(scope.row)">启动
           </el-button>
+
           <el-button
             v-if="permissions.job_sys_job_shutdown_job"
             type="text"
@@ -92,6 +93,12 @@
             icon="el-icon-edit"
             @click="handleUpdate(scope.row,scope.index)">修改
           </el-button>
+          <el-button
+            v-if="permissions.job_sys_job_run_job"
+            type="text"
+            icon="el-icon-s-promotion"
+            @click="handleRunJob(scope.row)">执行
+          </el-button>
           <el-button
             v-if="permissions.job_sys_job_del"
             type="text"
@@ -136,7 +143,8 @@ import {
   shutDownJobRa,
   shutdownJobsRa,
   startJobRa,
-  startJobsRa
+  startJobsRa,
+  runJobRa
 } from '@/api/daemon/sys-job'
 import { tableLogOption, tableOption } from '@/const/crud/daemon/sys-job'
 import { remote } from '@/api/admin/dict'
@@ -261,6 +269,38 @@ export default {
         })
       }
     },
+    /**
+     * 执行定时任务
+     */
+    handleRunJob(row) {
+      this.$confirm(
+        '立刻执行一次任务(任务名称:' + row.jobName + '), 是否继续?',
+        '提示',
+        {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }
+      ).then(() => {
+        runJobRa(row.jobId).then(response => {
+          const code = response.data.code
+          if (code === 0) {
+            this.$notify({
+              title: '成功',
+              message: '执行成功',
+              type: 'success'
+            })
+            this.refreshChange()
+          }
+        }).catch(() => {
+          this.$notify.error({
+            title: '错误',
+            message: '执行失败'
+          })
+        })
+      })
+
+    },
     /**
        * 新增定时任务
        */

+ 111 - 0
src/views/gen/datasource.vue

@@ -0,0 +1,111 @@
+<!--
+  -    Copyright (c) 2018-2025, lengleng All rights reserved.
+  -
+  - Redistribution and use in source and binary forms, with or without
+  - modification, are permitted provided that the following conditions are met:
+  -
+  - Redistributions of source code must retain the above copyright notice,
+  - this list of conditions and the following disclaimer.
+  - Redistributions in binary form must reproduce the above copyright
+  - notice, this list of conditions and the following disclaimer in the
+  - documentation and/or other materials provided with the distribution.
+  - Neither the name of the pig4cloud.com developer nor the names of its
+  - contributors may be used to endorse or promote products derived from
+  - this software without specific prior written permission.
+  - Author: lengleng (wangiegie@gmail.com)
+  -->
+
+<template>
+  <div class="execution">
+    <basic-container>
+      <avue-crud
+        ref="data-source-settings-crud"
+        v-model="dsForm"
+        :page="dsPage"
+        :data="tableDsData"
+        :option="tableDsOption"
+        :before-open="handleOpenBefore"
+        @row-update="handleUpdate"
+        @row-save="handleSave"
+        @row-del="rowDel"
+        @refresh-change="refreshDsChange"
+        @on-load="getDsList"/>
+    </basic-container>
+  </div>
+</template>
+
+<script>
+  import {addObj, delObj, fetchDsList, putObj} from '@/api/gen/gen'
+  import {formOption, tableDsOption, tableOption} from '@/const/crud/gen/gen'
+
+  export default {
+    name: 'CodeGenerator',
+    data() {
+      return {
+        dataSourceList: [],
+        tableDsData: [],
+        box: false,
+        dsPage: {
+          total: 0, // 总页数
+          currentPage: 1, // 当前页数
+          pageSize: 20 // 每页显示多少条
+        },
+        dsForm: {},
+        tableLoading: false,
+        tableOption: tableOption,
+        tableDsOption: tableDsOption,
+        formOption: formOption
+      }
+    },
+    created() {
+    },
+    methods: {
+      rowDel: function (row, index) {
+        this.$confirm('是否确认删除ID为' + row.id, '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(function () {
+          return delObj(row.id)
+        }).then(() => {
+          this.$message.success('删除成功')
+          this.getDsList(this.dsPage)
+        })
+      },
+      handleOpenBefore: function (show) {
+        this.dsForm.password = undefined
+        show()
+      },
+      handleUpdate: function (row, index, done) {
+        putObj(row).then(() => {
+          this.$message.success('修改成功')
+          done()
+          this.getDsList(this.dsPage)
+        })
+      },
+      handleSave: function (row, done) {
+        addObj(row).then(() => {
+          this.$message.success('添加成功')
+          done()
+          this.getDsList(this.dsPage)
+        })
+      },
+      getDsList(page, params) {
+        fetchDsList(Object.assign({
+          current: page.currentPage,
+          size: page.pageSize
+        }, params)).then(response => {
+          this.tableDsData = response.data.data.records
+          this.dsPage.total = response.data.data.total
+        })
+      },
+      refreshDsChange() {
+        this.getDsList(this.dsPage)
+      }
+    }
+  }
+</script>
+
+<style lang="scss" scoped>
+</style>
+

+ 68 - 0
src/views/gen/design.vue

@@ -0,0 +1,68 @@
+<template>
+  <div class="webapp">
+    <basic-container>
+      <avue-form-design :option="option"
+                        @submit="handleSubmit">
+      </avue-form-design>
+    </basic-container>
+  </div>
+</template>
+
+
+<script>
+    import {getForm, postForm} from '@/api/gen/gen'
+    import {validatenull} from "../../util/validate";
+
+    export default {
+        data() {
+            return {
+                box: true,
+                option: {
+                    column: []
+                }
+            }
+        },
+        created() {
+            this.getFormInfo()
+        },
+        methods: {
+            handleSubmit(json) {
+                let params = this.$route.query;
+                if (validatenull(params)) {
+                    return false
+                }
+                let result = JSON.stringify(json)
+                postForm(result, params.tableName, params.dsId).then(response => {
+                    this.$message.success('生成并保存成功')
+                })
+            },
+            getFormInfo() {
+                let params = this.$route.query;
+                if (validatenull(params)) {
+                    return false
+                }
+                getForm(params.tableName, params.dsId).then(response => {
+                    if (!validatenull(response.data.data)) {
+                        this.option = JSON.parse(response.data.data)
+                    }
+                })
+            }
+        }
+    }
+</script>
+<style lang="scss">
+  .webapp {
+    background-color: #fff;
+    position: relative;
+    width: 100%;
+    height: 100%;
+
+    .form-designer {
+      height: 800px;
+    }
+
+    .form-designer .widget-config-container .el-tabs__header {
+      position: relative;
+    }
+  }
+</style>

+ 138 - 0
src/views/gen/form.vue

@@ -0,0 +1,138 @@
+<!--
+  -    Copyright (c) 2018-2025, lengleng All rights reserved.
+  -
+  - Redistribution and use in source and binary forms, with or without
+  - modification, are permitted provided that the following conditions are met:
+  -
+  - Redistributions of source code must retain the above copyright notice,
+  - this list of conditions and the following disclaimer.
+  - Redistributions in binary form must reproduce the above copyright
+  - notice, this list of conditions and the following disclaimer in the
+  - documentation and/or other materials provided with the distribution.
+  - Neither the name of the pig4cloud.com developer nor the names of its
+  - contributors may be used to endorse or promote products derived from
+  - this software without specific prior written permission.
+  - Author: lengleng (wangiegie@gmail.com)
+  -->
+<template>
+  <div class="execution">
+    <basic-container>
+      <avue-crud ref="crud"
+                 :page="page"
+                 :data="tableData"
+                 :permission="permissionList"
+                 :table-loading="tableLoading"
+                 :option="tableOption"
+                 @on-load="getList"
+                 @search-change="searchChange"
+                 @refresh-change="refreshChange"
+                 @row-update="handleUpdate"
+                 @row-save="handleSave"
+                 @row-del="rowDel">
+      </avue-crud>
+    </basic-container>
+  </div>
+</template>
+
+<script>
+  import {addObj, delObj, fetchList, putObj} from '@/api/gen/form'
+  import {tableOption} from '@/const/crud/gen/form'
+  import {mapGetters} from 'vuex'
+
+  export default {
+    name: 'genForm',
+    data() {
+      return {
+        searchForm: {},
+        tableData: [],
+        page: {
+          total: 0, // 总页数
+          currentPage: 1, // 当前页数
+          pageSize: 20 // 每页显示多少条
+        },
+        tableLoading: false,
+        tableOption: tableOption
+      }
+    },
+    computed: {
+      ...mapGetters(['permissions']),
+      permissionList() {
+        return {
+          addBtn: this.vaildData(this.permissions.gen_form_add, false),
+          delBtn: this.vaildData(this.permissions.gen_form_del, false),
+          editBtn: this.vaildData(this.permissions.gen_form_edit, false)
+        };
+      }
+    },
+    methods: {
+      getList(page, params) {
+        this.tableLoading = true
+        fetchList(Object.assign({
+          descs: 'create_time',
+          current: page.currentPage,
+          size: page.pageSize
+        }, params, this.searchForm)).then(response => {
+          this.tableData = response.data.data.records
+          this.page.total = response.data.data.total
+          this.tableLoading = false
+        }).catch(() => {
+          this.tableLoading = false
+        })
+      },
+      rowDel: function (row, index) {
+        var _this = this
+        this.$confirm('是否确认删除ID为' + row.id, '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }).then(function () {
+          return delObj(row.id)
+        }).then(data => {
+          _this.tableData.splice(index, 1)
+          _this.$message({
+            showClose: true,
+            message: '删除成功',
+            type: 'success'
+          })
+          this.getList(this.page)
+        })
+      },
+      handleUpdate: function (row, index, done, loading) {
+        putObj(row).then(data => {
+          this.$message({
+            showClose: true,
+            message: '修改成功',
+            type: 'success'
+          })
+          done()
+          this.getList(this.page)
+        }).catch(() => {
+          loading();
+        });
+      },
+      handleSave: function (row, done, loading) {
+        addObj(row).then(data => {
+          this.$message({
+            showClose: true,
+            message: '添加成功',
+            type: 'success'
+          })
+          done()
+          this.getList(this.page)
+        }).catch(() => {
+          loading();
+        });
+      },
+      searchChange(form) {
+        this.searchForm = form
+        this.getList(this.page, form)
+      },
+      refreshChange() {
+        this.getList(this.page)
+      }
+    }
+  }
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 102 - 135
src/views/gen/index.vue

@@ -21,7 +21,7 @@
       <el-row :gutter="20">
         <el-col :span="4">
           <div class="grid-content bg-purple">
-            <el-select v-model="q.id" placeholder="请选择数据源">
+            <el-select v-model="q.id" placeholder="请选择数据源" @change="search">
               <el-option
                 v-for="item in dataSourceList"
                 :key="item.id"
@@ -35,11 +35,10 @@
             <el-input v-model="q.tableName" placeholder="表名称"/>
           </div>
         </el-col>
-        <el-col :span="6">
+        <el-col :span="12">
           <div class="grid-content bg-purple">
             <el-button type="primary" icon="el-icon-search" @click="search">搜索</el-button>
-            <el-button type="primary" icon="el-icon-setting" @click="setting" @close="dsBox=false">维护
-            </el-button>
+            <el-button type="primary" icon="el-icon-download" @click="openBatch">批量生成</el-button>
           </div>
         </el-col>
       </el-row>
@@ -59,6 +58,11 @@
             icon="el-icon-check"
             @click="handleDown(scope.row,scope.index)">生成
           </el-button>
+          <el-button
+            type="text"
+            icon="icon-sheji"
+            @click="handleDesign(scope.row,scope.index)">设计
+          </el-button>
         </template>
       </avue-crud>
 
@@ -72,28 +76,21 @@
             ref="formData"
             :option="formOption"
             v-model="formData"
-            @submit="gen()"/>
+            @submit="gen"/>
         </div>
       </el-dialog>
-
       <el-dialog
-        :visible.sync="dsBox"
-        :table-loading="tableLoading"
-        title="数据源管理"
-        width="90%"
-        @close="dsBox=false">
-        <avue-crud
-          ref="data-source-settings-crud"
-          v-model="dsForm"
-          :page="dsPage"
-          :data="tableDsData"
-          :option="tableDsOption"
-          :before-open="handleOpenBefore"
-          @row-update="handleUpdate"
-          @row-save="handleSave"
-          @row-del="rowDel"
-          @refresh-change="refreshDsChange"
-          @on-load="getDsList"/>
+        :visible.sync="boxBatch"
+        title="批量生成"
+        width="50%"
+        lock-scroll>
+        <div class="pull-auto">
+          <avue-form
+            ref="formBatchData"
+            :option="formBatchOption"
+            v-model="formBatchData"
+            @submit="batchGen"/>
+        </div>
       </el-dialog>
 
     </basic-container>
@@ -101,124 +98,94 @@
 </template>
 
 <script>
-import { addObj, delObj, fetchDsList, fetchList, fetchSelectDsList, handleDown, putObj } from '@/api/gen/gen'
-import { formOption, tableDsOption, tableOption } from '@/const/crud/gen/gen'
+  import {fetchList, fetchSelectDsList, handleDown} from '@/api/gen/gen'
+  import {formBatchOption, formOption, tableOption} from '@/const/crud/gen/gen'
 
-export default {
-  name: 'CodeGenerator',
-  data() {
-    return {
-      dsBox: false,
-      q: {},
-      dataSourceList: [],
-      tableData: [],
-      tableDsData: [],
-      formData: {},
-      box: false,
-      page: {
-        total: 0, // 总页数
-        currentPage: 1, // 当前页数
-        pageSize: 20 // 每页显示多少条
-      },
-      dsPage: {
-        total: 0, // 总页数
-        currentPage: 1, // 当前页数
-        pageSize: 20 // 每页显示多少条
-      },
-      dsForm: {},
-      tableLoading: false,
-      tableOption: tableOption,
-      tableDsOption: tableDsOption,
-      formOption: formOption
-    }
-  },
-  created() {
-    this.getdataSourceList()
-  },
-  methods: {
-    getList(page) {
-      this.tableLoading = true
-      fetchList(Object.assign({
-        current: page.currentPage,
-        size: page.pageSize
-      }, this.q)).then(response => {
-        this.tableData = response.data.data.records
-        this.page.total = response.data.data.total
-        this.tableLoading = false
-      })
-    },
-    rowDel: function(row, index) {
-      this.$confirm('是否确认删除ID为' + row.id, '提示', {
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        type: 'warning'
-      }).then(function() {
-        return delObj(row.id)
-      }).then(() => {
-        this.tableData.splice(index, 1)
-        this.$message.success('删除成功')
-        this.getDsList(this.page)
-      }).catch(function() {
-      })
-    },
-    handleOpenBefore: function(show) {
-      this.dsForm.password = undefined
-      show()
-    },
-    handleUpdate: function(row, index, done) {
-      putObj(row).then(() => {
-        this.tableData.splice(index, 1, Object.assign({}, row))
-        this.$message.success('修改成功')
-        done()
-        this.getDsList(this.page)
-      })
+  export default {
+    name: 'CodeGenerator',
+    data() {
+      return {
+        q: {},
+        dataSourceList: [],
+        tableData: [],
+        formData: {},
+        formBatchData: {},
+        box: false,
+        boxBatch: false,
+        page: {
+          total: 0, // 总页数
+          currentPage: 1, // 当前页数
+          pageSize: 20 // 每页显示多少条
+        },
+        tableLoading: false,
+        tableOption: tableOption,
+        formOption: formOption,
+        formBatchOption: formBatchOption
+      }
     },
-    handleSave: function(row, done) {
-      addObj(row).then(() => {
-        this.tableData.push(Object.assign({}, row))
-        this.$message.success('添加成功')
-        done()
-        this.getDsList(this.page)
-      })
+    created() {
+      this.getdataSourceList()
     },
-    getDsList(page, params) {
-      fetchDsList(Object.assign({
-        current: page.currentPage,
-        size: page.pageSize
-      }, params)).then(response => {
-        this.tableDsData = response.data.data.records
-        this.dsPage.total = response.data.data.total
-      })
-    },
-    handleDown: function(row) {
-      this.formData.tableName = row.tableName
-      this.box = true
-    },
-    refreshChange() {
-      this.getList(this.page)
-    },
-    refreshDsChange() {
-      this.getDsList(this.page)
-    },
-    gen() {
-      this.formData.id = this.q.id
-      handleDown(this.formData).then(() => {
+    methods: {
+      getList(page) {
+        this.tableLoading = true
+        fetchList(Object.assign({
+          current: page.currentPage,
+          size: page.pageSize
+        }, this.q)).then(response => {
+          this.tableData = response.data.data.records
+          this.page.total = response.data.data.total
+          this.tableLoading = false
+        })
+      },
+      handleDesign: function (row) {
+        this.$router.push({path: '/gen/design', query: {tableName: row.tableName, dsId: this.q.id}})
+      },
+      handleDown: function (row) {
+        this.formData.tableName = row.tableName
         this.box = true
-      })
-    },
-    setting() {
-      this.dsBox = true
-    },
-    search() {
-      this.getList(this.page)
-    },
-    getdataSourceList() {
-      fetchSelectDsList().then(response => {
-        this.dataSourceList = response.data.data
-      })
+      },
+      refreshChange() {
+        this.getList(this.page)
+      },
+      gen(form,done) {
+        this.formData.id = this.q.id
+        handleDown(this.formData).then(() => {
+          done()
+          this.box = false
+        }).catch(()=>{
+            done()
+        })
+      },
+      getdataSourceList() {
+        fetchSelectDsList().then(response => {
+          this.dataSourceList = response.data.data
+        })
+      },
+      search() {
+        this.getList(this.page)
+      },
+      openBatch() {
+        if (this.$refs.crud.tableSelect.length <= 1 || this.$refs.crud.tableSelect.length > 10) {
+          this.$message.error('选中表数量不合法,数量最多10个')
+          return false
+        }
+        let tableName = []
+        for (const table of this.$refs.crud.tableSelect) {
+          tableName.push(table.tableName)
+        }
+        this.formBatchData.tableName = tableName.join('-')
+        this.boxBatch = true
+      },
+      batchGen(form,done) {
+        this.formBatchData.id = this.q.id
+        handleDown(this.formBatchData).then(() => {
+          done()
+          this.boxBatch = false
+        })
+      }
     }
   }
-}
 </script>
 
 <style lang="scss" scoped>

+ 4 - 4
src/views/mp/wxaccountfans/index.vue

@@ -17,13 +17,13 @@
 <template>
   <div class="execution">
     <basic-container>
-      <el-row :gutter="20">
-        <el-col :span="6">
+      <el-row :gutter="12">
+        <el-col :span="4">
           <div class="grid-content bg-purple">
             <el-input v-model="q.nickname" placeholder="请输入昵称"/>
           </div>
         </el-col>
-        <el-col :span="6">
+        <el-col :span="4">
           <div class="grid-content bg-purple">
             <el-select v-model="q.account" placeholder="请选择公众号">
               <el-option
@@ -34,7 +34,7 @@
             </el-select>
           </div>
         </el-col>
-        <el-col :span="6">
+        <el-col :span="4">
           <div class="grid-content bg-purple">
             <el-button type="primary" icon="el-icon-search" @click="search">搜索</el-button>
             <el-button type="primary" icon="el-icon-sort" @click="asyncFans">同步</el-button>