projects/mesxc-zjl #279
							
								
								
									
										2
									
								
								.env.dev
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								.env.dev
									
									
									
									
									
								
							@@ -25,7 +25,7 @@ VUE_APP_BASE_API = 'http://192.168.0.33:48082'
 | 
			
		||||
# VUE_APP_BASE_API = 'http://192.168.1.78:48082'
 | 
			
		||||
# VUE_APP_BASE_API = 'http://192.168.1.47:48082'
 | 
			
		||||
# socket地址
 | 
			
		||||
VUE_APP_Socket_API = 'ws://192.168.0.33:48082'
 | 
			
		||||
VUE_APP_Socket_API = 'ws://10.70.2.2:8080'
 | 
			
		||||
VUE_APP_Socket_Dcs_API = 'ws://10.70.180.10:8081'
 | 
			
		||||
 | 
			
		||||
# 积木报表指向地址
 | 
			
		||||
 
 | 
			
		||||
@@ -75,42 +75,19 @@ export const constantRoutes = [
 | 
			
		||||
    hidden: true,
 | 
			
		||||
    meta: { requireToken: true }
 | 
			
		||||
  },
 | 
			
		||||
  // {
 | 
			
		||||
  //   path: '/',
 | 
			
		||||
  //   component: Layout,
 | 
			
		||||
  //   // redirect: 'core/base/factory',
 | 
			
		||||
  //   // children: [{
 | 
			
		||||
  //   //   path: 'index',
 | 
			
		||||
  //   //   redirect: 'core/base/factory',
 | 
			
		||||
  //   //   component: (resolve) => require(['@/views/index'], resolve),
 | 
			
		||||
  //   //   name: '首页',
 | 
			
		||||
  //   //   meta: { title: '首页', icon: 'dashboard', affix: true }
 | 
			
		||||
  //   // }
 | 
			
		||||
  //   // ]
 | 
			
		||||
  // },
 | 
			
		||||
  {
 | 
			
		||||
    path: '/AGVBoard',
 | 
			
		||||
    name: 'AGVBoard',
 | 
			
		||||
    // component: Layout,
 | 
			
		||||
    // route level code-splitting
 | 
			
		||||
    // this generates a separate chunk (about.[hash].js) for this route
 | 
			
		||||
    // which is lazy-loaded when the route is visited.
 | 
			
		||||
    component: () => import(/* webpackChunkName: "about" */ '@/views/OperationalOverview/AGVBoard.vue')
 | 
			
		||||
  },
 | 
			
		||||
    {
 | 
			
		||||
  {
 | 
			
		||||
    path: '/coldBoard',
 | 
			
		||||
    name: 'coldBoard',
 | 
			
		||||
    // route level code-splitting
 | 
			
		||||
    // this generates a separate chunk (about.[hash].js) for this route
 | 
			
		||||
    // which is lazy-loaded when the route is visited.
 | 
			
		||||
    component: () => import(/* webpackChunkName: "about" */ '@/views/OperationalOverview/coldBoard.vue')
 | 
			
		||||
  },
 | 
			
		||||
     {
 | 
			
		||||
  {
 | 
			
		||||
    path: '/processingBoard',
 | 
			
		||||
    name: 'processingBoard',
 | 
			
		||||
    // route level code-splitting
 | 
			
		||||
    // this generates a separate chunk (about.[hash].js) for this route
 | 
			
		||||
    // which is lazy-loaded when the route is visited.
 | 
			
		||||
    component: () => import(/* webpackChunkName: "about" */ '@/views/OperationalOverview/processingBoard.vue')
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
@@ -141,138 +118,6 @@ export const constantRoutes = [
 | 
			
		||||
      meta: { title: '字典数据', icon: '', activeMenu: '/system/dict' }
 | 
			
		||||
    }
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: '/job',
 | 
			
		||||
    component: Layout,
 | 
			
		||||
    hidden: true,
 | 
			
		||||
    children: [{
 | 
			
		||||
      path: 'log',
 | 
			
		||||
      component: (resolve) => require(['@/views/infra/job/log'], resolve),
 | 
			
		||||
      name: 'InfraJobLog',
 | 
			
		||||
      meta: { title: '调度日志', activeMenu: '/infra/job' }
 | 
			
		||||
    }
 | 
			
		||||
    ]
 | 
			
		||||
  }, {
 | 
			
		||||
    path: '/codegen',
 | 
			
		||||
    component: Layout,
 | 
			
		||||
    hidden: true,
 | 
			
		||||
    children: [{
 | 
			
		||||
      path: 'edit/:tableId(\\d+)',
 | 
			
		||||
      component: (resolve) => require(['@/views/infra/codegen/editTable'], resolve),
 | 
			
		||||
      name: 'InfraCodegenEditTable',
 | 
			
		||||
      meta: { title: '修改生成配置', activeMenu: '/infra/codegen' }
 | 
			
		||||
    }
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: '/bpm',
 | 
			
		||||
    component: Layout,
 | 
			
		||||
    hidden: true,
 | 
			
		||||
    redirect: 'noredirect',
 | 
			
		||||
    children: [{
 | 
			
		||||
      path: 'oa/leave/create',
 | 
			
		||||
      component: (resolve) => require(['@/views/bpm/oa/leave/create'], resolve),
 | 
			
		||||
      name: 'BpmOALeaveCreate',
 | 
			
		||||
      meta: { title: '发起 OA 请假', icon: 'form', activeMenu: '/bpm/oa/leave' }
 | 
			
		||||
    }, {
 | 
			
		||||
      path: 'oa/leave/detail',
 | 
			
		||||
      component: (resolve) => require(['@/views/bpm/oa/leave/detail'], resolve),
 | 
			
		||||
      name: 'BpmOALeaveDetail',
 | 
			
		||||
      meta: { title: '查看 OA 请假', icon: 'view', activeMenu: '/bpm/oa/leave' }
 | 
			
		||||
    }
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: '/bpm',
 | 
			
		||||
    component: Layout,
 | 
			
		||||
    hidden: true,
 | 
			
		||||
    children: [{
 | 
			
		||||
      path: 'manager/form/edit',
 | 
			
		||||
      component: (resolve) => require(['@/views/bpm/form/formEditor'], resolve),
 | 
			
		||||
      name: 'BpmFormEditor',
 | 
			
		||||
      meta: { title: '流程表单-编辑', activeMenu: '/bpm/manager/form' }
 | 
			
		||||
    }, {
 | 
			
		||||
      path: 'manager/definition',
 | 
			
		||||
      component: (resolve) => require(['@/views/bpm/definition/index'], resolve),
 | 
			
		||||
      name: 'BpmProcessDefinition',
 | 
			
		||||
      meta: { title: '流程定义', activeMenu: '/bpm/manager/model' }
 | 
			
		||||
    }, {
 | 
			
		||||
      path: 'manager/model/design',
 | 
			
		||||
      component: (resolve) => require(['@/views/bpm/model/modelEditor'], resolve),
 | 
			
		||||
      name: 'BpmModelEditor',
 | 
			
		||||
      meta: { title: '设计流程', activeMenu: '/bpm/manager/model' }
 | 
			
		||||
    }, {
 | 
			
		||||
      path: 'process-instance/create',
 | 
			
		||||
      component: (resolve) => require(['@/views/bpm/processInstance/create'], resolve),
 | 
			
		||||
      name: 'BpmProcessInstanceCreate',
 | 
			
		||||
      meta: { title: '发起流程', activeMenu: '/bpm/task/my' }
 | 
			
		||||
    }, {
 | 
			
		||||
      path: 'process-instance/detail',
 | 
			
		||||
      component: (resolve) => require(['@/views/bpm/processInstance/detail'], resolve),
 | 
			
		||||
      name: 'BpmProcessInstanceDetail',
 | 
			
		||||
      meta: { title: '流程详情', activeMenu: '/bpm/task/my' }
 | 
			
		||||
    }
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: '/property',
 | 
			
		||||
    component: Layout,
 | 
			
		||||
    hidden: true,
 | 
			
		||||
    children: [{
 | 
			
		||||
      path: 'value/:propertyId(\\d+)',
 | 
			
		||||
      component: (resolve) => require(['@/views/mall/product/property/value'], resolve),
 | 
			
		||||
      name: 'ProductPropertyValue',
 | 
			
		||||
      meta: { title: '商品属性值', icon: '', activeMenu: '/product/property' }
 | 
			
		||||
    }
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: '/spu',
 | 
			
		||||
    component: Layout,
 | 
			
		||||
    hidden: true,
 | 
			
		||||
    children: [{
 | 
			
		||||
      path: 'edit/:spuId(\\d+)',
 | 
			
		||||
      component: (resolve) => require(['@/views/mall/product/spu/save'], resolve),
 | 
			
		||||
      name: 'ProductSpuUpdate',
 | 
			
		||||
      meta: { title: '修改商品', activeMenu: '/product/spu' }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      path: 'add',
 | 
			
		||||
      component: (resolve) => require(['@/views/mall/product/spu/save'], resolve),
 | 
			
		||||
      name: 'ProductSpuCreate',
 | 
			
		||||
      meta: { title: '添加商品', activeMenu: '/product/spu' }
 | 
			
		||||
    }
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: '/trade/order',
 | 
			
		||||
    component: Layout,
 | 
			
		||||
    hidden: true,
 | 
			
		||||
    children: [
 | 
			
		||||
      {
 | 
			
		||||
        path: 'detail',
 | 
			
		||||
        name: 'TradeOrderDetail',
 | 
			
		||||
        hidden: true,
 | 
			
		||||
        meta: { title: '订单详情' },
 | 
			
		||||
        component: (resolve) => require(['@/views/mall/trade/order/detail'], resolve)
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: '/pay',
 | 
			
		||||
    component: Layout,
 | 
			
		||||
    hidden: true,
 | 
			
		||||
    children: [{
 | 
			
		||||
      path: 'order/submit',
 | 
			
		||||
      name: 'PayOrderSubmit',
 | 
			
		||||
      hidden: true,
 | 
			
		||||
      meta: {
 | 
			
		||||
        title: '收银台',
 | 
			
		||||
        noCache: true
 | 
			
		||||
      },
 | 
			
		||||
      component: (resolve) => require(['@/views/pay/order/submit'], resolve)
 | 
			
		||||
    }]
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,174 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="定义编号" align="center" prop="id" width="400" />
 | 
			
		||||
      <el-table-column label="定义名称" align="center" prop="name" width="100">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button type="text" @click="handleBpmnDetail(scope.row)">
 | 
			
		||||
            <span>{{ scope.row.name }}</span>
 | 
			
		||||
          </el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="定义分类" align="center" prop="category" width="100">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.BPM_MODEL_CATEGORY" :value="scope.row.category" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="表单信息" align="center" prop="formType" width="200">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button v-if="scope.row.formId" type="text" @click="handleFormDetail(scope.row)">
 | 
			
		||||
            <span>{{ scope.row.formName }}</span>
 | 
			
		||||
          </el-button>
 | 
			
		||||
          <el-button v-else-if="scope.row.formCustomCreatePath" type="text" @click="handleFormDetail(scope.row)">
 | 
			
		||||
            <span>{{ scope.row.formCustomCreatePath }}</span>
 | 
			
		||||
          </el-button>
 | 
			
		||||
          <label v-else>暂无表单</label>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="流程版本" align="center" prop="processDefinition.version" width="80">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-tag size="medium" v-if="scope.row">v{{ scope.row.version }}</el-tag>
 | 
			
		||||
          <el-tag size="medium" type="warning" v-else>未部署</el-tag>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="状态" align="center" prop="version" width="80">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
            <el-tag type="success" v-if="scope.row.suspensionState === 1">激活</el-tag>
 | 
			
		||||
            <el-tag type="warning" v-if="scope.row.suspensionState === 2">挂起</el-tag>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="部署时间" align="center" prop="deploymentTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.deploymentTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="定义描述" align="center" prop="description" width="300" show-overflow-tooltip />
 | 
			
		||||
      <el-table-column label="操作" align="center" width="150" fixed="right">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-s-custom" @click="handleAssignRule(scope.row)"
 | 
			
		||||
                     v-hasPermi="['bpm:task-assign-rule:update']">分配规则</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
 | 
			
		||||
    <!-- 流程表单配置详情 -->
 | 
			
		||||
    <el-dialog title="表单详情" :visible.sync="detailOpen" width="50%" append-to-body>
 | 
			
		||||
      <parser :key="new Date().getTime()" :form-conf="detailForm" />
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
 | 
			
		||||
    <!-- 流程模型图的预览 -->
 | 
			
		||||
    <el-dialog title="流程图" :visible.sync="showBpmnOpen" width="80%" append-to-body>
 | 
			
		||||
      <my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" />
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- ========== 流程任务分配规则 ========== -->
 | 
			
		||||
    <taskAssignRuleDialog ref="taskAssignRuleDialog" />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {getProcessDefinitionBpmnXML, getProcessDefinitionPage} from "@/api/bpm/definition";
 | 
			
		||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
 | 
			
		||||
import {decodeFields} from "@/utils/formGenerator";
 | 
			
		||||
import Parser from '@/components/parser/Parser'
 | 
			
		||||
import taskAssignRuleDialog from "../taskAssignRule/taskAssignRuleDialog";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "BpmProcessDefinition",
 | 
			
		||||
  components: {
 | 
			
		||||
    Parser,
 | 
			
		||||
    taskAssignRuleDialog
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 表格数据
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      // 流程表单详情
 | 
			
		||||
      detailOpen: false,
 | 
			
		||||
      detailForm: {
 | 
			
		||||
        fields: []
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      // BPMN 数据
 | 
			
		||||
      showBpmnOpen: false,
 | 
			
		||||
      bpmnXML: null,
 | 
			
		||||
      bpmnControlForm: {
 | 
			
		||||
        prefix: "flowable"
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      // 数据字典
 | 
			
		||||
      categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY),
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    const key = this.$route.query && this.$route.query.key
 | 
			
		||||
    if (key) {
 | 
			
		||||
      this.queryParams['key'] = key
 | 
			
		||||
    }
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询流程定义列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      getProcessDefinitionPage(this.queryParams).then(response => {
 | 
			
		||||
          this.list = response.data.list;
 | 
			
		||||
          this.total = response.data.total;
 | 
			
		||||
          this.loading = false;
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
    },
 | 
			
		||||
    /** 流程表单的详情按钮操作 */
 | 
			
		||||
    handleFormDetail(row) {
 | 
			
		||||
      // 流程表单
 | 
			
		||||
      if (row.formId) {
 | 
			
		||||
        // 设置值
 | 
			
		||||
        this.detailForm = {
 | 
			
		||||
          ...JSON.parse(row.formConf),
 | 
			
		||||
          fields: decodeFields(row.formFields)
 | 
			
		||||
        }
 | 
			
		||||
        // 弹窗打开
 | 
			
		||||
        this.detailOpen = true
 | 
			
		||||
        // 业务表单
 | 
			
		||||
      } else if (row.formCustomCreatePath) {
 | 
			
		||||
        this.$router.push({ path: row.formCustomCreatePath});
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    /** 流程图的详情按钮操作 */
 | 
			
		||||
    handleBpmnDetail(row) {
 | 
			
		||||
      getProcessDefinitionBpmnXML(row.id).then(response => {
 | 
			
		||||
        this.bpmnXML = response.data
 | 
			
		||||
        // 弹窗打开
 | 
			
		||||
        this.showBpmnOpen = true
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    /** 处理任务分配规则列表的按钮操作 */
 | 
			
		||||
    handleAssignRule(row) {
 | 
			
		||||
      this.$refs['taskAssignRuleDialog'].initProcessDefinition(row.id);
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
.my-process-designer {
 | 
			
		||||
  height: calc(100vh - 200px);
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,567 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="container">
 | 
			
		||||
    <div class="left-board">
 | 
			
		||||
      <div class="logo-wrapper">
 | 
			
		||||
        <div class="logo">流程表单</div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <el-scrollbar class="left-scrollbar">
 | 
			
		||||
        <!-- 左边:表单项 -->
 | 
			
		||||
        <div class="components-list">
 | 
			
		||||
          <div v-for="(item, listIndex) in leftComponents" :key="listIndex">
 | 
			
		||||
            <div class="components-title">
 | 
			
		||||
              <svg-icon icon-class="component" />
 | 
			
		||||
              {{ item.title }}
 | 
			
		||||
            </div>
 | 
			
		||||
            <draggable
 | 
			
		||||
              class="components-draggable"
 | 
			
		||||
              :list="item.list"
 | 
			
		||||
              :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
 | 
			
		||||
              :clone="cloneComponent"
 | 
			
		||||
              draggable=".components-item"
 | 
			
		||||
              :sort="false"
 | 
			
		||||
              @end="onEnd"
 | 
			
		||||
            >
 | 
			
		||||
              <div
 | 
			
		||||
                v-for="(element, index) in item.list"
 | 
			
		||||
                :key="index"
 | 
			
		||||
                class="components-item"
 | 
			
		||||
                @click="addComponent(element)"
 | 
			
		||||
              >
 | 
			
		||||
                <div class="components-body">
 | 
			
		||||
                  <svg-icon :icon-class="element.__config__.tagIcon" />
 | 
			
		||||
                  {{ element.__config__.label }}
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
            </draggable>
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          <!-- 左边:动态表单 -->
 | 
			
		||||
          <el-form ref="form" :model="form" :rules="rules" label-width="80px">
 | 
			
		||||
            <el-form-item label="表单名" prop="name">
 | 
			
		||||
              <el-input v-model="form.name" placeholder="请输入表单名" />
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="开启状态" prop="status">
 | 
			
		||||
              <el-radio-group v-model="form.status">
 | 
			
		||||
                <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
 | 
			
		||||
                          :key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
 | 
			
		||||
              </el-radio-group>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="备注" prop="remark">
 | 
			
		||||
              <el-input type="textarea" v-model="form.remark" placeholder="请输入备注" />
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
          </el-form>
 | 
			
		||||
        </div>
 | 
			
		||||
      </el-scrollbar>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="center-board">
 | 
			
		||||
      <div class="action-bar">
 | 
			
		||||
        <el-button icon="el-icon-check" type="text" @click="save">保存</el-button>
 | 
			
		||||
        <!--        <el-button icon="el-icon-video-play" type="text" @click="run">-->
 | 
			
		||||
<!--          运行-->
 | 
			
		||||
<!--        </el-button>-->
 | 
			
		||||
        <el-button icon="el-icon-view" type="text" @click="showJson">
 | 
			
		||||
          查看json
 | 
			
		||||
        </el-button>
 | 
			
		||||
<!--        <el-button icon="el-icon-download" type="text" @click="download">-->
 | 
			
		||||
<!--          导出vue文件-->
 | 
			
		||||
<!--        </el-button>-->
 | 
			
		||||
<!--        <el-button class="copy-btn-main" icon="el-icon-document-copy" type="text" @click="copy">-->
 | 
			
		||||
<!--          复制代码-->
 | 
			
		||||
<!--        </el-button>-->
 | 
			
		||||
        <el-button class="delete-btn" icon="el-icon-delete" type="text" @click="empty">
 | 
			
		||||
          清空
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <!-- 中间,表单项 -->
 | 
			
		||||
      <el-scrollbar class="center-scrollbar">
 | 
			
		||||
        <el-row class="center-board-row" :gutter="formConf.gutter">
 | 
			
		||||
          <el-form
 | 
			
		||||
            :size="formConf.size"
 | 
			
		||||
            :label-position="formConf.labelPosition"
 | 
			
		||||
            :disabled="formConf.disabled"
 | 
			
		||||
            :label-width="formConf.labelWidth + 'px'"
 | 
			
		||||
          >
 | 
			
		||||
            <draggable class="drawing-board" :list="drawingList" :animation="340" group="componentsGroup">
 | 
			
		||||
              <draggable-item
 | 
			
		||||
                v-for="(item, index) in drawingList"
 | 
			
		||||
                :key="item.renderKey"
 | 
			
		||||
                :drawing-list="drawingList"
 | 
			
		||||
                :current-item="item"
 | 
			
		||||
                :index="index"
 | 
			
		||||
                :active-id="activeId"
 | 
			
		||||
                :form-conf="formConf"
 | 
			
		||||
                @activeItem="activeFormItem"
 | 
			
		||||
                @copyItem="drawingItemCopy"
 | 
			
		||||
                @deleteItem="drawingItemDelete"
 | 
			
		||||
              />
 | 
			
		||||
            </draggable>
 | 
			
		||||
            <div v-show="!drawingList.length" class="empty-info">
 | 
			
		||||
              从左侧拖入或点选组件进行表单设计
 | 
			
		||||
            </div>
 | 
			
		||||
          </el-form>
 | 
			
		||||
        </el-row>
 | 
			
		||||
      </el-scrollbar>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <!-- 右边:组件属性/表单属性 -->
 | 
			
		||||
    <right-panel
 | 
			
		||||
      :active-data="activeData"
 | 
			
		||||
      :form-conf="formConf"
 | 
			
		||||
      :show-field="!!drawingList.length"
 | 
			
		||||
      @tag-change="tagChange"
 | 
			
		||||
      @fetch-data="fetchData"
 | 
			
		||||
    />
 | 
			
		||||
 | 
			
		||||
<!--    <form-drawer-->
 | 
			
		||||
<!--      :visible.sync="drawerVisible"-->
 | 
			
		||||
<!--      :form-data="formData"-->
 | 
			
		||||
<!--      size="100%"-->
 | 
			
		||||
<!--      :generate-conf="generateConf"-->
 | 
			
		||||
<!--    />-->
 | 
			
		||||
 | 
			
		||||
    <json-drawer
 | 
			
		||||
      size="60%"
 | 
			
		||||
      :visible.sync="jsonDrawerVisible"
 | 
			
		||||
      :json-str="JSON.stringify(formData)"
 | 
			
		||||
      @refresh="refreshJson"
 | 
			
		||||
    />
 | 
			
		||||
 | 
			
		||||
<!--    <code-type-dialog-->
 | 
			
		||||
<!--      :visible.sync="dialogVisible"-->
 | 
			
		||||
<!--      title="选择生成类型"-->
 | 
			
		||||
<!--      :show-file-name="showFileName"-->
 | 
			
		||||
<!--      @confirm="generate"-->
 | 
			
		||||
<!--    />-->
 | 
			
		||||
 | 
			
		||||
<!--    <input id="copyNode" type="hidden">-->
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import draggable from 'vuedraggable'
 | 
			
		||||
import { debounce } from 'throttle-debounce'
 | 
			
		||||
import { saveAs } from 'file-saver'
 | 
			
		||||
import ClipboardJS from 'clipboard'
 | 
			
		||||
import render from '@/components/render/render'
 | 
			
		||||
import FormDrawer from '@/views/infra/build/FormDrawer'
 | 
			
		||||
import JsonDrawer from '@/views/infra/build/JsonDrawer'
 | 
			
		||||
import RightPanel from '@/views/infra/build/RightPanel'
 | 
			
		||||
import {
 | 
			
		||||
  inputComponents, selectComponents, layoutComponents, formConf
 | 
			
		||||
} from '@/components/generator/config'
 | 
			
		||||
import {beautifierConf, titleCase, deepClone, isObjectObject} from '@/utils'
 | 
			
		||||
import {
 | 
			
		||||
  makeUpHtml, vueTemplate, vueScript, cssStyle
 | 
			
		||||
} from '@/components/generator/html'
 | 
			
		||||
import { makeUpJs } from '@/components/generator/js'
 | 
			
		||||
import { makeUpCss } from '@/components/generator/css'
 | 
			
		||||
import drawingDefalut from '@/components/generator/drawingDefalut'
 | 
			
		||||
import logo from '@/assets/logo/logo.png'
 | 
			
		||||
import CodeTypeDialog from '@/views/infra/build/CodeTypeDialog'
 | 
			
		||||
import DraggableItem from '@/views/infra/build/DraggableItem'
 | 
			
		||||
import {
 | 
			
		||||
  getDrawingList, saveDrawingList, getIdGlobal, saveIdGlobal, getFormConf
 | 
			
		||||
} from '@/utils/db'
 | 
			
		||||
import loadBeautifier from '@/utils/loadBeautifier'
 | 
			
		||||
import {CommonStatusEnum} from "@/utils/constants";
 | 
			
		||||
import {createForm, getForm, updateForm} from "@/api/bpm/form";
 | 
			
		||||
import {decodeFields} from "@/utils/formGenerator";
 | 
			
		||||
 | 
			
		||||
let beautifier
 | 
			
		||||
const emptyActiveData = { style: {}, autosize: {} }
 | 
			
		||||
let oldActiveId
 | 
			
		||||
let tempActiveData
 | 
			
		||||
const drawingListInDB = getDrawingList()
 | 
			
		||||
const formConfInDB = getFormConf()
 | 
			
		||||
const idGlobal = getIdGlobal()
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  components: {
 | 
			
		||||
    draggable,
 | 
			
		||||
    render,
 | 
			
		||||
    FormDrawer,
 | 
			
		||||
    JsonDrawer,
 | 
			
		||||
    RightPanel,
 | 
			
		||||
    CodeTypeDialog,
 | 
			
		||||
    DraggableItem
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      logo,
 | 
			
		||||
      idGlobal,
 | 
			
		||||
      formConf,
 | 
			
		||||
      inputComponents,
 | 
			
		||||
      selectComponents,
 | 
			
		||||
      layoutComponents,
 | 
			
		||||
      labelWidth: 100,
 | 
			
		||||
      // drawingList: drawingDefalut,
 | 
			
		||||
      drawingData: {}, // 生成后的表单数据
 | 
			
		||||
      activeId: drawingDefalut[0].__config__.formId,
 | 
			
		||||
 | 
			
		||||
      drawingList: [], // 表单项的数组
 | 
			
		||||
      // activeId: undefined,
 | 
			
		||||
      // activeData: {},
 | 
			
		||||
 | 
			
		||||
      drawerVisible: false,
 | 
			
		||||
      formData: {},
 | 
			
		||||
      dialogVisible: false,
 | 
			
		||||
      jsonDrawerVisible: false,
 | 
			
		||||
      generateConf: null,
 | 
			
		||||
      showFileName: false,
 | 
			
		||||
      activeData: drawingDefalut[0], // 右边编辑器激活的表单项
 | 
			
		||||
      saveDrawingListDebounce: debounce(340, saveDrawingList),
 | 
			
		||||
      saveIdGlobalDebounce: debounce(340, saveIdGlobal),
 | 
			
		||||
      leftComponents: [
 | 
			
		||||
        {
 | 
			
		||||
          title: '输入型组件',
 | 
			
		||||
          list: inputComponents
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          title: '选择型组件',
 | 
			
		||||
          list: selectComponents
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          title: '布局型组件',
 | 
			
		||||
          list: layoutComponents
 | 
			
		||||
        }
 | 
			
		||||
      ],
 | 
			
		||||
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {
 | 
			
		||||
        status: CommonStatusEnum.ENABLE,
 | 
			
		||||
      },
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        name: [{ required: true, message: "表单名不能为空", trigger: "blur" }],
 | 
			
		||||
        status: [{ required: true, message: "开启状态不能为空", trigger: "blur" }],
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
  },
 | 
			
		||||
  watch: {
 | 
			
		||||
    // eslint-disable-next-line func-names
 | 
			
		||||
    'activeData.__config__.label': function (val, oldVal) {
 | 
			
		||||
      if (
 | 
			
		||||
        this.activeData.placeholder === undefined
 | 
			
		||||
        || !this.activeData.__config__.tag
 | 
			
		||||
        || oldActiveId !== this.activeId
 | 
			
		||||
      ) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
      this.activeData.placeholder = this.activeData.placeholder.replace(oldVal, '') + val
 | 
			
		||||
    },
 | 
			
		||||
    activeId: {
 | 
			
		||||
      handler(val) {
 | 
			
		||||
        oldActiveId = val
 | 
			
		||||
      },
 | 
			
		||||
      immediate: true
 | 
			
		||||
    },
 | 
			
		||||
    drawingList: {
 | 
			
		||||
      handler(val) {
 | 
			
		||||
        this.saveDrawingListDebounce(val)
 | 
			
		||||
        if (val.length === 0) this.idGlobal = 100
 | 
			
		||||
      },
 | 
			
		||||
      deep: true
 | 
			
		||||
    },
 | 
			
		||||
    idGlobal: {
 | 
			
		||||
      handler(val) {
 | 
			
		||||
        this.saveIdGlobalDebounce(val)
 | 
			
		||||
      },
 | 
			
		||||
      immediate: true
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  mounted() {
 | 
			
		||||
    // 【add by 芋道源码】不读缓存
 | 
			
		||||
    // if (Array.isArray(drawingListInDB) && drawingListInDB.length > 0) {
 | 
			
		||||
    //   this.drawingList = drawingListInDB
 | 
			
		||||
    // } else {
 | 
			
		||||
    //   this.drawingList = drawingDefalut
 | 
			
		||||
    // }
 | 
			
		||||
    // this.activeFormItem(this.drawingList[0])
 | 
			
		||||
    // if (formConfInDB) {
 | 
			
		||||
    //   this.formConf = formConfInDB
 | 
			
		||||
    // }
 | 
			
		||||
    loadBeautifier(btf => {
 | 
			
		||||
      beautifier = btf
 | 
			
		||||
    })
 | 
			
		||||
    const clipboard = new ClipboardJS('#copyNode', {
 | 
			
		||||
      text: trigger => {
 | 
			
		||||
        const codeStr = this.generateCode()
 | 
			
		||||
        this.$notify({
 | 
			
		||||
          title: '成功',
 | 
			
		||||
          message: '代码已复制到剪切板,可粘贴。',
 | 
			
		||||
          type: 'success'
 | 
			
		||||
        })
 | 
			
		||||
        return codeStr
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    clipboard.on('error', e => {
 | 
			
		||||
      this.$message.error('代码复制失败')
 | 
			
		||||
    })
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    // 读取表单配置
 | 
			
		||||
    const formId = this.$route.query && this.$route.query.formId
 | 
			
		||||
    if (formId) {
 | 
			
		||||
      getForm(formId).then(response => {
 | 
			
		||||
        const data = response.data
 | 
			
		||||
        this.form = {
 | 
			
		||||
          id: data.id,
 | 
			
		||||
          name: data.name,
 | 
			
		||||
          status: data.status,
 | 
			
		||||
          remark: data.remark
 | 
			
		||||
        }
 | 
			
		||||
        this.formConf = JSON.parse(data.conf)
 | 
			
		||||
        this.drawingList = decodeFields(data.fields)
 | 
			
		||||
        // 设置激活的表单项
 | 
			
		||||
        this.activeData = this.drawingList[0]
 | 
			
		||||
        this.activeId = this.activeData.__config__.formId
 | 
			
		||||
        // 设置 idGlobal,避免重复
 | 
			
		||||
        this.idGlobal += this.drawingList.length
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    setObjectValueReduce(obj, strKeys, data) {
 | 
			
		||||
      const arr = strKeys.split('.')
 | 
			
		||||
      arr.reduce((pre, item, i) => {
 | 
			
		||||
        if (arr.length === i + 1) {
 | 
			
		||||
          pre[item] = data
 | 
			
		||||
        } else if (!isObjectObject(pre[item])) {
 | 
			
		||||
          pre[item] = {}
 | 
			
		||||
        }
 | 
			
		||||
        return pre[item]
 | 
			
		||||
      }, obj)
 | 
			
		||||
    },
 | 
			
		||||
    setRespData(component, resp) {
 | 
			
		||||
      const { dataPath, renderKey, dataConsumer } = component.__config__
 | 
			
		||||
      if (!dataPath || !dataConsumer) return
 | 
			
		||||
      const respData = dataPath.split('.').reduce((pre, item) => pre[item], resp)
 | 
			
		||||
 | 
			
		||||
      // 将请求回来的数据,赋值到指定属性。
 | 
			
		||||
      // 以el-tabel为例,根据Element文档,应该将数据赋值给el-tabel的data属性,所以dataConsumer的值应为'data';
 | 
			
		||||
      // 此时赋值代码可写成 component[dataConsumer] = respData;
 | 
			
		||||
      // 但为支持更深层级的赋值(如:dataConsumer的值为'options.data'),使用setObjectValueReduce
 | 
			
		||||
      this.setObjectValueReduce(component, dataConsumer, respData)
 | 
			
		||||
      const i = this.drawingList.findIndex(item => item.__config__.renderKey === renderKey)
 | 
			
		||||
      if (i > -1) this.$set(this.drawingList, i, component)
 | 
			
		||||
    },
 | 
			
		||||
    fetchData(component) {
 | 
			
		||||
      const { dataType, method, url } = component.__config__
 | 
			
		||||
      if (dataType === 'dynamic' && method && url) {
 | 
			
		||||
        this.setLoading(component, true)
 | 
			
		||||
        this.$axios({
 | 
			
		||||
          method,
 | 
			
		||||
          url
 | 
			
		||||
        }).then(resp => {
 | 
			
		||||
          this.setLoading(component, false)
 | 
			
		||||
          this.setRespData(component, resp.data)
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    setLoading(component, val) {
 | 
			
		||||
      const { directives } = component
 | 
			
		||||
      if (Array.isArray(directives)) {
 | 
			
		||||
        const t = directives.find(d => d.name === 'loading')
 | 
			
		||||
        if (t) t.value = val
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    activeFormItem(currentItem) {
 | 
			
		||||
      this.activeData = currentItem
 | 
			
		||||
      this.activeId = currentItem.__config__.formId
 | 
			
		||||
    },
 | 
			
		||||
    onEnd(obj) {
 | 
			
		||||
      if (obj.from !== obj.to) {
 | 
			
		||||
        this.fetchData(tempActiveData)
 | 
			
		||||
        this.activeData = tempActiveData
 | 
			
		||||
        this.activeId = this.idGlobal
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    addComponent(item) {
 | 
			
		||||
      const clone = this.cloneComponent(item)
 | 
			
		||||
      this.fetchData(clone)
 | 
			
		||||
      this.drawingList.push(clone)
 | 
			
		||||
      this.activeFormItem(clone)
 | 
			
		||||
    },
 | 
			
		||||
    cloneComponent(origin) {
 | 
			
		||||
      const clone = deepClone(origin)
 | 
			
		||||
      const config = clone.__config__
 | 
			
		||||
      config.span = this.formConf.span // 生成代码时,会根据span做精简判断
 | 
			
		||||
      this.createIdAndKey(clone)
 | 
			
		||||
      clone.placeholder !== undefined && (clone.placeholder += config.label)
 | 
			
		||||
      tempActiveData = clone
 | 
			
		||||
      return tempActiveData
 | 
			
		||||
    },
 | 
			
		||||
    createIdAndKey(item) {
 | 
			
		||||
      const config = item.__config__
 | 
			
		||||
      config.formId = ++this.idGlobal
 | 
			
		||||
      config.renderKey = `${config.formId}${+new Date()}` // 改变renderKey后可以实现强制更新组件
 | 
			
		||||
      if (config.layout === 'colFormItem') {
 | 
			
		||||
        item.__vModel__ = `field${this.idGlobal}`
 | 
			
		||||
      } else if (config.layout === 'rowFormItem') {
 | 
			
		||||
        config.componentName = `row${this.idGlobal}`
 | 
			
		||||
        !Array.isArray(config.children) && (config.children = [])
 | 
			
		||||
        delete config.label // rowFormItem无需配置label属性
 | 
			
		||||
      }
 | 
			
		||||
      if (Array.isArray(config.children)) {
 | 
			
		||||
        config.children = config.children.map(childItem => this.createIdAndKey(childItem))
 | 
			
		||||
      }
 | 
			
		||||
      return item
 | 
			
		||||
    },
 | 
			
		||||
    // 获得表单数据
 | 
			
		||||
    AssembleFormData() {
 | 
			
		||||
      this.formData = {
 | 
			
		||||
        fields: deepClone(this.drawingList),
 | 
			
		||||
        ...this.formConf
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    save() {
 | 
			
		||||
      // this.AssembleFormData()
 | 
			
		||||
      // console.log(this.formData)
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        const form = {
 | 
			
		||||
          conf: JSON.stringify(this.formConf), // 表单配置
 | 
			
		||||
          fields: this.encodeFields(), // 表单项的数组
 | 
			
		||||
          ...this.form // 表单名等
 | 
			
		||||
        }
 | 
			
		||||
        // 修改的提交
 | 
			
		||||
        if (this.form.id != null) {
 | 
			
		||||
          updateForm(form).then(response => {
 | 
			
		||||
            this.$modal.msgSuccess("修改成功");
 | 
			
		||||
            this.close()
 | 
			
		||||
          });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 添加的提交
 | 
			
		||||
        createForm(form).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("新增成功");
 | 
			
		||||
          this.close()
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 关闭按钮 */
 | 
			
		||||
    close() {
 | 
			
		||||
      this.$tab.closeOpenPage({ path: "/bpm/manager/form" });
 | 
			
		||||
    },
 | 
			
		||||
    encodeFields() {
 | 
			
		||||
      const fields = []
 | 
			
		||||
      this.drawingList.forEach(item => {
 | 
			
		||||
        fields.push(JSON.stringify(item))
 | 
			
		||||
      })
 | 
			
		||||
      return fields
 | 
			
		||||
    },
 | 
			
		||||
    generate(data) {
 | 
			
		||||
      const func = this[`exec${titleCase(this.operationType)}`]
 | 
			
		||||
      this.generateConf = data
 | 
			
		||||
      func && func(data)
 | 
			
		||||
    },
 | 
			
		||||
    execRun(data) {
 | 
			
		||||
      this.AssembleFormData()
 | 
			
		||||
      this.drawerVisible = true
 | 
			
		||||
    },
 | 
			
		||||
    execDownload(data) {
 | 
			
		||||
      const codeStr = this.generateCode()
 | 
			
		||||
      const blob = new Blob([codeStr], { type: 'text/plain;charset=utf-8' })
 | 
			
		||||
      saveAs(blob, data.fileName)
 | 
			
		||||
    },
 | 
			
		||||
    execCopy(data) {
 | 
			
		||||
      document.getElementById('copyNode').click()
 | 
			
		||||
    },
 | 
			
		||||
    empty() {
 | 
			
		||||
      this.$confirm('确定要清空所有组件吗?', '提示', { type: 'warning' }).then(
 | 
			
		||||
        () => {
 | 
			
		||||
          this.drawingList = []
 | 
			
		||||
          this.idGlobal = 100
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
    },
 | 
			
		||||
    drawingItemCopy(item, list) {
 | 
			
		||||
      let clone = deepClone(item)
 | 
			
		||||
      clone = this.createIdAndKey(clone)
 | 
			
		||||
      list.push(clone)
 | 
			
		||||
      this.activeFormItem(clone)
 | 
			
		||||
    },
 | 
			
		||||
    drawingItemDelete(index, list) {
 | 
			
		||||
      list.splice(index, 1)
 | 
			
		||||
      this.$nextTick(() => {
 | 
			
		||||
        const len = this.drawingList.length
 | 
			
		||||
        if (len) {
 | 
			
		||||
          this.activeFormItem(this.drawingList[len - 1])
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    generateCode() {
 | 
			
		||||
      const { type } = this.generateConf
 | 
			
		||||
      this.AssembleFormData()
 | 
			
		||||
      const script = vueScript(makeUpJs(this.formData, type))
 | 
			
		||||
      const html = vueTemplate(makeUpHtml(this.formData, type))
 | 
			
		||||
      const css = cssStyle(makeUpCss(this.formData))
 | 
			
		||||
      return beautifier.html(html + script + css, beautifierConf.html)
 | 
			
		||||
    },
 | 
			
		||||
    showJson() {
 | 
			
		||||
      this.AssembleFormData()
 | 
			
		||||
      this.jsonDrawerVisible = true
 | 
			
		||||
    },
 | 
			
		||||
    download() {
 | 
			
		||||
      this.dialogVisible = true
 | 
			
		||||
      this.showFileName = true
 | 
			
		||||
      this.operationType = 'download'
 | 
			
		||||
    },
 | 
			
		||||
    run() {
 | 
			
		||||
      this.dialogVisible = true
 | 
			
		||||
      this.showFileName = false
 | 
			
		||||
      this.operationType = 'run'
 | 
			
		||||
    },
 | 
			
		||||
    copy() {
 | 
			
		||||
      this.dialogVisible = true
 | 
			
		||||
      this.showFileName = false
 | 
			
		||||
      this.operationType = 'copy'
 | 
			
		||||
    },
 | 
			
		||||
    tagChange(newTag) {
 | 
			
		||||
      newTag = this.cloneComponent(newTag)
 | 
			
		||||
      const config = newTag.__config__
 | 
			
		||||
      newTag.__vModel__ = this.activeData.__vModel__
 | 
			
		||||
      config.formId = this.activeId
 | 
			
		||||
      config.span = this.activeData.__config__.span
 | 
			
		||||
      this.activeData.__config__.tag = config.tag
 | 
			
		||||
      this.activeData.__config__.tagIcon = config.tagIcon
 | 
			
		||||
      this.activeData.__config__.document = config.document
 | 
			
		||||
      if (typeof this.activeData.__config__.defaultValue === typeof config.defaultValue) {
 | 
			
		||||
        config.defaultValue = this.activeData.__config__.defaultValue
 | 
			
		||||
      }
 | 
			
		||||
      Object.keys(newTag).forEach(key => {
 | 
			
		||||
        if (this.activeData[key] !== undefined) {
 | 
			
		||||
          newTag[key] = this.activeData[key]
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
      this.activeData = newTag
 | 
			
		||||
      this.updateDrawingList(newTag, this.drawingList)
 | 
			
		||||
    },
 | 
			
		||||
    updateDrawingList(newTag, list) {
 | 
			
		||||
      const index = list.findIndex(item => item.__config__.formId === this.activeId)
 | 
			
		||||
      if (index > -1) {
 | 
			
		||||
        list.splice(index, 1, newTag)
 | 
			
		||||
      } else {
 | 
			
		||||
        list.forEach(item => {
 | 
			
		||||
          if (Array.isArray(item.__config__.children)) this.updateDrawingList(newTag, item.__config__.children)
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    refreshJson(data) {
 | 
			
		||||
      this.drawingList = deepClone(data.fields)
 | 
			
		||||
      delete data.fields
 | 
			
		||||
      this.formConf = data
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang='scss'>
 | 
			
		||||
@import '@/styles/home';
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,161 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="表单名" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入表单名" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['bpm:form:create']">新增</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="编号" align="center" prop="id" />
 | 
			
		||||
      <el-table-column label="表单名" align="center" prop="name" />
 | 
			
		||||
      <el-table-column label="开启状态" align="center" prop="status">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="备注" align="center" prop="remark" />
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleDetail(scope.row)"
 | 
			
		||||
                     v-hasPermi="['bpm:form:query']">详情</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                     v-hasPermi="['bpm:form:update']">修改</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-hasPermi="['bpm:form:delete']">删除</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!--表单配置详情-->
 | 
			
		||||
    <el-dialog title="表单详情" :visible.sync="detailOpen" width="50%" append-to-body>
 | 
			
		||||
      <div class="test-form">
 | 
			
		||||
        <parser :key="new Date().getTime()" :form-conf="detailForm" />
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {deleteForm, getForm, getFormPage} from "@/api/bpm/form";
 | 
			
		||||
import Parser from '@/components/parser/Parser'
 | 
			
		||||
import {decodeFields} from "@/utils/formGenerator";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "BpmForm",
 | 
			
		||||
  components: {
 | 
			
		||||
    Parser
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 工作流的列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        name: null,
 | 
			
		||||
      },
 | 
			
		||||
      // 表单详情
 | 
			
		||||
      detailOpen: false,
 | 
			
		||||
      detailForm: {
 | 
			
		||||
        fields: []
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getFormPage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 详情按钮操作 */
 | 
			
		||||
    handleDetail(row) {
 | 
			
		||||
      getForm(row.id).then(response => {
 | 
			
		||||
        // 设置值
 | 
			
		||||
        const data = response.data
 | 
			
		||||
        this.detailForm = {
 | 
			
		||||
          ...JSON.parse(data.conf),
 | 
			
		||||
          fields: decodeFields(data.fields)
 | 
			
		||||
        }
 | 
			
		||||
        // 弹窗打开
 | 
			
		||||
        this.detailOpen = true
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.$router.push({
 | 
			
		||||
        name: "BpmFormEditor"
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.$router.push({
 | 
			
		||||
        name: "BpmFormEditor",
 | 
			
		||||
        query:{
 | 
			
		||||
          formId: row.id
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认删除工作表单的编号为"' + id + '"的数据项?').then(function() {
 | 
			
		||||
        return deleteForm(id);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("删除成功");
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,246 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="组名" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入组名" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="状态" prop="status">
 | 
			
		||||
        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
 | 
			
		||||
                     :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['bpm:user-group:create']">新增</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="编号" align="center" prop="id" />
 | 
			
		||||
      <el-table-column label="组名" align="center" prop="name" />
 | 
			
		||||
      <el-table-column label="描述" align="center" prop="description" />
 | 
			
		||||
      <el-table-column label="成员" align="center">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span v-for="userId in scope.row.memberUserIds">
 | 
			
		||||
            {{ getUserNickname(userId) }}
 | 
			
		||||
          </span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="状态" align="center" prop="status">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                     v-hasPermi="['bpm:user-group:update']">修改</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-hasPermi="['bpm:user-group:delete']">删除</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
 | 
			
		||||
        <el-form-item label="组名" prop="name">
 | 
			
		||||
          <el-input v-model="form.name" placeholder="请输入组名" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="描述" prop="description">
 | 
			
		||||
          <el-input v-model="form.description" placeholder="请输入描述" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="成员" prop="memberUserIds">
 | 
			
		||||
          <el-select v-model="form.memberUserIds" multiple placeholder="请选择成员">
 | 
			
		||||
            <el-option v-for="user in users" :key="parseInt(user.id)" :label="user.nickname" :value="parseInt(user.id)"/>
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="状态" prop="status">
 | 
			
		||||
          <el-radio-group v-model="form.status">
 | 
			
		||||
            <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
 | 
			
		||||
                      :key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { createUserGroup, updateUserGroup, deleteUserGroup, getUserGroup, getUserGroupPage } from "@/api/bpm/userGroup";
 | 
			
		||||
import {CommonStatusEnum} from "@/utils/constants";
 | 
			
		||||
import {listSimpleUsers} from "@/api/system/user";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "BpmUserGroup",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 用户组列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 用户列表
 | 
			
		||||
      users: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        name: null,
 | 
			
		||||
        status: null,
 | 
			
		||||
        createTime: []
 | 
			
		||||
      },
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {},
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        name: [{ required: true, message: "组名不能为空", trigger: "blur" }],
 | 
			
		||||
        description: [{ required: true, message: "描述不能为空", trigger: "blur" }],
 | 
			
		||||
        memberUserIds: [{ required: true, message: "成员不能为空", trigger: "change" }],
 | 
			
		||||
        status: [{ required: true, message: "状态不能为空", trigger: "blur" }],
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
    // 获得用户列表
 | 
			
		||||
    listSimpleUsers().then(response => {
 | 
			
		||||
      this.users = response.data;
 | 
			
		||||
    })
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getUserGroupPage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        description: undefined,
 | 
			
		||||
        memberUserIds: [],
 | 
			
		||||
        status: CommonStatusEnum.ENABLE,
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.title = "添加用户组";
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      getUserGroup(id).then(response => {
 | 
			
		||||
        this.form = response.data;
 | 
			
		||||
        this.open = true;
 | 
			
		||||
        this.title = "修改用户组";
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 修改的提交
 | 
			
		||||
        if (this.form.id != null) {
 | 
			
		||||
          updateUserGroup(this.form).then(response => {
 | 
			
		||||
            this.$modal.msgSuccess("修改成功");
 | 
			
		||||
            this.open = false;
 | 
			
		||||
            this.getList();
 | 
			
		||||
          });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 添加的提交
 | 
			
		||||
        createUserGroup(this.form).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("新增成功");
 | 
			
		||||
          this.open = false;
 | 
			
		||||
          this.getList();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认删除用户组编号为"' + id + '"的数据项?').then(function() {
 | 
			
		||||
        return deleteUserGroup(id);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("删除成功");
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    getUserNickname(userId) {
 | 
			
		||||
      for (const user of this.users) {
 | 
			
		||||
        if (user.id === userId) {
 | 
			
		||||
          return user.nickname;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      return '未知(' + userId + ')';
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,548 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="流程标识" prop="key">
 | 
			
		||||
        <el-input v-model="queryParams.key" placeholder="请输入流程标识" clearable style="width: 240px;"
 | 
			
		||||
                  @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="流程名称" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入流程名称" clearable style="width: 240px;"
 | 
			
		||||
                  @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="流程分类" prop="category">
 | 
			
		||||
        <el-select v-model="queryParams.category" placeholder="流程分类" clearable style="width: 240px">
 | 
			
		||||
          <el-option v-for="dict in categoryDictDatas" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['bpm:model:create']">新建流程</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="info" icon="el-icon-upload2" size="mini" @click="handleImport"
 | 
			
		||||
                   v-hasPermi="['bpm:model:import']">导入流程</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="流程标识" align="center" prop="key" />
 | 
			
		||||
      <el-table-column label="流程名称" align="center" prop="name" width="200">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button type="text" @click="handleBpmnDetail(scope.row)">
 | 
			
		||||
            <span>{{ scope.row.name }}</span>
 | 
			
		||||
          </el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="流程分类" align="center" prop="category" width="100">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.BPM_MODEL_CATEGORY" :value="scope.row.category" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="表单信息" align="center" prop="formType" width="200">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button v-if="scope.row.formId" type="text" @click="handleFormDetail(scope.row)">
 | 
			
		||||
            <span>{{ scope.row.formName }}</span>
 | 
			
		||||
          </el-button>
 | 
			
		||||
          <el-button v-else-if="scope.row.formCustomCreatePath" type="text" @click="handleFormDetail(scope.row)">
 | 
			
		||||
            <span>{{ scope.row.formCustomCreatePath }}</span>
 | 
			
		||||
          </el-button>
 | 
			
		||||
          <label v-else>暂无表单</label>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="最新部署的流程定义" align="center">
 | 
			
		||||
        <el-table-column label="流程版本" align="center" prop="processDefinition.version" width="80">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <el-tag size="medium" v-if="scope.row.processDefinition">v{{ scope.row.processDefinition.version }}</el-tag>
 | 
			
		||||
            <el-tag size="medium" type="warning" v-else>未部署</el-tag>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="激活状态" align="center" prop="processDefinition.version" width="80">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <el-switch v-if="scope.row.processDefinition" v-model="scope.row.processDefinition.suspensionState"
 | 
			
		||||
                       :active-value="1" :inactive-value="2" @change="handleChangeState(scope.row)" />
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="部署时间" align="center" prop="deploymentTime" width="180">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <span v-if="scope.row.processDefinition">{{ parseTime(scope.row.processDefinition.deploymentTime) }}</span>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" width="450" fixed="right">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                     v-hasPermi="['bpm:model:update']">修改流程</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-setting" @click="handleDesign(scope.row)"
 | 
			
		||||
                     v-hasPermi="['bpm:model:update']">设计流程</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-s-custom" @click="handleAssignRule(scope.row)"
 | 
			
		||||
                     v-hasPermi="['bpm:task-assign-rule:query']">分配规则</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-thumb" @click="handleDeploy(scope.row)"
 | 
			
		||||
                     v-hasPermi="['bpm:model:deploy']">发布流程</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-ice-cream-round" @click="handleDefinitionList(scope.row)"
 | 
			
		||||
                     v-hasPermi="['bpm:process-definition:query']">流程定义</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-hasPermi="['bpm:model:delete']">删除</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 流程表单配置详情 -->
 | 
			
		||||
    <el-dialog title="表单详情" :visible.sync="detailOpen" width="50%" append-to-body>
 | 
			
		||||
      <parser :key="new Date().getTime()" :form-conf="detailForm" />
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
 | 
			
		||||
    <!-- 流程模型图的预览 -->
 | 
			
		||||
    <el-dialog title="流程图" :visible.sync="showBpmnOpen" width="80%" append-to-body>
 | 
			
		||||
      <my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" />
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="110px">
 | 
			
		||||
        <el-form-item label="流程标识" prop="key">
 | 
			
		||||
          <el-input v-model="form.key" placeholder="请输入流标标识" style="width: 330px;" :disabled="!!form.id" />
 | 
			
		||||
          <el-tooltip v-if="!form.id" class="item" effect="light" content="新建后,流程标识不可修改!" placement="top">
 | 
			
		||||
            <i style="padding-left: 5px;" class="el-icon-question" />
 | 
			
		||||
          </el-tooltip>
 | 
			
		||||
          <el-tooltip v-else class="item" effect="light" content="流程标识不可修改!" placement="top">
 | 
			
		||||
            <i style="padding-left: 5px;" class="el-icon-question" />
 | 
			
		||||
          </el-tooltip>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="流程名称" prop="name">
 | 
			
		||||
          <el-input v-model="form.name" placeholder="请输入流程名称" :disabled="!!form.id" clearable />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.id" label="流程分类" prop="category">
 | 
			
		||||
          <el-select v-model="form.category" placeholder="请选择流程分类" clearable style="width: 100%">
 | 
			
		||||
            <el-option v-for="dict in categoryDictDatas" :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="流程描述" prop="description">
 | 
			
		||||
          <el-input type="textarea" v-model="form.description" clearable />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <div v-if="form.id">
 | 
			
		||||
          <el-form-item label="表单类型" prop="formType">
 | 
			
		||||
            <el-radio-group v-model="form.formType">
 | 
			
		||||
              <el-radio v-for="dict in modelFormTypeDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
 | 
			
		||||
                {{dict.label}}
 | 
			
		||||
              </el-radio>
 | 
			
		||||
            </el-radio-group>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item v-if="form.formType === 10" label="流程表单" prop="formId">
 | 
			
		||||
            <el-select v-model="form.formId" clearable style="width: 100%">
 | 
			
		||||
              <el-option v-for="form in forms" :key="form.id" :label="form.name" :value="form.id"/>
 | 
			
		||||
            </el-select>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item v-if="form.formType === 20" label="表单提交路由" prop="formCustomCreatePath" >
 | 
			
		||||
            <el-input v-model="form.formCustomCreatePath" placeholder="请输入表单提交路由" style="width: 330px;" />
 | 
			
		||||
            <el-tooltip class="item" effect="light" content="自定义表单的提交路径,使用 Vue 的路由地址,例如说:bpm/oa/leave/create" placement="top">
 | 
			
		||||
              <i style="padding-left: 5px;" class="el-icon-question" />
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item v-if="form.formType === 20" label="表单查看路由" prop="formCustomViewPath">
 | 
			
		||||
            <el-input v-model="form.formCustomViewPath" placeholder="请输入表单查看路由" style="width: 330px;" />
 | 
			
		||||
            <el-tooltip class="item" effect="light" content="自定义表单的查看路径,使用 Vue 的路由地址,例如说:bpm/oa/leave/view" placement="top">
 | 
			
		||||
              <i style="padding-left: 5px;" class="el-icon-question" />
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </div>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
 | 
			
		||||
    <!-- 用户导入对话框 -->
 | 
			
		||||
    <el-dialog title="导入流程" :visible.sync="upload.open" width="400px" append-to-body>
 | 
			
		||||
      <el-upload ref="upload" :limit="1" accept=".bpmn, .xml" :headers="upload.headers" :action="upload.url"
 | 
			
		||||
        :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess"
 | 
			
		||||
        :auto-upload="false" name="bpmnFile" :data="upload.form" drag>
 | 
			
		||||
        <i class="el-icon-upload"></i>
 | 
			
		||||
        <div class="el-upload__text">
 | 
			
		||||
          将文件拖到此处,或
 | 
			
		||||
          <em>点击上传</em>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“bpm”或“xml”格式文件!</div>
 | 
			
		||||
        <div class="el-upload__tip" slot="tip">
 | 
			
		||||
          <el-form ref="uploadForm" size="mini" label-width="90px" :model="upload.form" :rules="upload.rules" @submit.native.prevent>
 | 
			
		||||
            <el-form-item label="流程标识" prop="key">
 | 
			
		||||
              <el-input v-model="upload.form.key" placeholder="请输入流标标识" style="width: 250px;" />
 | 
			
		||||
              <el-tooltip class="item" effect="light" content="新建后,流程标识不可修改!" placement="top">
 | 
			
		||||
                <i style="padding-left: 5px;" class="el-icon-question" />
 | 
			
		||||
              </el-tooltip>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="流程名称" prop="name">
 | 
			
		||||
              <el-input v-model="upload.form.name" placeholder="请输入流程名称" clearable />
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="流程描述" prop="description">
 | 
			
		||||
              <el-input type="textarea" v-model="upload.form.description" clearable />
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
          </el-form>
 | 
			
		||||
        </div>
 | 
			
		||||
      </el-upload>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitFileForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="uploadClose">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
 | 
			
		||||
    <!-- ========== 流程任务分配规则 ========== -->
 | 
			
		||||
    <taskAssignRuleDialog ref="taskAssignRuleDialog" />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {
 | 
			
		||||
  deleteModel,
 | 
			
		||||
  deployModel,
 | 
			
		||||
  getModelPage,
 | 
			
		||||
  getModel,
 | 
			
		||||
  updateModelState,
 | 
			
		||||
  createModel,
 | 
			
		||||
  updateModel
 | 
			
		||||
} from "@/api/bpm/model";
 | 
			
		||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
 | 
			
		||||
import {getForm, getSimpleForms} from "@/api/bpm/form";
 | 
			
		||||
import {decodeFields} from "@/utils/formGenerator";
 | 
			
		||||
import Parser from '@/components/parser/Parser'
 | 
			
		||||
import {getBaseHeader} from "@/utils/request";
 | 
			
		||||
import taskAssignRuleDialog from "../taskAssignRule/taskAssignRuleDialog";
 | 
			
		||||
 | 
			
		||||
import Treeselect from "@riophae/vue-treeselect";
 | 
			
		||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "BpmModel",
 | 
			
		||||
  components: {
 | 
			
		||||
    Parser,
 | 
			
		||||
    Treeselect,
 | 
			
		||||
    taskAssignRuleDialog
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 表格数据
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      // BPMN 数据
 | 
			
		||||
      showBpmnOpen: false,
 | 
			
		||||
      bpmnXML: null,
 | 
			
		||||
      bpmnControlForm: {
 | 
			
		||||
        prefix: "flowable"
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      // 流程表单详情
 | 
			
		||||
      detailOpen: false,
 | 
			
		||||
      detailForm: {
 | 
			
		||||
        fields: []
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      // 流程表单
 | 
			
		||||
      title: "",
 | 
			
		||||
      open: false,
 | 
			
		||||
      form: {},
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        key: [{ required: true, message: "流程标识不能为空", trigger: "blur" }],
 | 
			
		||||
        name: [{ required: true, message: "流程名称不能为空", trigger: "blur" }],
 | 
			
		||||
        formType: [{ required: true, message: "流程名称不能为空", trigger: "blur" }],
 | 
			
		||||
        formId: [{ required: true, message: "业务表单不能为空", trigger: "blur" }],
 | 
			
		||||
        category: [{ required: true, message: "流程分类不能为空", trigger: "blur" }],
 | 
			
		||||
        formCustomCreatePath: [{ required: true, message: "表单提交路由不能为空", trigger: "blur" }],
 | 
			
		||||
        formCustomViewPath: [{ required: true, message: "表单查看路由不能为空", trigger: "blur" }],
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      // 流程导入参数
 | 
			
		||||
      upload: {
 | 
			
		||||
        // 是否显示弹出层(用户导入)
 | 
			
		||||
        open: false,
 | 
			
		||||
        // 是否禁用上传
 | 
			
		||||
        isUploading: false,
 | 
			
		||||
        // 设置上传的请求头部
 | 
			
		||||
        headers: getBaseHeader(),
 | 
			
		||||
        // 上传的地址
 | 
			
		||||
        url: process.env.VUE_APP_BASE_API + '/admin-api' + "/bpm/model/import",
 | 
			
		||||
        // 表单
 | 
			
		||||
        form: {},
 | 
			
		||||
        // 校验规则
 | 
			
		||||
        rules: {
 | 
			
		||||
          key: [{ required: true, message: "流程标识不能为空", trigger: "blur" }],
 | 
			
		||||
          name: [{ required: true, message: "流程名称不能为空", trigger: "blur" }],
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
      // 流程表单的下拉框的数据
 | 
			
		||||
      forms: [],
 | 
			
		||||
 | 
			
		||||
      // 数据字典
 | 
			
		||||
      categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY),
 | 
			
		||||
      modelFormTypeDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_FORM_TYPE),
 | 
			
		||||
      taskAssignRuleDictDatas: getDictDatas(DICT_TYPE.BPM_TASK_ASSIGN_RULE_TYPE),
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
    // 获得流程表单的下拉框的数据
 | 
			
		||||
    getSimpleForms().then(response => {
 | 
			
		||||
      this.forms = response.data
 | 
			
		||||
    })
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询流程模型列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      getModelPage(this.queryParams).then(response => {
 | 
			
		||||
          this.list = response.data.list;
 | 
			
		||||
          this.total = response.data.total;
 | 
			
		||||
          this.loading = false;
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    // 表单重置
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        key: undefined,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        description: undefined,
 | 
			
		||||
        category: undefined,
 | 
			
		||||
        formType: undefined,
 | 
			
		||||
        formId: undefined,
 | 
			
		||||
        formCustomCreatePath: undefined,
 | 
			
		||||
        formCustomViewPath: undefined
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.dateRange = [];
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.title = "新建模型";
 | 
			
		||||
      this.open = true;
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.title = "修改模型";
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      // 设置 form
 | 
			
		||||
      this.form = {
 | 
			
		||||
        ...row
 | 
			
		||||
      };
 | 
			
		||||
      // 触发一次校验
 | 
			
		||||
      // this.$refs["form"].validate();
 | 
			
		||||
    },
 | 
			
		||||
    /** 设计按钮操作 */
 | 
			
		||||
    handleDesign(row) {
 | 
			
		||||
      this.$router.push({
 | 
			
		||||
        name: "BpmModelEditor",
 | 
			
		||||
        query:{
 | 
			
		||||
          modelId: row.id
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 更新
 | 
			
		||||
        if (this.form.id) {
 | 
			
		||||
          updateModel({
 | 
			
		||||
            ...this.form,
 | 
			
		||||
            formId: this.form.formType === 10 ? this.form.formId : undefined,
 | 
			
		||||
            formCustomCreatePath: this.form.formType === 20 ? this.form.formCustomCreatePath : undefined,
 | 
			
		||||
            formCustomViewPath: this.form.formType === 20 ? this.form.formCustomViewPath : undefined,
 | 
			
		||||
          }).then(response => {
 | 
			
		||||
            this.$modal.msgSuccess("修改模型成功");
 | 
			
		||||
            this.open = false;
 | 
			
		||||
            this.getList();
 | 
			
		||||
          });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 创建
 | 
			
		||||
        createModel(this.form).then(response => {
 | 
			
		||||
          this.open = false;
 | 
			
		||||
          this.getList();
 | 
			
		||||
          this.$alert('<strong>新建模型成功!</strong>后续需要执行如下 4 个步骤:' +
 | 
			
		||||
            '<div>1. 点击【修改流程】按钮,配置流程的分类、表单信息</div>' +
 | 
			
		||||
            '<div>2. 点击【设计流程】按钮,绘制流程图</div>' +
 | 
			
		||||
            '<div>3. 点击【分配规则】按钮,设置每个用户任务的审批人</div>' +
 | 
			
		||||
            '<div>4. 点击【发布流程】按钮,完成流程的最终发布</div>' +
 | 
			
		||||
            '另外,每次流程修改后,都需要点击【发布流程】按钮,才能正式生效!!!',
 | 
			
		||||
            '重要提示', {
 | 
			
		||||
              dangerouslyUseHTMLString: true,
 | 
			
		||||
              type: 'success'
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const that = this;
 | 
			
		||||
      this.$modal.confirm('是否删除该流程!!').then(function() {
 | 
			
		||||
        deleteModel(row.id).then(response => {
 | 
			
		||||
          that.getList();
 | 
			
		||||
          that.$modal.msgSuccess("删除成功");
 | 
			
		||||
        })
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    /** 部署按钮操作 */
 | 
			
		||||
    handleDeploy(row) {
 | 
			
		||||
      const that = this;
 | 
			
		||||
      this.$modal.confirm('是否部署该流程!!').then(function() {
 | 
			
		||||
        deployModel(row.id).then(response => {
 | 
			
		||||
          that.getList();
 | 
			
		||||
          that.$modal.msgSuccess("部署成功");
 | 
			
		||||
        })
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    /** 流程表单的详情按钮操作 */
 | 
			
		||||
    handleFormDetail(row) {
 | 
			
		||||
      // 流程表单
 | 
			
		||||
      if (row.formId) {
 | 
			
		||||
        getForm(row.formId).then(response => {
 | 
			
		||||
          // 设置值
 | 
			
		||||
          const data = response.data
 | 
			
		||||
          this.detailForm = {
 | 
			
		||||
            ...JSON.parse(data.conf),
 | 
			
		||||
            fields: decodeFields(data.fields)
 | 
			
		||||
          }
 | 
			
		||||
          // 弹窗打开
 | 
			
		||||
          this.detailOpen = true
 | 
			
		||||
        })
 | 
			
		||||
        // 业务表单
 | 
			
		||||
      } else if (row.formCustomCreatePath) {
 | 
			
		||||
        this.$router.push({ path: row.formCustomCreatePath});
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    /** 流程图的详情按钮操作 */
 | 
			
		||||
    handleBpmnDetail(row) {
 | 
			
		||||
      getModel(row.id).then(response => {
 | 
			
		||||
        this.bpmnXML = response.data.bpmnXml
 | 
			
		||||
        // 弹窗打开
 | 
			
		||||
        this.showBpmnOpen = true
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    /** 跳转流程定义的列表 */
 | 
			
		||||
    handleDefinitionList(row) {
 | 
			
		||||
      this.$router.push({
 | 
			
		||||
        name: "BpmProcessDefinition",
 | 
			
		||||
        query:{
 | 
			
		||||
          key: row.key
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 更新状态操作 */
 | 
			
		||||
    handleChangeState(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      let state = row.processDefinition.suspensionState;
 | 
			
		||||
      let statusState = state === 1 ? '激活' : '挂起';
 | 
			
		||||
      this.$modal.confirm('是否确认' + statusState + '流程名字为"' + row.name + '"的数据项?').then(function() {
 | 
			
		||||
        return updateModelState(id, state);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess(statusState + "成功");
 | 
			
		||||
      }).catch(() => {
 | 
			
		||||
        // 取消后,进行恢复按钮
 | 
			
		||||
        row.processDefinition.suspensionState = (state === 1 ? 2 : 1);
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 导入按钮操作 */
 | 
			
		||||
    handleImport() {
 | 
			
		||||
      this.upload.open = true;
 | 
			
		||||
    },
 | 
			
		||||
    // 文件上传中处理
 | 
			
		||||
    handleFileUploadProgress(event, file, fileList) {
 | 
			
		||||
      this.upload.isUploading = true;
 | 
			
		||||
    },
 | 
			
		||||
    // 文件上传成功处理
 | 
			
		||||
    handleFileSuccess(response, file, fileList) {
 | 
			
		||||
      if (response.code !== 0) {
 | 
			
		||||
        this.$modal.msgError(response.msg)
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      // 重置表单
 | 
			
		||||
      this.uploadClose();
 | 
			
		||||
      // 提示,并刷新
 | 
			
		||||
      this.$modal.msgSuccess("导入流程成功!请点击【设计流程】按钮,进行编辑保存后,才可以进行【发布流程】");
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    uploadClose() {
 | 
			
		||||
      // 关闭弹窗
 | 
			
		||||
      this.upload.open = false;
 | 
			
		||||
      // 重置上传状态和文件
 | 
			
		||||
      this.upload.isUploading = false;
 | 
			
		||||
      this.$refs.upload.clearFiles();
 | 
			
		||||
      // 重置表单
 | 
			
		||||
      this.upload.form = {};
 | 
			
		||||
      this.resetForm("uploadForm");
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交上传文件 */
 | 
			
		||||
    submitFileForm() {
 | 
			
		||||
      this.$refs["uploadForm"].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        this.$refs.upload.submit();
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    /** 处理任务分配规则列表的按钮操作 */
 | 
			
		||||
    handleAssignRule(row) {
 | 
			
		||||
      this.$refs['taskAssignRuleDialog'].initModel(row.id);
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
.my-process-designer {
 | 
			
		||||
  height: calc(100vh - 200px);
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,170 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
 | 
			
		||||
    <!-- 流程设计器,负责绘制流程等 -->
 | 
			
		||||
    <my-process-designer v-if="xmlString !== undefined" :key="`designer-${reloadIndex}`" v-model="xmlString" v-bind="controlForm"
 | 
			
		||||
      keyboard ref="processDesigner" @init-finished="initModeler"
 | 
			
		||||
      @save="save"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 流程属性器,负责编辑每个流程节点的属性 -->
 | 
			
		||||
    <my-properties-panel :key="`penal-${reloadIndex}`" :bpmn-modeler="modeler" :prefix="controlForm.prefix" class="process-panel"
 | 
			
		||||
      :model="model" />
 | 
			
		||||
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import translations from "@/components/bpmnProcessDesigner/src/translations";
 | 
			
		||||
// 自定义元素选中时的弹出菜单(修改 默认任务 为 用户任务)
 | 
			
		||||
import CustomContentPadProvider from "@/components/bpmnProcessDesigner/package/designer/plugins/content-pad";
 | 
			
		||||
// 自定义左侧菜单(修改 默认任务 为 用户任务)
 | 
			
		||||
import CustomPaletteProvider from "@/components/bpmnProcessDesigner/package/designer/plugins/palette";
 | 
			
		||||
// import xmlObj2json from "./utils/xml2json";
 | 
			
		||||
import MyProcessPalette from "@/components/bpmnProcessDesigner/package/palette/ProcessPalette";
 | 
			
		||||
import {createModel, getModel, updateModel} from "@/api/bpm/model";
 | 
			
		||||
// 自定义侧边栏
 | 
			
		||||
// import MyProcessPanel from "../package/process-panel/ProcessPanel";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "BpmModelEditor",
 | 
			
		||||
  components: { MyProcessPalette },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      xmlString: undefined, // BPMN XML
 | 
			
		||||
      modeler: null,
 | 
			
		||||
      reloadIndex: 0,
 | 
			
		||||
      controlDrawerVisible: false,
 | 
			
		||||
      translationsSelf: translations,
 | 
			
		||||
      controlForm: {
 | 
			
		||||
        simulation: true,
 | 
			
		||||
        labelEditing: false,
 | 
			
		||||
        labelVisible: false,
 | 
			
		||||
        prefix: "flowable",
 | 
			
		||||
        headerButtonSize: "mini",
 | 
			
		||||
        additionalModel: [CustomContentPadProvider, CustomPaletteProvider]
 | 
			
		||||
      },
 | 
			
		||||
      addis: {
 | 
			
		||||
        CustomContentPadProvider,
 | 
			
		||||
        CustomPaletteProvider
 | 
			
		||||
      },
 | 
			
		||||
      // 流程模型的信息
 | 
			
		||||
      model: {},
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    // 如果 modelId 非空,说明是修改流程模型
 | 
			
		||||
    const modelId = this.$route.query && this.$route.query.modelId
 | 
			
		||||
    if (modelId) {
 | 
			
		||||
      getModel(modelId).then(response => {
 | 
			
		||||
        this.xmlString = response.data.bpmnXml
 | 
			
		||||
        this.model = {
 | 
			
		||||
          ...response.data,
 | 
			
		||||
          bpmnXml: undefined, // 清空 bpmnXml 属性
 | 
			
		||||
        }
 | 
			
		||||
        // this.controlForm.processId = response.data.key
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    initModeler(modeler) {
 | 
			
		||||
      setTimeout(() => {
 | 
			
		||||
        this.modeler = modeler;
 | 
			
		||||
        console.log(modeler);
 | 
			
		||||
      }, 10);
 | 
			
		||||
    },
 | 
			
		||||
    save(bpmnXml) {
 | 
			
		||||
      const data = {
 | 
			
		||||
        ...this.model,
 | 
			
		||||
        bpmnXml: bpmnXml, // this.bpmnXml 只是初始化流程图,后续修改无法通过它获得
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // 修改的提交
 | 
			
		||||
      if (data.id) {
 | 
			
		||||
        updateModel(data).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("修改成功")
 | 
			
		||||
          // 跳转回去
 | 
			
		||||
          this.close()
 | 
			
		||||
        })
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
      // 添加的提交
 | 
			
		||||
      createModel(data).then(response => {
 | 
			
		||||
        this.$modal.msgSuccess("保存成功")
 | 
			
		||||
        // 跳转回去
 | 
			
		||||
        this.close()
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    /** 关闭按钮 */
 | 
			
		||||
    close() {
 | 
			
		||||
      this.$tab.closeOpenPage({ path: "/bpm/manager/model" });
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
//body {
 | 
			
		||||
//  overflow: hidden;
 | 
			
		||||
//  margin: 0;
 | 
			
		||||
//  box-sizing: border-box;
 | 
			
		||||
//}
 | 
			
		||||
//.app {
 | 
			
		||||
//  width: 100%;
 | 
			
		||||
//  height: 100%;
 | 
			
		||||
//  box-sizing: border-box;
 | 
			
		||||
//  display: inline-grid;
 | 
			
		||||
//  grid-template-columns: 100px auto max-content;
 | 
			
		||||
//}
 | 
			
		||||
.demo-control-bar {
 | 
			
		||||
  position: fixed;
 | 
			
		||||
  right: 8px;
 | 
			
		||||
  bottom: 8px;
 | 
			
		||||
  z-index: 1;
 | 
			
		||||
  .open-control-dialog {
 | 
			
		||||
    width: 48px;
 | 
			
		||||
    height: 48px;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
    border-radius: 4px;
 | 
			
		||||
    font-size: 32px;
 | 
			
		||||
    background: rgba(64, 158, 255, 1);
 | 
			
		||||
    color: #ffffff;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO 芋艿:去掉多余的 faq
 | 
			
		||||
//.info-tip {
 | 
			
		||||
//  position: fixed;
 | 
			
		||||
//  top: 40px;
 | 
			
		||||
//  right: 500px;
 | 
			
		||||
//  z-index: 10;
 | 
			
		||||
//  color: #999999;
 | 
			
		||||
//}
 | 
			
		||||
 | 
			
		||||
.control-form {
 | 
			
		||||
  .el-radio {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    line-height: 32px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.element-overlays {
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  padding: 8px;
 | 
			
		||||
  background: rgba(0, 0, 0, 0.6);
 | 
			
		||||
  border-radius: 4px;
 | 
			
		||||
  color: #fafafa;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.my-process-designer {
 | 
			
		||||
  height: calc(100vh - 84px);
 | 
			
		||||
}
 | 
			
		||||
.process-panel__container {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  right: 0;
 | 
			
		||||
  top: 55px;
 | 
			
		||||
  height: calc(100vh - 84px);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,75 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
 | 
			
		||||
        <el-form-item label="开始时间" prop="startTime">
 | 
			
		||||
          <el-date-picker clearable size="small" v-model="form.startTime" type="date" value-format="timestamp" placeholder="选择开始时间" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="结束时间" prop="endTime">
 | 
			
		||||
          <el-date-picker clearable size="small" v-model="form.endTime" type="date" value-format="timestamp" placeholder="选择结束时间" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="请假类型" prop="type">
 | 
			
		||||
          <el-select v-model="form.type" placeholder="请选择">
 | 
			
		||||
            <el-option v-for="dict in typeDictData" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="原因" prop="reason">
 | 
			
		||||
          <el-col :span="10">
 | 
			
		||||
            <el-input type="textarea" :rows="3" v-model="form.reason" placeholder="请输入原因" />
 | 
			
		||||
          </el-col>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item>
 | 
			
		||||
          <el-button type="primary" @click="submitForm">提 交</el-button>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { createLeave}  from "@/api/bpm/leave"
 | 
			
		||||
import { getDictDatas, DICT_TYPE } from '@/utils/dict'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "BpmOALeaveCreate",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {
 | 
			
		||||
        startTime: undefined,
 | 
			
		||||
        endTime: undefined,
 | 
			
		||||
        type: undefined,
 | 
			
		||||
        reason: undefined,
 | 
			
		||||
      },
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        startTime: [{ required: true, message: "开始时间不能为空", trigger: "blur" }],
 | 
			
		||||
        endTime: [{ required: true, message: "结束时间不能为空", trigger: "blur" }],
 | 
			
		||||
        type: [{ required: true, message: "请假类型不能为空", trigger: "change" }],
 | 
			
		||||
        reason: [{ required: true, message: "请假原因不能为空", trigger: "change" }],
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      typeDictData: getDictDatas(DICT_TYPE.BPM_OA_LEAVE_TYPE),
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 添加的提交
 | 
			
		||||
        createLeave(this.form).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("发起成功");
 | 
			
		||||
          this.$tab.closeOpenPage({ path: "/bpm/oa/leave" });
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,59 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
      <el-form ref="form" :model="form" label-width="100px">
 | 
			
		||||
        <el-form-item label="开始时间:" prop="startTime"> {{parseTime(form.startTime, '{y}-{m}-{d}')}} </el-form-item>
 | 
			
		||||
        <el-form-item label="结束时间:" prop="endTime"> {{parseTime(form.endTime, '{y}-{m}-{d}')}} </el-form-item>
 | 
			
		||||
        <el-form-item label="请假类型:" prop="type">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.BPM_OA_LEAVE_TYPE" :value="form.type"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="原因:" prop="reason"> {{ form.reason }}</el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { getLeave}  from "@/api/bpm/leave"
 | 
			
		||||
import {getDictDatas, DICT_TYPE} from '@/utils/dict'
 | 
			
		||||
export default {
 | 
			
		||||
  name: "BpmOALeaveDetail",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  props: {
 | 
			
		||||
    id: {
 | 
			
		||||
      type: [String, Number],
 | 
			
		||||
      default: undefined
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      leaveId: undefined, // 请假编号
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {
 | 
			
		||||
        startTime: undefined,
 | 
			
		||||
        endTime: undefined,
 | 
			
		||||
        type: undefined,
 | 
			
		||||
        reason: undefined,
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      typeDictData: getDictDatas(DICT_TYPE.BPM_OA_LEAVE_TYPE),
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.leaveId = this.id || this.$route.query.id;
 | 
			
		||||
    if (!this.leaveId) {
 | 
			
		||||
      this.$message.error('未传递 id 参数,无法查看 OA 请假信息');
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    this.getDetail();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 获得请假信息 */
 | 
			
		||||
    getDetail() {
 | 
			
		||||
      getLeave(this.leaveId).then(response => {
 | 
			
		||||
        this.form = response.data;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,173 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="请假类型" prop="type">
 | 
			
		||||
        <el-select v-model="queryParams.type" placeholder="请选择请假类型" clearable>
 | 
			
		||||
          <el-option v-for="dict in leaveTypeDictData" :key="dict.value" :label="dict.label" :value="dict.value" />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="申请时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="结果" prop="result">
 | 
			
		||||
        <el-select v-model="queryParams.result" placeholder="请选择流结果" clearable>
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT)"
 | 
			
		||||
                     :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="原因" prop="reason">
 | 
			
		||||
        <el-input v-model="queryParams.reason" placeholder="请输入原因" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini"
 | 
			
		||||
                   v-hasPermi="['bpm:oa-leave:create']" @click="handleAdd">发起请假</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="申请编号" align="center" prop="id" />
 | 
			
		||||
      <el-table-column label="状态" align="center" prop="result">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT" :value="scope.row.result"/>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="开始时间" align="center" prop="startTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.startTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="结束时间" align="center" prop="endTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.endTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="请假类型" align="center" prop="type">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.BPM_OA_LEAVE_TYPE" :value="scope.row.type"/>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="原因" align="center" prop="reason" />
 | 
			
		||||
      <el-table-column label="申请时间" align="center" prop="applyTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleCancel(scope.row)"
 | 
			
		||||
                     v-hasPermi="['bpm:oa-leave:create']" v-if="scope.row.result === 1">取消请假</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-view" @click="handleDetail(scope.row)"
 | 
			
		||||
                     v-hasPermi="['bpm:oa-leave:query']">详情</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleProcessDetail(scope.row)">审批进度</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { getLeavePage } from "@/api/bpm/leave"
 | 
			
		||||
import { getDictDatas, DICT_TYPE } from '@/utils/dict'
 | 
			
		||||
import {cancelProcessInstance} from "@/api/bpm/processInstance";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "BpmOALeave",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 请假申请列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        result: null,
 | 
			
		||||
        type: null,
 | 
			
		||||
        reason: null,
 | 
			
		||||
        createTime: []
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      leaveTypeDictData: getDictDatas(DICT_TYPE.BPM_OA_LEAVE_TYPE),
 | 
			
		||||
      leaveResultData: getDictDatas(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT),
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getLeavePage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.$router.push({ name: "BpmOALeaveCreate"});
 | 
			
		||||
    },
 | 
			
		||||
    /** 详情按钮操作 */
 | 
			
		||||
    handleDetail(row) {
 | 
			
		||||
      this.$router.push({ name: "BpmOALeaveDetail", query: { id: row.id}});
 | 
			
		||||
    },
 | 
			
		||||
    /** 查看审批进度的操作 */
 | 
			
		||||
    handleProcessDetail(row) {
 | 
			
		||||
      this.$router.push({ name: "BpmProcessInstanceDetail", query: { id: row.processInstanceId}});
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消请假 */
 | 
			
		||||
    handleCancel(row) {
 | 
			
		||||
      const id = row.processInstanceId;
 | 
			
		||||
      this.$prompt('请输入取消原因?', "取消流程", {
 | 
			
		||||
        type: 'warning',
 | 
			
		||||
        confirmButtonText: "确定",
 | 
			
		||||
        cancelButtonText: "取消",
 | 
			
		||||
        inputPattern: /^[\s\S]*.*\S[\s\S]*$/, // 判断非空,且非空格
 | 
			
		||||
        inputErrorMessage: "取消原因不能为空",
 | 
			
		||||
      }).then(({ value }) => {
 | 
			
		||||
        return cancelProcessInstance(id, value);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("取消成功");
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,168 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <!-- 第一步,通过流程定义的列表,选择对应的流程 -->
 | 
			
		||||
    <div v-if="!selectProcessInstance">
 | 
			
		||||
      <el-table v-loading="loading" :data="list">
 | 
			
		||||
        <el-table-column label="流程名称" align="center" prop="name" width="200">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <el-button type="text" @click="handleBpmnDetail(scope.row)">
 | 
			
		||||
              <span>{{ scope.row.name }}</span>
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="流程分类" align="center" prop="category" width="100">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <dict-tag :type="DICT_TYPE.BPM_MODEL_CATEGORY" :value="scope.row.category" />
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="流程版本" align="center" prop="processDefinition.version" width="80">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <el-tag size="medium" v-if="scope.row">v{{ scope.row.version }}</el-tag>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="流程描述" align="center" prop="description" width="300" show-overflow-tooltip />
 | 
			
		||||
        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <el-button type="text" size="small" icon="el-icon-plus" @click="handleSelect(scope.row)">选择</el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
      </el-table>
 | 
			
		||||
    </div>
 | 
			
		||||
    <!-- 第二步,填写表单,进行流程的提交 -->
 | 
			
		||||
    <div v-else>
 | 
			
		||||
      <el-card class="box-card" >
 | 
			
		||||
        <div slot="header" class="clearfix">
 | 
			
		||||
          <span class="el-icon-document">申请信息【{{ selectProcessInstance.name }}】</span>
 | 
			
		||||
          <el-button style="float: right;" type="primary" @click="selectProcessInstance = undefined">选择其它流程</el-button>
 | 
			
		||||
        </div>
 | 
			
		||||
        <el-col :span="16" :offset="6">
 | 
			
		||||
          <div>
 | 
			
		||||
            <parser :key="new Date().getTime()" :form-conf="detailForm" @submit="submitForm" />
 | 
			
		||||
          </div>
 | 
			
		||||
        </el-col>
 | 
			
		||||
      </el-card>
 | 
			
		||||
      <el-card class="box-card">
 | 
			
		||||
        <div slot="header" class="clearfix">
 | 
			
		||||
          <span class="el-icon-picture-outline">流程图</span>
 | 
			
		||||
        </div>
 | 
			
		||||
        <my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" />
 | 
			
		||||
      </el-card>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {getProcessDefinitionBpmnXML, getProcessDefinitionList} from "@/api/bpm/definition";
 | 
			
		||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
 | 
			
		||||
import {decodeFields} from "@/utils/formGenerator";
 | 
			
		||||
import Parser from '@/components/parser/Parser'
 | 
			
		||||
import {createProcessInstance} from "@/api/bpm/processInstance";
 | 
			
		||||
 | 
			
		||||
// 流程实例的发起
 | 
			
		||||
export default {
 | 
			
		||||
  name: "ProcessInstanceCreate",
 | 
			
		||||
  components: {
 | 
			
		||||
    Parser
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 表格数据
 | 
			
		||||
      list: [],
 | 
			
		||||
 | 
			
		||||
      // 流程表单详情
 | 
			
		||||
      detailForm: {
 | 
			
		||||
        fields: []
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      // BPMN 数据
 | 
			
		||||
      bpmnXML: null,
 | 
			
		||||
      bpmnControlForm: {
 | 
			
		||||
        prefix: "flowable"
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      // 流程表单
 | 
			
		||||
      selectProcessInstance: undefined, // 选择的流程实例
 | 
			
		||||
 | 
			
		||||
      // 数据字典
 | 
			
		||||
      categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY),
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询流程定义列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      getProcessDefinitionList({
 | 
			
		||||
        suspensionState: 1
 | 
			
		||||
      }).then(response => {
 | 
			
		||||
          this.list = response.data
 | 
			
		||||
          this.loading = false
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
    },
 | 
			
		||||
    /** 处理选择流程的按钮操作 **/
 | 
			
		||||
    handleSelect(row) {
 | 
			
		||||
      // 设置选择的流程
 | 
			
		||||
      this.selectProcessInstance = row;
 | 
			
		||||
 | 
			
		||||
      // 流程表单
 | 
			
		||||
      if (row.formId) {
 | 
			
		||||
        // 设置对应的表单
 | 
			
		||||
        this.detailForm = {
 | 
			
		||||
          ...JSON.parse(row.formConf),
 | 
			
		||||
          fields: decodeFields(row.formFields)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 加载流程图
 | 
			
		||||
        getProcessDefinitionBpmnXML(row.id).then(response => {
 | 
			
		||||
          this.bpmnXML = response.data
 | 
			
		||||
        })
 | 
			
		||||
      } else if (row.formCustomCreatePath) {
 | 
			
		||||
        this.$router.push({ path: row.formCustomCreatePath});
 | 
			
		||||
        // 这里暂时无需加载流程图,因为跳出到另外个 Tab;
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm(params) {
 | 
			
		||||
      if (!params) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      // 设置表单禁用
 | 
			
		||||
      const conf = params.conf;
 | 
			
		||||
      conf.disabled = true; // 表单禁用
 | 
			
		||||
      conf.formBtns = false; // 按钮隐藏
 | 
			
		||||
 | 
			
		||||
      // 提交表单,创建流程
 | 
			
		||||
      const variables = params.values;
 | 
			
		||||
      createProcessInstance({
 | 
			
		||||
        processDefinitionId: this.selectProcessInstance.id,
 | 
			
		||||
        variables: variables
 | 
			
		||||
      }).then(response => {
 | 
			
		||||
        this.$modal.msgSuccess("发起流程成功");
 | 
			
		||||
        // 关闭当前窗口
 | 
			
		||||
        this.$tab.closeOpenPage();
 | 
			
		||||
        this.$router.go(-1);
 | 
			
		||||
      }).catch(() => {
 | 
			
		||||
        conf.disabled = false; // 表单开启
 | 
			
		||||
        conf.formBtns = true; // 按钮展示
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
.my-process-designer {
 | 
			
		||||
  height: calc(100vh - 200px);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.box-card {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  margin-bottom: 20px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,400 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <!-- 审批信息 -->
 | 
			
		||||
    <el-card class="box-card" v-loading="processInstanceLoading" v-for="(item, index) in runningTasks" :key="index">
 | 
			
		||||
      <div slot="header" class="clearfix">
 | 
			
		||||
        <span class="el-icon-picture-outline">审批任务【{{ item.name }}】</span>
 | 
			
		||||
      </div>
 | 
			
		||||
      <el-col :span="16" :offset="6" >
 | 
			
		||||
        <el-form :ref="'form' + index" :model="auditForms[index]" :rules="auditRule" label-width="100px">
 | 
			
		||||
          <el-form-item label="流程名" v-if="processInstance && processInstance.name">
 | 
			
		||||
            {{ processInstance.name }}
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label="流程发起人" v-if="processInstance && processInstance.startUser">
 | 
			
		||||
            {{ processInstance.startUser.nickname }}
 | 
			
		||||
            <el-tag type="info" size="mini">{{ processInstance.startUser.deptName }}</el-tag>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label="审批建议" prop="reason">
 | 
			
		||||
            <el-input type="textarea" v-model="auditForms[index].reason" placeholder="请输入审批建议" />
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </el-form>
 | 
			
		||||
        <div style="margin-left: 10%; margin-bottom: 20px; font-size: 14px;">
 | 
			
		||||
          <el-button  icon="el-icon-edit-outline" type="success" size="mini" @click="handleAudit(item, true)">通过</el-button>
 | 
			
		||||
          <el-button  icon="el-icon-circle-close" type="danger" size="mini" @click="handleAudit(item, false)">不通过</el-button>
 | 
			
		||||
          <el-button  icon="el-icon-edit-outline" type="primary" size="mini" @click="handleUpdateAssignee(item)">转办</el-button>
 | 
			
		||||
          <el-button icon="el-icon-edit-outline" type="primary" size="mini" @click="handleDelegate(item)">委派</el-button>
 | 
			
		||||
          <el-button icon="el-icon-refresh-left" type="warning" size="mini" @click="handleBack(item)">退回</el-button>
 | 
			
		||||
        </div>
 | 
			
		||||
      </el-col>
 | 
			
		||||
    </el-card>
 | 
			
		||||
    <!-- 申请信息 -->
 | 
			
		||||
    <el-card class="box-card" v-loading="processInstanceLoading">
 | 
			
		||||
      <div slot="header" class="clearfix">
 | 
			
		||||
        <span class="el-icon-document">申请信息【{{ processInstance.name }}】</span>
 | 
			
		||||
      </div>
 | 
			
		||||
      <el-col v-if="this.processInstance.processDefinition && this.processInstance.processDefinition.formType === 10"
 | 
			
		||||
              :span="16" :offset="6">
 | 
			
		||||
        <div >
 | 
			
		||||
          <parser :key="new Date().getTime()" :form-conf="detailForm" />
 | 
			
		||||
        </div>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <div v-if="this.processInstance.processDefinition && this.processInstance.processDefinition.formType === 20">
 | 
			
		||||
        <async-biz-form-component :id="this.processInstance.businessKey"></async-biz-form-component>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-card>
 | 
			
		||||
 | 
			
		||||
    <!-- 审批记录 -->
 | 
			
		||||
    <el-card class="box-card" v-loading="tasksLoad">
 | 
			
		||||
      <div slot="header" class="clearfix">
 | 
			
		||||
        <span class="el-icon-picture-outline">审批记录</span>
 | 
			
		||||
      </div>
 | 
			
		||||
      <el-col :span="16" :offset="4" >
 | 
			
		||||
        <div class="block">
 | 
			
		||||
          <el-timeline>
 | 
			
		||||
            <el-timeline-item v-for="(item, index) in tasks" :key="index"
 | 
			
		||||
                              :icon="getTimelineItemIcon(item)" :type="getTimelineItemType(item)">
 | 
			
		||||
              <p style="font-weight: 700">任务:{{ item.name }}</p>
 | 
			
		||||
              <el-card :body-style="{ padding: '10px' }">
 | 
			
		||||
                <label v-if="item.assigneeUser" style="font-weight: normal; margin-right: 30px;">
 | 
			
		||||
                  审批人:{{ item.assigneeUser.nickname }}
 | 
			
		||||
                  <el-tag type="info" size="mini">{{ item.assigneeUser.deptName }}</el-tag>
 | 
			
		||||
                </label>
 | 
			
		||||
                <label style="font-weight: normal" v-if="item.createTime">创建时间:</label>
 | 
			
		||||
                <label style="color:#8a909c; font-weight: normal">{{ parseTime(item.createTime) }}</label>
 | 
			
		||||
                <label v-if="item.endTime" style="margin-left: 30px;font-weight: normal">审批时间:</label>
 | 
			
		||||
                <label v-if="item.endTime" style="color:#8a909c;font-weight: normal"> {{ parseTime(item.endTime) }}</label>
 | 
			
		||||
                <label v-if="item.durationInMillis" style="margin-left: 30px;font-weight: normal">耗时:</label>
 | 
			
		||||
                <label v-if="item.durationInMillis" style="color:#8a909c;font-weight: normal"> {{ getDateStar(item.durationInMillis) }} </label>
 | 
			
		||||
                <p v-if="item.reason">
 | 
			
		||||
                  <el-tag :type="getTimelineItemType(item)">{{ item.reason }}</el-tag>
 | 
			
		||||
                </p>
 | 
			
		||||
              </el-card>
 | 
			
		||||
            </el-timeline-item>
 | 
			
		||||
          </el-timeline>
 | 
			
		||||
        </div>
 | 
			
		||||
      </el-col>
 | 
			
		||||
    </el-card>
 | 
			
		||||
 | 
			
		||||
    <!-- 高亮流程图 -->
 | 
			
		||||
    <el-card class="box-card" v-loading="processInstanceLoading">
 | 
			
		||||
      <div slot="header" class="clearfix">
 | 
			
		||||
        <span class="el-icon-picture-outline">流程图</span>
 | 
			
		||||
      </div>
 | 
			
		||||
      <my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" :activityData="activityList"
 | 
			
		||||
            :processInstanceData="processInstance" :taskData="tasks" />
 | 
			
		||||
    </el-card>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(转派审批人) -->
 | 
			
		||||
    <el-dialog title="转派审批人" :visible.sync="updateAssignee.open" width="500px" append-to-body>
 | 
			
		||||
      <el-form ref="updateAssigneeForm" :model="updateAssignee.form" :rules="updateAssignee.rules" label-width="110px">
 | 
			
		||||
        <el-form-item label="新审批人" prop="assigneeUserId">
 | 
			
		||||
          <el-select v-model="updateAssignee.form.assigneeUserId" clearable style="width: 100%">
 | 
			
		||||
            <el-option v-for="item in userOptions" :key="item.id" :label="item.nickname" :value="item.id" />
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitUpdateAssigneeForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancelUpdateAssigneeForm">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {getProcessDefinitionBpmnXML} from "@/api/bpm/definition";
 | 
			
		||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
 | 
			
		||||
import store from "@/store";
 | 
			
		||||
import {decodeFields} from "@/utils/formGenerator";
 | 
			
		||||
import Parser from '@/components/parser/Parser'
 | 
			
		||||
import {getProcessInstance} from "@/api/bpm/processInstance";
 | 
			
		||||
import {approveTask, getTaskListByProcessInstanceId, rejectTask, updateTaskAssignee} from "@/api/bpm/task";
 | 
			
		||||
import {getDate} from "@/utils/dateUtils";
 | 
			
		||||
import {listSimpleUsers} from "@/api/system/user";
 | 
			
		||||
import {getActivityList} from "@/api/bpm/activity";
 | 
			
		||||
import Vue from "vue";
 | 
			
		||||
 | 
			
		||||
// 流程实例的详情页,可用于审批
 | 
			
		||||
export default {
 | 
			
		||||
  name: "ProcessInstanceDetail",
 | 
			
		||||
  components: {
 | 
			
		||||
    Parser
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      processInstanceLoading: true,
 | 
			
		||||
      // 流程实例
 | 
			
		||||
      id: undefined, // 流程实例的编号
 | 
			
		||||
      processInstance: {},
 | 
			
		||||
 | 
			
		||||
      // 流程表单详情
 | 
			
		||||
      detailForm: {
 | 
			
		||||
        fields: []
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      // BPMN 数据
 | 
			
		||||
      bpmnXML: null,
 | 
			
		||||
      bpmnControlForm: {
 | 
			
		||||
        prefix: "flowable"
 | 
			
		||||
      },
 | 
			
		||||
      activityList: [],
 | 
			
		||||
 | 
			
		||||
      // 审批记录
 | 
			
		||||
      tasksLoad: true,
 | 
			
		||||
      tasks: [],
 | 
			
		||||
 | 
			
		||||
      // 审批表单
 | 
			
		||||
      runningTasks: [],
 | 
			
		||||
      auditForms: [],
 | 
			
		||||
      auditRule: {
 | 
			
		||||
        reason: [{ required: true, message: "审批建议不能为空", trigger: "blur" }],
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      // 转派审批人
 | 
			
		||||
      userOptions: [],
 | 
			
		||||
      updateAssignee: {
 | 
			
		||||
        open: false,
 | 
			
		||||
        form: {
 | 
			
		||||
          assigneeUserId: undefined,
 | 
			
		||||
        },
 | 
			
		||||
        rules: {
 | 
			
		||||
          assigneeUserId: [{ required: true, message: "新审批人不能为空", trigger: "change" }],
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.id = this.$route.query.id;
 | 
			
		||||
    if (!this.id) {
 | 
			
		||||
      this.$message.error('未传递 id 参数,无法查看流程信息');
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    this.getDetail();
 | 
			
		||||
 | 
			
		||||
    // 获得用户列表
 | 
			
		||||
    this.userOptions = [];
 | 
			
		||||
    listSimpleUsers().then(response => {
 | 
			
		||||
      this.userOptions.push(...response.data);
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 获得流程实例 */
 | 
			
		||||
    getDetail() {
 | 
			
		||||
      // 获得流程实例相关
 | 
			
		||||
      this.processInstanceLoading = true;
 | 
			
		||||
      getProcessInstance(this.id).then(response => {
 | 
			
		||||
        if (!response.data) {
 | 
			
		||||
          this.$message.error('查询不到流程信息!');
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 设置流程信息
 | 
			
		||||
        this.processInstance = response.data;
 | 
			
		||||
 | 
			
		||||
        //将业务表单,注册为动态组件
 | 
			
		||||
        const path = this.processInstance.processDefinition.formCustomViewPath;
 | 
			
		||||
        Vue.component("async-biz-form-component", function(resolve) {
 | 
			
		||||
          require([`@/views${path}`], resolve);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // 设置表单信息
 | 
			
		||||
        if (this.processInstance.processDefinition.formType === 10) {
 | 
			
		||||
          this.detailForm = {
 | 
			
		||||
            ...JSON.parse(this.processInstance.processDefinition.formConf),
 | 
			
		||||
            disabled: true, // 表单禁用
 | 
			
		||||
            formBtns: false, // 按钮隐藏
 | 
			
		||||
            fields: decodeFields(this.processInstance.processDefinition.formFields)
 | 
			
		||||
          }
 | 
			
		||||
          // 设置表单的值
 | 
			
		||||
          this.detailForm.fields.forEach(item => {
 | 
			
		||||
            const val = this.processInstance.formVariables[item.__vModel__]
 | 
			
		||||
            if (val) {
 | 
			
		||||
              item.__config__.defaultValue = val
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 加载流程图
 | 
			
		||||
        getProcessDefinitionBpmnXML(this.processInstance.processDefinition.id).then(response => {
 | 
			
		||||
          this.bpmnXML = response.data
 | 
			
		||||
        });
 | 
			
		||||
        // 加载活动列表
 | 
			
		||||
        getActivityList({
 | 
			
		||||
          processInstanceId: this.processInstance.id
 | 
			
		||||
        }).then(response => {
 | 
			
		||||
          this.activityList = response.data;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // 取消加载中
 | 
			
		||||
        this.processInstanceLoading = false;
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      // 获得流程任务列表(审批记录)
 | 
			
		||||
      this.tasksLoad = true;
 | 
			
		||||
      this.runningTasks = [];
 | 
			
		||||
      this.auditForms = [];
 | 
			
		||||
      getTaskListByProcessInstanceId(this.id).then(response => {
 | 
			
		||||
        // 审批记录
 | 
			
		||||
        this.tasks = [];
 | 
			
		||||
        // 移除已取消的审批
 | 
			
		||||
        response.data.forEach(task => {
 | 
			
		||||
          if (task.result !== 4) {
 | 
			
		||||
            this.tasks.push(task);
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
        // 排序,将未完成的排在前面,已完成的排在后面;
 | 
			
		||||
        this.tasks.sort((a, b) => {
 | 
			
		||||
          // 有已完成的情况,按照完成时间倒序
 | 
			
		||||
          if (a.endTime && b.endTime) {
 | 
			
		||||
            return b.endTime - a.endTime;
 | 
			
		||||
          } else if (a.endTime) {
 | 
			
		||||
            return 1;
 | 
			
		||||
          } else if (b.endTime) {
 | 
			
		||||
            return -1;
 | 
			
		||||
            // 都是未完成,按照创建时间倒序
 | 
			
		||||
          } else {
 | 
			
		||||
            return b.createTime - a.createTime;
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // 需要审核的记录
 | 
			
		||||
        const userId = store.getters.userId;
 | 
			
		||||
        this.tasks.forEach(task => {
 | 
			
		||||
          if (task.result !== 1) { // 只有待处理才需要
 | 
			
		||||
            return;
 | 
			
		||||
          }
 | 
			
		||||
          if (!task.assigneeUser || task.assigneeUser.id !== userId) { // 自己不是处理人
 | 
			
		||||
            return;
 | 
			
		||||
          }
 | 
			
		||||
          this.runningTasks.push({...task});
 | 
			
		||||
          this.auditForms.push({
 | 
			
		||||
            reason: ''
 | 
			
		||||
          })
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // 取消加载中
 | 
			
		||||
        this.tasksLoad = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    getDateStar(ms) {
 | 
			
		||||
      return getDate(ms);
 | 
			
		||||
    },
 | 
			
		||||
    getTimelineItemIcon(item) {
 | 
			
		||||
      if (item.result === 1) {
 | 
			
		||||
        return 'el-icon-time';
 | 
			
		||||
      }
 | 
			
		||||
      if (item.result === 2) {
 | 
			
		||||
        return 'el-icon-check';
 | 
			
		||||
      }
 | 
			
		||||
      if (item.result === 3) {
 | 
			
		||||
        return 'el-icon-close';
 | 
			
		||||
      }
 | 
			
		||||
      if (item.result === 4) {
 | 
			
		||||
        return 'el-icon-remove-outline';
 | 
			
		||||
      }
 | 
			
		||||
      return '';
 | 
			
		||||
    },
 | 
			
		||||
    getTimelineItemType(item) {
 | 
			
		||||
      if (item.result === 1) {
 | 
			
		||||
        return 'primary';
 | 
			
		||||
      }
 | 
			
		||||
      if (item.result === 2) {
 | 
			
		||||
        return 'success';
 | 
			
		||||
      }
 | 
			
		||||
      if (item.result === 3) {
 | 
			
		||||
        return 'danger';
 | 
			
		||||
      }
 | 
			
		||||
      if (item.result === 4) {
 | 
			
		||||
        return 'info';
 | 
			
		||||
      }
 | 
			
		||||
      return '';
 | 
			
		||||
    },
 | 
			
		||||
    /** 处理审批通过和不通过的操作 */
 | 
			
		||||
    handleAudit(task, pass) {
 | 
			
		||||
      const index = this.runningTasks.indexOf(task);
 | 
			
		||||
      this.$refs['form' + index][0].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        const data = {
 | 
			
		||||
          id: task.id,
 | 
			
		||||
          reason: this.auditForms[index].reason
 | 
			
		||||
        }
 | 
			
		||||
        if (pass) {
 | 
			
		||||
          approveTask(data).then(response => {
 | 
			
		||||
            this.$modal.msgSuccess("审批通过成功!");
 | 
			
		||||
            this.getDetail(); // 获得最新详情
 | 
			
		||||
          });
 | 
			
		||||
        } else {
 | 
			
		||||
          rejectTask(data).then(response => {
 | 
			
		||||
            this.$modal.msgSuccess("审批不通过成功!");
 | 
			
		||||
            this.getDetail(); // 获得最新详情
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 处理转派审批人 */
 | 
			
		||||
    handleUpdateAssignee(task) {
 | 
			
		||||
      // 设置表单
 | 
			
		||||
      this.resetUpdateAssigneeForm();
 | 
			
		||||
      this.updateAssignee.form.id = task.id;
 | 
			
		||||
      // 设置为打开
 | 
			
		||||
      this.updateAssignee.open = true;
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交转派审批人 */
 | 
			
		||||
    submitUpdateAssigneeForm() {
 | 
			
		||||
      this.$refs['updateAssigneeForm'].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        updateTaskAssignee(this.updateAssignee.form).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("转派任务成功!");
 | 
			
		||||
          this.updateAssignee.open = false;
 | 
			
		||||
          this.getDetail(); // 获得最新详情
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消转派审批人 */
 | 
			
		||||
    cancelUpdateAssigneeForm() {
 | 
			
		||||
      this.updateAssignee.open = false;
 | 
			
		||||
      this.resetUpdateAssigneeForm();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置转派审批人 */
 | 
			
		||||
    resetUpdateAssigneeForm() {
 | 
			
		||||
      this.updateAssignee.form = {
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        assigneeUserId: undefined,
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("updateAssigneeForm");
 | 
			
		||||
    },
 | 
			
		||||
    /** 处理审批退回的操作 */
 | 
			
		||||
    handleDelegate(task) {
 | 
			
		||||
      this.$modal.msgError("暂不支持【委派】功能,可以使用【转派】替代!");
 | 
			
		||||
    },
 | 
			
		||||
    /** 处理审批退回的操作 */
 | 
			
		||||
    handleBack(task) {
 | 
			
		||||
      this.$modal.msgError("暂不支持【退回】功能!");
 | 
			
		||||
      // 可参考 http://blog.wya1.com/article/636697030/details/7296
 | 
			
		||||
      // const data = {
 | 
			
		||||
      //   id: task.id,
 | 
			
		||||
      //   assigneeUserId: 1
 | 
			
		||||
      // }
 | 
			
		||||
      // backTask(data).then(response => {
 | 
			
		||||
      //   this.$modal.msgSuccess("回退成功!");
 | 
			
		||||
      //   this.getDetail(); // 获得最新详情
 | 
			
		||||
      // });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
.my-process-designer {
 | 
			
		||||
  height: calc(100vh - 200px);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.box-card {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  margin-bottom: 20px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,182 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="流程名" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入流程名" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="所属流程" prop="processDefinitionId">
 | 
			
		||||
        <el-input v-model="queryParams.processDefinitionId" placeholder="请输入流程定义的编号" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="流程分类" prop="category">
 | 
			
		||||
        <el-select v-model="queryParams.category" placeholder="请选择流程分类" clearable>
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY)"
 | 
			
		||||
                     :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="提交时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="状态" prop="status">
 | 
			
		||||
        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS)"
 | 
			
		||||
                     :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="结果" prop="result">
 | 
			
		||||
        <el-select v-model="queryParams.result" placeholder="请选择流结果" clearable>
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT)"
 | 
			
		||||
                     :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['bpm:process-instance:query']">发起流程</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="编号" align="center" prop="id" width="320" />
 | 
			
		||||
      <el-table-column label="流程名" align="center" prop="name" />
 | 
			
		||||
      <el-table-column label="流程分类" align="center" prop="category">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.BPM_MODEL_CATEGORY" :value="scope.row.category" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="当前审批任务" align="center" prop="tasks">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button v-for="task in scope.row.tasks" :key="task.id" type="text"">
 | 
			
		||||
            <span>{{ task.name }}</span>
 | 
			
		||||
          </el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="状态" align="center" prop="status">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS" :value="scope.row.status" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="结果" align="center" prop="result">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT" :value="scope.row.result"/>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="提交时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="结束时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.endTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button type="text" size="small" icon="el-icon-delete" v-if="scope.row.result === 1"
 | 
			
		||||
                     v-hasPermi="['bpm:process-instance:cancel']" @click="handleCancel(scope.row)">取消</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleDetail(scope.row)"
 | 
			
		||||
                     v-hasPermi="['bpm:process-instance:query']">详情</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { getMyProcessInstancePage, cancelProcessInstance } from "@/api/bpm/processInstance";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "BpmProcessInstance",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 工作流的流程实例的拓展列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        name: null,
 | 
			
		||||
        processDefinitionId: null,
 | 
			
		||||
        category: null,
 | 
			
		||||
        status: null,
 | 
			
		||||
        result: null,
 | 
			
		||||
        createTime: []
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getMyProcessInstancePage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 **/
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.$router.push({ name: "BpmProcessInstanceCreate"})
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮操作 */
 | 
			
		||||
    handleCancel(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$prompt('请输入取消原因?', "取消流程", {
 | 
			
		||||
        type: 'warning',
 | 
			
		||||
        confirmButtonText: "确定",
 | 
			
		||||
        cancelButtonText: "取消",
 | 
			
		||||
        inputPattern: /^[\s\S]*.*\S[\s\S]*$/, // 判断非空,且非空格
 | 
			
		||||
        inputErrorMessage: "取消原因不能为空",
 | 
			
		||||
      }).then(({ value }) => {
 | 
			
		||||
        return cancelProcessInstance(id, value);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("取消成功");
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    /** 处理详情按钮 */
 | 
			
		||||
    handleDetail(row) {
 | 
			
		||||
      this.$router.push({ name: "BpmProcessInstanceDetail", query: { id: row.id}});
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,120 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="流程名" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入流程名" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="任务编号" align="center" prop="id" width="320" fixed />
 | 
			
		||||
      <el-table-column label="任务名称" align="center" prop="name" width="200" />
 | 
			
		||||
      <el-table-column label="所属流程" align="center" prop="processInstance.name" width="200" />
 | 
			
		||||
      <el-table-column label="流程发起人" align="center" prop="processInstance.startUserNickname" width="120" />
 | 
			
		||||
      <el-table-column label="结果" align="center" prop="result">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT" :value="scope.row.result"/>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="审批意见" align="center" prop="reason" width="200" />
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="审批时间" align="center" prop="endTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.endTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="耗时" align="center" prop="durationInMillis" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ getDateStar(scope.row.durationInMillis) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleAudit(scope.row)"
 | 
			
		||||
                     v-hasPermi="['bpm:task:query']">详情</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {getDoneTaskPage} from '@/api/bpm/task'
 | 
			
		||||
import {getDate} from "@/utils/dateUtils";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "BpmDoneTask",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 已办任务列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        name: null,
 | 
			
		||||
        createTime: []
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      getDoneTaskPage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    getDateStar(ms) {
 | 
			
		||||
      return getDate(ms);
 | 
			
		||||
    },
 | 
			
		||||
    /** 处理审批按钮 */
 | 
			
		||||
    handleAudit(row) {
 | 
			
		||||
      this.$router.push({ name: "BpmProcessInstanceDetail", query: { id: row.processInstance.id}});
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,107 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="工作流" url="https://doc.iocoder.cn/bpm" />
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="流程名" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入流程名" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="任务编号" align="center" prop="id" width="320" />
 | 
			
		||||
      <el-table-column label="任务名称" align="center" prop="name" />
 | 
			
		||||
      <el-table-column label="所属流程" align="center" prop="processInstance.name" />
 | 
			
		||||
      <el-table-column label="流程发起人" align="center" prop="processInstance.startUserNickname" />
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="状态" align="center" prop="version" width="80">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-tag type="success" v-if="scope.row.suspensionState === 1">激活</el-tag>
 | 
			
		||||
          <el-tag type="warning" v-if="scope.row.suspensionState === 2">挂起</el-tag>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleAudit(scope.row)"
 | 
			
		||||
                     v-hasPermi="['bpm:task:update']">审批</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {getTodoTaskPage} from '@/api/bpm/task'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "BpmTodoTask",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 待办任务列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        name: null,
 | 
			
		||||
        createTime: []
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 处理查询参数
 | 
			
		||||
      getTodoTaskPage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 处理审批按钮 */
 | 
			
		||||
    handleAudit(row) {
 | 
			
		||||
      this.$router.push({ name: "BpmProcessInstanceDetail", query: { id: row.processInstance.id}});
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,337 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <!-- 列表弹窗 -->
 | 
			
		||||
    <el-dialog title="任务分配规则" :visible.sync="visible" width="800px" append-to-body>
 | 
			
		||||
      <el-table v-loading="loading" :data="list">
 | 
			
		||||
        <el-table-column label="任务名" align="center" prop="taskDefinitionName" width="120" fixed />
 | 
			
		||||
        <el-table-column label="任务标识" align="center" prop="taskDefinitionKey" width="120" show-tooltip-when-overflow />
 | 
			
		||||
        <el-table-column label="规则类型" align="center" prop="type" width="120">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <dict-tag :type="DICT_TYPE.BPM_TASK_ASSIGN_RULE_TYPE" :value="scope.row.type" />
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="规则范围" align="center" prop="options" width="440px">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <el-tag size="medium" v-if="scope.row.options" :key="option" v-for="option in scope.row.options">
 | 
			
		||||
              {{ getAssignRuleOptionName(scope.row.type, option) }}
 | 
			
		||||
            </el-tag>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column v-if="modelId" label="操作" align="center" width="80" fixed="right">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdateTaskAssignRule(scope.row)"
 | 
			
		||||
                       v-hasPermi="['bpm:task-assign-rule:update']">修改</el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
      </el-table>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
    <!-- 添加/修改弹窗 -->
 | 
			
		||||
    <el-dialog title="修改任务规则" :visible.sync="open" width="500px" append-to-body>
 | 
			
		||||
      <el-form ref="taskAssignRuleForm" :model="form" :rules="rules" label-width="110px">
 | 
			
		||||
        <el-form-item label="任务名称" prop="taskDefinitionName">
 | 
			
		||||
          <el-input v-model="form.taskDefinitionName" disabled />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="任务标识" prop="taskDefinitionKey">
 | 
			
		||||
          <el-input v-model="form.taskDefinitionKey" disabled />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="规则类型" prop="type">
 | 
			
		||||
          <el-select v-model="form.type" clearable style="width: 100%">
 | 
			
		||||
            <el-option v-for="dict in taskAssignRuleTypeDictDatas" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.type === 10" label="指定角色" prop="roleIds">
 | 
			
		||||
          <el-select v-model="form.roleIds" multiple clearable style="width: 100%">
 | 
			
		||||
            <el-option v-for="item in roleOptions" :key="item.id" :label="item.name" :value="item.id" />
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.type === 20 || form.type === 21" label="指定部门" prop="deptIds">
 | 
			
		||||
          <treeselect v-model="form.deptIds" :options="deptTreeOptions" multiple flat :defaultExpandLevel="3"
 | 
			
		||||
                      placeholder="请选择指定部门" :normalizer="normalizer"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.type === 22" label="指定岗位" prop="postIds">
 | 
			
		||||
          <el-select v-model="form.postIds" multiple clearable style="width: 100%">
 | 
			
		||||
            <el-option v-for="item in postOptions" :key="item.id" :label="item.name" :value="item.id" />
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.type === 30 || form.type === 31 || form.type === 32" label="指定用户" prop="userIds">
 | 
			
		||||
          <el-select v-model="form.userIds" multiple clearable style="width: 100%">
 | 
			
		||||
            <el-option v-for="item in userOptions" :key="item.id" :label="item.nickname" :value="item.id" />
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.type === 40" label="指定用户组" prop="userGroupIds">
 | 
			
		||||
          <el-select v-model="form.userGroupIds" multiple clearable style="width: 100%">
 | 
			
		||||
            <el-option v-for="item in userGroupOptions" :key="item.id" :label="item.name" :value="item.id" />
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.type === 50" label="指定脚本" prop="scripts">
 | 
			
		||||
          <el-select v-model="form.scripts" multiple clearable style="width: 100%">
 | 
			
		||||
            <el-option v-for="dict in taskAssignScriptDictDatas" :key="parseInt(dict.value)"
 | 
			
		||||
                       :label="dict.label" :value="parseInt(dict.value)"/>
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitAssignRuleForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancelAssignRuleForm">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
 | 
			
		||||
import {createTaskAssignRule, getTaskAssignRuleList, updateTaskAssignRule} from "@/api/bpm/taskAssignRule";
 | 
			
		||||
import {listSimpleRoles} from "@/api/system/role";
 | 
			
		||||
import {listSimpleDepts} from "@/api/system/dept";
 | 
			
		||||
 | 
			
		||||
import Treeselect from "@riophae/vue-treeselect";
 | 
			
		||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 | 
			
		||||
import {listSimplePosts} from "@/api/system/post";
 | 
			
		||||
import {listSimpleUsers} from "@/api/system/user";
 | 
			
		||||
import {listSimpleUserGroups} from "@/api/bpm/userGroup";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "BpmTaskAssignRule",
 | 
			
		||||
  components: {
 | 
			
		||||
    Treeselect
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 如下参数,可传递
 | 
			
		||||
      modelId: undefined, // 流程模型的编号。如果 modelId 非空,则用于流程模型的查看与配置
 | 
			
		||||
      processDefinitionId: undefined, // 流程定义的编号。如果 processDefinitionId 非空,则用于流程定义的查看,不支持配置
 | 
			
		||||
      visible: false,
 | 
			
		||||
 | 
			
		||||
      // 任务分配规则表单
 | 
			
		||||
      row: undefined, // 选中的流程模型
 | 
			
		||||
      list: [], // 选中流程模型的任务分配规则们
 | 
			
		||||
      loading: false, // 加载中
 | 
			
		||||
      open: false, // 是否打开
 | 
			
		||||
      form: {}, // 表单
 | 
			
		||||
      rules: { // 表单校验规则
 | 
			
		||||
        type: [{ required: true, message: "规则类型不能为空", trigger: "change" }],
 | 
			
		||||
        roleIds: [{required: true, message: "指定角色不能为空", trigger: "change" }],
 | 
			
		||||
        deptIds: [{required: true, message: "指定部门不能为空", trigger: "change" }],
 | 
			
		||||
        postIds: [{required: true, message: "指定岗位不能为空", trigger: "change"}],
 | 
			
		||||
        userIds: [{required: true, message: "指定用户不能为空", trigger: "change"}],
 | 
			
		||||
        userGroupIds: [{required: true, message: "指定用户组不能为空", trigger: "change"}],
 | 
			
		||||
        scripts: [{required: true, message: "指定脚本不能为空", trigger: "change"}],
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      // 各种下拉框
 | 
			
		||||
      roleOptions: [],
 | 
			
		||||
      deptOptions: [],
 | 
			
		||||
      deptTreeOptions: [],
 | 
			
		||||
      postOptions: [],
 | 
			
		||||
      userOptions: [],
 | 
			
		||||
      userGroupOptions: [],
 | 
			
		||||
 | 
			
		||||
      // 数据字典
 | 
			
		||||
      modelFormTypeDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_FORM_TYPE),
 | 
			
		||||
      taskAssignRuleTypeDictDatas: getDictDatas(DICT_TYPE.BPM_TASK_ASSIGN_RULE_TYPE),
 | 
			
		||||
      taskAssignScriptDictDatas: getDictDatas(DICT_TYPE.BPM_TASK_ASSIGN_SCRIPT),
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    initModel(modelId) {
 | 
			
		||||
      this.modelId = modelId;
 | 
			
		||||
      this.processDefinitionId = undefined;
 | 
			
		||||
 | 
			
		||||
      // 初始化所有下拉框
 | 
			
		||||
      this.init0();
 | 
			
		||||
    },
 | 
			
		||||
    initProcessDefinition(processDefinitionId) {
 | 
			
		||||
      this.modelId = undefined;
 | 
			
		||||
      this.processDefinitionId = processDefinitionId;
 | 
			
		||||
 | 
			
		||||
      // 初始化所有下拉框
 | 
			
		||||
      this.init0();
 | 
			
		||||
    },
 | 
			
		||||
    /** 初始化 */
 | 
			
		||||
    init0() {
 | 
			
		||||
      // 设置可见
 | 
			
		||||
      this.visible = true;
 | 
			
		||||
      // 获得列表
 | 
			
		||||
      this.getList();
 | 
			
		||||
 | 
			
		||||
      // 获得角色列表
 | 
			
		||||
      this.roleOptions = [];
 | 
			
		||||
      listSimpleRoles().then(response => {
 | 
			
		||||
        this.roleOptions.push(...response.data);
 | 
			
		||||
      });
 | 
			
		||||
      // 获得部门列表
 | 
			
		||||
      this.deptOptions = [];
 | 
			
		||||
      this.deptTreeOptions = [];
 | 
			
		||||
      listSimpleDepts().then(response => {
 | 
			
		||||
        this.deptOptions.push(...response.data);
 | 
			
		||||
        this.deptTreeOptions.push(...this.handleTree(response.data, "id"));
 | 
			
		||||
      });
 | 
			
		||||
      // 获得岗位列表
 | 
			
		||||
      this.postOptions = [];
 | 
			
		||||
      listSimplePosts().then(response => {
 | 
			
		||||
        this.postOptions.push(...response.data);
 | 
			
		||||
      });
 | 
			
		||||
      // 获得用户列表
 | 
			
		||||
      this.userOptions = [];
 | 
			
		||||
      listSimpleUsers().then(response => {
 | 
			
		||||
        this.userOptions.push(...response.data);
 | 
			
		||||
      });
 | 
			
		||||
      // 获得用户组列表
 | 
			
		||||
      this.userGroupOptions = [];
 | 
			
		||||
      listSimpleUserGroups().then(response => {
 | 
			
		||||
        this.userGroupOptions.push(...response.data);
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 获得任务分配规则列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      getTaskAssignRuleList({
 | 
			
		||||
        modelId: this.modelId,
 | 
			
		||||
        processDefinitionId: this.processDefinitionId,
 | 
			
		||||
      }).then(response => {
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
        this.list = response.data;
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    /** 处理修改任务分配规则的按钮操作 */
 | 
			
		||||
    handleUpdateTaskAssignRule(row) {
 | 
			
		||||
      // 先重置标识
 | 
			
		||||
      this.resetAssignRuleForm();
 | 
			
		||||
      // 设置表单
 | 
			
		||||
      this.form = {
 | 
			
		||||
        ...row,
 | 
			
		||||
        options: [],
 | 
			
		||||
        roleIds: [],
 | 
			
		||||
        deptIds: [],
 | 
			
		||||
        postIds: [],
 | 
			
		||||
        userIds: [],
 | 
			
		||||
        userGroupIds: [],
 | 
			
		||||
        scripts: [],
 | 
			
		||||
      };
 | 
			
		||||
      // 将 options 赋值到对应的 roleIds 等选项
 | 
			
		||||
      if (row.type === 10) {
 | 
			
		||||
        this.form.roleIds.push(...row.options);
 | 
			
		||||
      } else if (row.type === 20 || row.type === 21) {
 | 
			
		||||
        this.form.deptIds.push(...row.options);
 | 
			
		||||
      } else if (row.type === 22) {
 | 
			
		||||
        this.form.postIds.push(...row.options);
 | 
			
		||||
      } else if (row.type === 30 || row.type === 31 || row.type === 32) {
 | 
			
		||||
        this.form.userIds.push(...row.options);
 | 
			
		||||
      } else if (row.type === 40) {
 | 
			
		||||
        this.form.userGroupIds.push(...row.options);
 | 
			
		||||
      } else if (row.type === 50) {
 | 
			
		||||
        this.form.scripts.push(...row.options);
 | 
			
		||||
      }
 | 
			
		||||
      this.open = true;
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交任务分配规则的表单 */
 | 
			
		||||
    submitAssignRuleForm() {
 | 
			
		||||
      this.$refs["taskAssignRuleForm"].validate(valid => {
 | 
			
		||||
        if (valid) {
 | 
			
		||||
          // 构建表单
 | 
			
		||||
          let form = {
 | 
			
		||||
            ...this.form,
 | 
			
		||||
            taskDefinitionName: undefined,
 | 
			
		||||
          };
 | 
			
		||||
          // 将 roleIds 等选项赋值到 options 中
 | 
			
		||||
          if (form.type === 10) {
 | 
			
		||||
            form.options = form.roleIds;
 | 
			
		||||
          } else if (form.type === 20 || form.type === 21) {
 | 
			
		||||
            form.options = form.deptIds;
 | 
			
		||||
          } else if (form.type === 22) {
 | 
			
		||||
            form.options = form.postIds;
 | 
			
		||||
          } else if (form.type === 30 || form.type === 31 || form.type === 32) {
 | 
			
		||||
            form.options = form.userIds;
 | 
			
		||||
          } else if (form.type === 40) {
 | 
			
		||||
            form.options = form.userGroupIds;
 | 
			
		||||
          } else if (form.type === 50) {
 | 
			
		||||
            form.options = form.scripts;
 | 
			
		||||
          }
 | 
			
		||||
          form.roleIds = undefined;
 | 
			
		||||
          form.deptIds = undefined;
 | 
			
		||||
          form.postIds = undefined;
 | 
			
		||||
          form.userIds = undefined;
 | 
			
		||||
          form.userGroupIds = undefined;
 | 
			
		||||
          form.scripts = undefined;
 | 
			
		||||
          // 新增
 | 
			
		||||
          if (!form.id) {
 | 
			
		||||
            form.modelId = this.modelId; // 模型编号
 | 
			
		||||
            createTaskAssignRule(form).then(response => {
 | 
			
		||||
              this.$modal.msgSuccess("修改成功");
 | 
			
		||||
              this.open = false;
 | 
			
		||||
              this.getList();
 | 
			
		||||
            });
 | 
			
		||||
            // 修改
 | 
			
		||||
          } else {
 | 
			
		||||
            form.taskDefinitionKey = undefined; // 无法修改
 | 
			
		||||
            updateTaskAssignRule(form).then(response => {
 | 
			
		||||
              this.$modal.msgSuccess("修改成功");
 | 
			
		||||
              this.open = false;
 | 
			
		||||
              this.getList();
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消任务分配规则的表单 */
 | 
			
		||||
    cancelAssignRuleForm() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.resetAssignRuleForm();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    resetAssignRuleForm() {
 | 
			
		||||
      this.form = {};
 | 
			
		||||
      this.resetForm("taskAssignRuleForm");
 | 
			
		||||
    },
 | 
			
		||||
    getAssignRuleOptionName(type, option) {
 | 
			
		||||
      if (type === 10) {
 | 
			
		||||
        for (const roleOption of this.roleOptions) {
 | 
			
		||||
          if (roleOption.id === option) {
 | 
			
		||||
            return roleOption.name;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      } else if (type === 20 || type === 21) {
 | 
			
		||||
        for (const deptOption of this.deptOptions) {
 | 
			
		||||
          if (deptOption.id === option) {
 | 
			
		||||
            return deptOption.name;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      } else if (type === 22) {
 | 
			
		||||
        for (const postOption of this.postOptions) {
 | 
			
		||||
          if (postOption.id === option) {
 | 
			
		||||
            return postOption.name;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      } else if (type === 30 || type === 31 || type === 32) {
 | 
			
		||||
        for (const userOption of this.userOptions) {
 | 
			
		||||
          if (userOption.id === option) {
 | 
			
		||||
            return userOption.nickname;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      } else if (type === 40) {
 | 
			
		||||
        for (const userGroupOption of this.userGroupOptions) {
 | 
			
		||||
          if (userGroupOption.id === option) {
 | 
			
		||||
            return userGroupOption.name;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      } else if (type === 50) {
 | 
			
		||||
        option = option + ''; // 转换成 string
 | 
			
		||||
        for (const dictData of this.taskAssignScriptDictDatas) {
 | 
			
		||||
          if (dictData.value === option) {
 | 
			
		||||
            return dictData.label;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      return '未知(' + option + ')';
 | 
			
		||||
    },
 | 
			
		||||
    // 格式化部门的下拉框
 | 
			
		||||
    normalizer(node) {
 | 
			
		||||
      return {
 | 
			
		||||
        id: node.id,
 | 
			
		||||
        label: node.name,
 | 
			
		||||
        children: node.children
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -2,42 +2,18 @@
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <search-bar
 | 
			
		||||
      :formConfigs="formConfig"
 | 
			
		||||
      ref="searchBarForm"
 | 
			
		||||
      @headBtnClick="buttonClick"
 | 
			
		||||
    />
 | 
			
		||||
    <search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <base-table
 | 
			
		||||
      :page="queryParams.pageNo"
 | 
			
		||||
      :limit="queryParams.pageSize"
 | 
			
		||||
      :table-props="tableProps"
 | 
			
		||||
      :table-data="list"
 | 
			
		||||
      :max-height="tableH"
 | 
			
		||||
    >
 | 
			
		||||
      <method-btn
 | 
			
		||||
        v-if="tableBtn.length"
 | 
			
		||||
        slot="handleBtn"
 | 
			
		||||
        :width="80"
 | 
			
		||||
        label="操作"
 | 
			
		||||
        :method-list="tableBtn"
 | 
			
		||||
        @clickBtn="handleClick"
 | 
			
		||||
      />
 | 
			
		||||
    <base-table :page="queryParams.pageNo" :limit="queryParams.pageSize" :table-props="tableProps" :table-data="list"
 | 
			
		||||
      :max-height="tableH">
 | 
			
		||||
      <method-btn v-if="tableBtn.length" slot="handleBtn" :width="80" label="操作" :method-list="tableBtn"
 | 
			
		||||
        @clickBtn="handleClick" />
 | 
			
		||||
    </base-table>
 | 
			
		||||
    <pagination
 | 
			
		||||
      :page.sync="queryParams.pageNo"
 | 
			
		||||
      :limit.sync="queryParams.pageSize"
 | 
			
		||||
      :total="total"
 | 
			
		||||
      @pagination="getList"
 | 
			
		||||
    />
 | 
			
		||||
    <pagination :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" :total="total"
 | 
			
		||||
      @pagination="getList" />
 | 
			
		||||
    <!-- 新增 -->
 | 
			
		||||
    <base-dialog
 | 
			
		||||
      :dialogTitle="addOrEditTitle"
 | 
			
		||||
      :dialogVisible="centervisible"
 | 
			
		||||
      @cancel="handleCancel"
 | 
			
		||||
      @confirm="handleConfirm"
 | 
			
		||||
      :before-close="handleCancel"
 | 
			
		||||
    >
 | 
			
		||||
    <base-dialog :dialogTitle="addOrEditTitle" :dialogVisible="centervisible" @cancel="handleCancel"
 | 
			
		||||
      @confirm="handleConfirm" :before-close="handleCancel">
 | 
			
		||||
      <energy-plc-add ref="energyPlc" @successSubmit="successSubmit" />
 | 
			
		||||
    </base-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
@@ -50,7 +26,8 @@ import EnergyPlcAdd from './components/energyPlcAdd.vue'
 | 
			
		||||
const tableProps = [
 | 
			
		||||
  {
 | 
			
		||||
    prop: 'plcTableName',
 | 
			
		||||
    label: '关联表名'
 | 
			
		||||
    label: '关联表名',
 | 
			
		||||
    showOverflowtooltip: true
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    prop: 'code',
 | 
			
		||||
@@ -60,7 +37,9 @@ const tableProps = [
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    prop: 'name',
 | 
			
		||||
    label: '标识名'
 | 
			
		||||
    label: '标识名',
 | 
			
		||||
    minWidth: 150,
 | 
			
		||||
    showOverflowtooltip: true
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    prop: 'enName',
 | 
			
		||||
@@ -109,21 +88,21 @@ export default {
 | 
			
		||||
      tableBtn: [
 | 
			
		||||
        this.$auth.hasPermi('base:energy-plc:update')
 | 
			
		||||
          ? {
 | 
			
		||||
              type: 'edit',
 | 
			
		||||
              btnName: '编辑'
 | 
			
		||||
            }
 | 
			
		||||
            type: 'edit',
 | 
			
		||||
            btnName: '编辑'
 | 
			
		||||
          }
 | 
			
		||||
          : undefined,
 | 
			
		||||
        this.$auth.hasPermi('base:energy-plc:delete')
 | 
			
		||||
          ? {
 | 
			
		||||
              type: 'delete',
 | 
			
		||||
              btnName: '删除'
 | 
			
		||||
            }
 | 
			
		||||
            type: 'delete',
 | 
			
		||||
            btnName: '删除'
 | 
			
		||||
          }
 | 
			
		||||
          : undefined
 | 
			
		||||
      ].filter((v) => v),
 | 
			
		||||
      tableH: this.tableHeight(260),
 | 
			
		||||
      collectionList: [
 | 
			
		||||
        {value: 0,label: '否'},
 | 
			
		||||
        {value: 1,label: '是'}
 | 
			
		||||
        { value: 0, label: '否' },
 | 
			
		||||
        { value: 1, label: '是' }
 | 
			
		||||
      ],
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
@@ -167,7 +146,7 @@ export default {
 | 
			
		||||
    getList() {
 | 
			
		||||
      getEnergyPlcPage(this.queryParams).then(response => {
 | 
			
		||||
        let arr = response.data.list || [];
 | 
			
		||||
        arr&&arr.map(item => {
 | 
			
		||||
        arr && arr.map(item => {
 | 
			
		||||
          this.collectionList.map(i => {
 | 
			
		||||
            if (item.collection === i.value) {
 | 
			
		||||
              item.collection = i.label
 | 
			
		||||
@@ -188,7 +167,7 @@ export default {
 | 
			
		||||
          this.centervisible = true
 | 
			
		||||
          break
 | 
			
		||||
        default:
 | 
			
		||||
        this.handleDelete(val.data)
 | 
			
		||||
          this.handleDelete(val.data)
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    handleCancel() {
 | 
			
		||||
@@ -205,13 +184,13 @@ export default {
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      this.$modal.confirm('是否确认删除关联表名为"' + row.name + '"的数据项?').then(function() {
 | 
			
		||||
          return deleteEnergyPlc(row.id);
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          this.queryParams.pageNo = 1;
 | 
			
		||||
          this.getList();
 | 
			
		||||
          this.$modal.msgSuccess("删除成功");
 | 
			
		||||
        }).catch(() => {});
 | 
			
		||||
      this.$modal.confirm('是否确认删除关联表名为"' + row.name + '"的数据项?').then(function () {
 | 
			
		||||
        return deleteEnergyPlc(row.id);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.queryParams.pageNo = 1;
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("删除成功");
 | 
			
		||||
      }).catch(() => { });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -2,47 +2,23 @@
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <search-bar
 | 
			
		||||
      :formConfigs="formConfig"
 | 
			
		||||
      ref="searchBarForm"
 | 
			
		||||
      @headBtnClick="buttonClick"
 | 
			
		||||
    />
 | 
			
		||||
    <search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <base-table
 | 
			
		||||
      :page="queryParams.pageNo"
 | 
			
		||||
      :limit="queryParams.pageSize"
 | 
			
		||||
      :table-props="tableProps"
 | 
			
		||||
      :table-data="list"
 | 
			
		||||
      :max-height="tableH"
 | 
			
		||||
    >
 | 
			
		||||
      <method-btn
 | 
			
		||||
        v-if="tableBtn.length"
 | 
			
		||||
        slot="handleBtn"
 | 
			
		||||
        :width="160"
 | 
			
		||||
        label="操作"
 | 
			
		||||
        :method-list="tableBtn"
 | 
			
		||||
        @clickBtn="handleClick"
 | 
			
		||||
      />
 | 
			
		||||
    <base-table :page="queryParams.pageNo" :limit="queryParams.pageSize" :table-props="tableProps" :table-data="list"
 | 
			
		||||
      :max-height="tableH">
 | 
			
		||||
      <method-btn v-if="tableBtn.length" slot="handleBtn" :width="160" label="操作" :method-list="tableBtn"
 | 
			
		||||
        @clickBtn="handleClick" />
 | 
			
		||||
    </base-table>
 | 
			
		||||
    <pagination
 | 
			
		||||
      :page.sync="queryParams.pageNo"
 | 
			
		||||
      :limit.sync="queryParams.pageSize"
 | 
			
		||||
      :total="total"
 | 
			
		||||
      @pagination="getList"
 | 
			
		||||
    />
 | 
			
		||||
    <pagination :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" :total="total"
 | 
			
		||||
      @pagination="getList" />
 | 
			
		||||
    <!-- 新增 -->
 | 
			
		||||
    <base-dialog
 | 
			
		||||
      :dialogTitle="addOrEditTitle"
 | 
			
		||||
      :dialogVisible="centervisible"
 | 
			
		||||
      @cancel="handleCancel"
 | 
			
		||||
      @confirm="handleConfirm"
 | 
			
		||||
      :before-close="handleCancel"
 | 
			
		||||
      width='30%'
 | 
			
		||||
    >
 | 
			
		||||
    <base-dialog :dialogTitle="addOrEditTitle" :dialogVisible="centervisible" @cancel="handleCancel"
 | 
			
		||||
      @confirm="handleConfirm" :before-close="handleCancel" width='30%'>
 | 
			
		||||
      <energy-plc-connect-add ref="energyPlcConnect" :objList="objList" @successSubmit="successSubmit" />
 | 
			
		||||
    </base-dialog>
 | 
			
		||||
    <!-- 参数绑定/查看 -->
 | 
			
		||||
    <energy-plc-param v-if="paramVisible" ref="plcParam" @closeDrawer="closeDrawer" :energyTypeList="energyTypeList"></energy-plc-param>
 | 
			
		||||
    <energy-plc-param v-if="paramVisible" ref="plcParam" @closeDrawer="closeDrawer"
 | 
			
		||||
      :energyTypeList="energyTypeList"></energy-plc-param>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@@ -69,11 +45,14 @@ const tableProps = [
 | 
			
		||||
  {
 | 
			
		||||
    prop: 'plcTableCode',
 | 
			
		||||
    label: '关联表编码',
 | 
			
		||||
    minWidth: 150,
 | 
			
		||||
    showOverflowtooltip: true
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    prop: 'cnName',
 | 
			
		||||
    label: '标识名'
 | 
			
		||||
    label: '标识名',
 | 
			
		||||
    minWidth: 150,
 | 
			
		||||
    showOverflowtooltip: true
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    prop: 'varNum',
 | 
			
		||||
@@ -113,9 +92,9 @@ export default {
 | 
			
		||||
      tableBtn: [
 | 
			
		||||
        this.$auth.hasPermi('base:energy-plc-connect:bind')
 | 
			
		||||
          ? {
 | 
			
		||||
              type: 'connect',
 | 
			
		||||
              btnName: '绑定'
 | 
			
		||||
            }
 | 
			
		||||
            type: 'connect',
 | 
			
		||||
            btnName: '绑定'
 | 
			
		||||
          }
 | 
			
		||||
          : undefined,
 | 
			
		||||
        {
 | 
			
		||||
          type: 'detail',
 | 
			
		||||
@@ -123,15 +102,15 @@ export default {
 | 
			
		||||
        },
 | 
			
		||||
        this.$auth.hasPermi('base:energy-plc-connect:update')
 | 
			
		||||
          ? {
 | 
			
		||||
              type: 'edit',
 | 
			
		||||
              btnName: '编辑'
 | 
			
		||||
            }
 | 
			
		||||
            type: 'edit',
 | 
			
		||||
            btnName: '编辑'
 | 
			
		||||
          }
 | 
			
		||||
          : undefined,
 | 
			
		||||
        this.$auth.hasPermi('base:energy-plc-connect:delete')
 | 
			
		||||
          ? {
 | 
			
		||||
              type: 'delete',
 | 
			
		||||
              btnName: '删除'
 | 
			
		||||
            }
 | 
			
		||||
            type: 'delete',
 | 
			
		||||
            btnName: '删除'
 | 
			
		||||
          }
 | 
			
		||||
          : undefined
 | 
			
		||||
      ].filter((v) => v),
 | 
			
		||||
      tableH: this.tableHeight(260),
 | 
			
		||||
@@ -230,13 +209,13 @@ export default {
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      this.$modal.confirm('是否确认删除对象为"' + row.objName + '"的数据项?').then(function() {
 | 
			
		||||
          return deleteEnergyPlcConnect(row.id);
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          this.queryParams.pageNo = 1;
 | 
			
		||||
          this.getList();
 | 
			
		||||
          this.$modal.msgSuccess("删除成功");
 | 
			
		||||
        }).catch(() => {});
 | 
			
		||||
      this.$modal.confirm('是否确认删除对象为"' + row.objName + '"的数据项?').then(function () {
 | 
			
		||||
        return deleteEnergyPlcConnect(row.id);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.queryParams.pageNo = 1;
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("删除成功");
 | 
			
		||||
      }).catch(() => { });
 | 
			
		||||
    },
 | 
			
		||||
    closeDrawer() {
 | 
			
		||||
      this.getList()
 | 
			
		||||
 
 | 
			
		||||
@@ -2,43 +2,18 @@
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <search-bar
 | 
			
		||||
      :formConfigs="formConfig"
 | 
			
		||||
      ref="searchBarForm"
 | 
			
		||||
      @headBtnClick="buttonClick"
 | 
			
		||||
    />
 | 
			
		||||
    <search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <base-table
 | 
			
		||||
      :page="queryParams.pageNo"
 | 
			
		||||
      :limit="queryParams.pageSize"
 | 
			
		||||
      :table-props="tableProps"
 | 
			
		||||
      :table-data="list"
 | 
			
		||||
      :max-height="tableH"
 | 
			
		||||
    >
 | 
			
		||||
      <method-btn
 | 
			
		||||
        v-if="tableBtn.length"
 | 
			
		||||
        slot="handleBtn"
 | 
			
		||||
        :width="120"
 | 
			
		||||
        label="操作"
 | 
			
		||||
        :method-list="tableBtn"
 | 
			
		||||
        @clickBtn="handleClick"
 | 
			
		||||
      />
 | 
			
		||||
    <base-table :page="queryParams.pageNo" :limit="queryParams.pageSize" :table-props="tableProps" :table-data="list"
 | 
			
		||||
      :max-height="tableH">
 | 
			
		||||
      <method-btn v-if="tableBtn.length" slot="handleBtn" :width="120" label="操作" :method-list="tableBtn"
 | 
			
		||||
        @clickBtn="handleClick" />
 | 
			
		||||
    </base-table>
 | 
			
		||||
    <pagination
 | 
			
		||||
      :page.sync="queryParams.pageNo"
 | 
			
		||||
      :limit.sync="queryParams.pageSize"
 | 
			
		||||
      :total="total"
 | 
			
		||||
      @pagination="getList"
 | 
			
		||||
    />
 | 
			
		||||
    <pagination :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" :total="total"
 | 
			
		||||
      @pagination="getList" />
 | 
			
		||||
    <!-- 新增 -->
 | 
			
		||||
    <base-dialog
 | 
			
		||||
      :dialogTitle="addOrEditTitle"
 | 
			
		||||
      :dialogVisible="centervisible"
 | 
			
		||||
      @cancel="handleCancel"
 | 
			
		||||
      @confirm="handleConfirm"
 | 
			
		||||
      :before-close="handleCancel"
 | 
			
		||||
      width='50%'
 | 
			
		||||
    >
 | 
			
		||||
    <base-dialog :dialogTitle="addOrEditTitle" :dialogVisible="centervisible" @cancel="handleCancel"
 | 
			
		||||
      @confirm="handleConfirm" :before-close="handleCancel" width='50%'>
 | 
			
		||||
      <group-class-add ref="classList" @successSubmit="successSubmit" />
 | 
			
		||||
    </base-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
@@ -85,7 +60,7 @@ const tableProps = [
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
export default {
 | 
			
		||||
  name: "GroupClass",
 | 
			
		||||
  name: "GroupClasses",
 | 
			
		||||
  components: { GroupClassAdd },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
@@ -115,33 +90,33 @@ export default {
 | 
			
		||||
      ],
 | 
			
		||||
      tableProps,
 | 
			
		||||
      tableBtn: [
 | 
			
		||||
      this.$auth.hasPermi('base:group-classes:cancel')
 | 
			
		||||
        this.$auth.hasPermi('base:group-classes:cancel')
 | 
			
		||||
          ? {
 | 
			
		||||
              type: 'cancel',
 | 
			
		||||
              btnName: '作废',
 | 
			
		||||
              showParam: {
 | 
			
		||||
                type: '&',
 | 
			
		||||
                data: [
 | 
			
		||||
                  {
 | 
			
		||||
                    type: 'unequal',
 | 
			
		||||
                    name: 'status',
 | 
			
		||||
                    value: '不可用'
 | 
			
		||||
                  }
 | 
			
		||||
                ]
 | 
			
		||||
              }
 | 
			
		||||
            type: 'cancel',
 | 
			
		||||
            btnName: '作废',
 | 
			
		||||
            showParam: {
 | 
			
		||||
              type: '&',
 | 
			
		||||
              data: [
 | 
			
		||||
                {
 | 
			
		||||
                  type: 'unequal',
 | 
			
		||||
                  name: 'status',
 | 
			
		||||
                  value: '不可用'
 | 
			
		||||
                }
 | 
			
		||||
              ]
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          : undefined,
 | 
			
		||||
        this.$auth.hasPermi('base:group-classes:update')
 | 
			
		||||
          ? {
 | 
			
		||||
              type: 'edit',
 | 
			
		||||
              btnName: '编辑'
 | 
			
		||||
            }
 | 
			
		||||
            type: 'edit',
 | 
			
		||||
            btnName: '编辑'
 | 
			
		||||
          }
 | 
			
		||||
          : undefined,
 | 
			
		||||
        this.$auth.hasPermi('base:group-classes:delete')
 | 
			
		||||
          ? {
 | 
			
		||||
              type: 'delete',
 | 
			
		||||
              btnName: '删除'
 | 
			
		||||
            }
 | 
			
		||||
            type: 'delete',
 | 
			
		||||
            btnName: '删除'
 | 
			
		||||
          }
 | 
			
		||||
          : undefined
 | 
			
		||||
      ].filter((v) => v),
 | 
			
		||||
      tableH: this.tableHeight(260),
 | 
			
		||||
@@ -213,7 +188,7 @@ export default {
 | 
			
		||||
          this.discard(val.data)
 | 
			
		||||
          break
 | 
			
		||||
        default:
 | 
			
		||||
        this.handleDelete(val.data)
 | 
			
		||||
          this.handleDelete(val.data)
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    handleCancel() {
 | 
			
		||||
@@ -235,33 +210,33 @@ export default {
 | 
			
		||||
      obj.endTime = row.endTime
 | 
			
		||||
      obj.enableTime = row.enableTime
 | 
			
		||||
      obj.disableTime = Date.parse(new Date())
 | 
			
		||||
      this.$modal.confirm('是否确认作废班次名称为"' + row.name + '"的数据项?').then(function() {
 | 
			
		||||
          return updateGroupClasses({ ...obj })
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          this.getList();
 | 
			
		||||
          this.$modal.msgSuccess("操作成功");
 | 
			
		||||
        }).catch(() => {});
 | 
			
		||||
      this.$modal.confirm('是否确认作废班次名称为"' + row.name + '"的数据项?').then(function () {
 | 
			
		||||
        return updateGroupClasses({ ...obj })
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("操作成功");
 | 
			
		||||
      }).catch(() => { });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      console.log(row)
 | 
			
		||||
      let _this = this
 | 
			
		||||
      if (row.status === '可用') {// 可用
 | 
			
		||||
        _this.$modal.confirm('删除的班次"' + row.name + '"可能会影响交接班计划,请点取消再次确认!').then(function() {
 | 
			
		||||
          return _this.$modal.confirm('是否确认删除班次名称为"' + row.name + '"的数据项?').then(function() {
 | 
			
		||||
              return deleteGroupClasses(row.id);
 | 
			
		||||
            }).then(() => {
 | 
			
		||||
              _this.getList();
 | 
			
		||||
              _this.$modal.msgSuccess("删除成功");
 | 
			
		||||
            }).catch(() => {});
 | 
			
		||||
          })
 | 
			
		||||
      } else {
 | 
			
		||||
        _this.$modal.confirm('是否确认删除班次名称为"' + row.name + '"的数据项?').then(function() {
 | 
			
		||||
        _this.$modal.confirm('删除的班次"' + row.name + '"可能会影响交接班计划,请点取消再次确认!').then(function () {
 | 
			
		||||
          return _this.$modal.confirm('是否确认删除班次名称为"' + row.name + '"的数据项?').then(function () {
 | 
			
		||||
            return deleteGroupClasses(row.id);
 | 
			
		||||
          }).then(() => {
 | 
			
		||||
            _this.getList();
 | 
			
		||||
            _this.$modal.msgSuccess("删除成功");
 | 
			
		||||
          }).catch(() => {});
 | 
			
		||||
          }).catch(() => { });
 | 
			
		||||
        })
 | 
			
		||||
      } else {
 | 
			
		||||
        _this.$modal.confirm('是否确认删除班次名称为"' + row.name + '"的数据项?').then(function () {
 | 
			
		||||
          return deleteGroupClasses(row.id);
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          _this.getList();
 | 
			
		||||
          _this.$modal.msgSuccess("删除成功");
 | 
			
		||||
        }).catch(() => { });
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,210 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="系统日志" url="https://doc.iocoder.cn/system-log/" />
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="用户编号" prop="userId">
 | 
			
		||||
        <el-input v-model="queryParams.userId" placeholder="请输入用户编号" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="用户类型" prop="userType">
 | 
			
		||||
        <el-select v-model="queryParams.userType" placeholder="请选择用户类型" clearable>
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.USER_TYPE)"
 | 
			
		||||
                     :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="应用名" prop="applicationName">
 | 
			
		||||
        <el-input v-model="queryParams.applicationName" placeholder="请输入应用名" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="请求地址" prop="requestUrl">
 | 
			
		||||
        <el-input v-model="queryParams.requestUrl" placeholder="请输入请求地址" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="请求时间" prop="beginTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.beginTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="执行时长" prop="duration">
 | 
			
		||||
        <el-input v-model="queryParams.duration" placeholder="请输入执行时长" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="结果码" prop="resultCode">
 | 
			
		||||
        <el-input v-model="queryParams.resultCode" placeholder="请输入结果码" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="warning" plain icon="el-icon-download" size="mini" :loading="exportLoading" @click="handleExport"
 | 
			
		||||
                   v-hasPermi="['infra:api-access-log:export']">导出</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="日志编号" align="center" prop="id" />
 | 
			
		||||
      <el-table-column label="用户编号" align="center" prop="userId" />
 | 
			
		||||
      <el-table-column label="用户类型" align="center" prop="userType">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.USER_TYPE" :value="scope.row.userType"/>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>>
 | 
			
		||||
      <el-table-column label="应用名" align="center" prop="applicationName" />
 | 
			
		||||
      <el-table-column label="请求方法名" align="center" prop="requestMethod" />
 | 
			
		||||
      <el-table-column label="请求地址" align="center" prop="requestUrl" width="250" />
 | 
			
		||||
      <el-table-column label="请求时间" align="center" prop="beginTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.beginTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="执行时长" align="center" prop="startTime">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ scope.row.duration }}  ms</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作结果" align="center" prop="status">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ scope.row.resultCode === 0 ? '成功' : '失败(' + scope.row.resultMsg + ')' }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row,scope.index)"
 | 
			
		||||
                     v-hasPermi="['infra:api-access-log:query']">详细</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 查看明细 -->
 | 
			
		||||
    <el-dialog title="API 访问日志详细" :visible.sync="open" width="700px" append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" label-width="100px" size="mini">
 | 
			
		||||
        <el-row>
 | 
			
		||||
          <el-col :span="24">
 | 
			
		||||
            <el-form-item label="日志主键:">{{ form.id }}</el-form-item>
 | 
			
		||||
            <el-form-item label="链路追踪:">{{ form.traceId }}</el-form-item>
 | 
			
		||||
            <el-form-item label="应用名:">{{ form.applicationName }}</el-form-item>
 | 
			
		||||
            <el-form-item label="用户信息:">
 | 
			
		||||
              {{ form.userId }} <dict-tag :type="DICT_TYPE.USER_TYPE" :value="form.userType"/> | {{ form.userIp }} | {{ form.userAgent}}
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="请求信息:">{{ form.requestMethod }} | {{ form.requestUrl }} </el-form-item>
 | 
			
		||||
            <el-form-item label="请求参数:">{{ form.requestParams }}</el-form-item>
 | 
			
		||||
            <el-form-item label="开始时间:">
 | 
			
		||||
              {{ parseTime(form.beginTime) }} ~ {{ parseTime(form.endTime) }} | {{ form.duration }} ms
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="操作结果:">
 | 
			
		||||
              <div v-if="form.resultCode === 0">正常</div>
 | 
			
		||||
              <div v-else-if="form.resultCode > 0">失败 | {{ form.resultCode }} || {{ form.resultMsg}}</div>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
          </el-col>
 | 
			
		||||
        </el-row>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button @click="open = false">关 闭</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { getApiAccessLogPage, exportApiAccessLogExcel } from "@/api/infra/apiAccessLog";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "InfraApiAccessLog",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 导出遮罩层
 | 
			
		||||
      exportLoading: false,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // API 访问日志列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        userId: null,
 | 
			
		||||
        userType: null,
 | 
			
		||||
        applicationName: null,
 | 
			
		||||
        requestUrl: null,
 | 
			
		||||
        duration: null,
 | 
			
		||||
        resultCode: null,
 | 
			
		||||
        beginTime: []
 | 
			
		||||
      },
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {},
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getApiAccessLogPage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {};
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 详细按钮操作 */
 | 
			
		||||
    handleView(row) {
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.form = row;
 | 
			
		||||
    },
 | 
			
		||||
    /** 导出按钮操作 */
 | 
			
		||||
    handleExport() {
 | 
			
		||||
      // 处理查询参数
 | 
			
		||||
      let params = {...this.queryParams};
 | 
			
		||||
      params.pageNo = undefined;
 | 
			
		||||
      params.pageSize = undefined;
 | 
			
		||||
      // 执行导出
 | 
			
		||||
      this.$modal.confirm('是否确认导出所有API 访问日志数据项?').then(() => {
 | 
			
		||||
        this.exportLoading = true;
 | 
			
		||||
        return exportApiAccessLogExcel(params);
 | 
			
		||||
      }).then(response => {
 | 
			
		||||
        this.$download.excel(response, 'API 访问日志.xls');
 | 
			
		||||
        this.exportLoading = false;
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,228 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="系统日志" url="https://doc.iocoder.cn/system-log/" />
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="用户编号" prop="userId">
 | 
			
		||||
        <el-input v-model="queryParams.userId" placeholder="请输入用户编号" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="用户类型" prop="userType">
 | 
			
		||||
        <el-select v-model="queryParams.userType" placeholder="请选择用户类型" clearable>
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.USER_TYPE)"
 | 
			
		||||
                     :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="应用名" prop="applicationName">
 | 
			
		||||
        <el-input v-model="queryParams.applicationName" placeholder="请输入应用名" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="请求地址" prop="requestUrl">
 | 
			
		||||
        <el-input v-model="queryParams.requestUrl" placeholder="请输入请求地址" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="异常时间" prop="exceptionTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.exceptionTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="处理状态" prop="processStatus">
 | 
			
		||||
        <el-select v-model="queryParams.processStatus" placeholder="请选择处理状态" clearable>
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.INFRA_API_ERROR_LOG_PROCESS_STATUS)"
 | 
			
		||||
                     :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" :loading="exportLoading"
 | 
			
		||||
                   v-hasPermi="['infra:api-error-log:export']">导出</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="日志编号" align="center" prop="id" />
 | 
			
		||||
      <el-table-column label="用户编号" align="center" prop="userId" />
 | 
			
		||||
      <el-table-column label="用户类型" align="center" prop="userType">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.USER_TYPE" :value="scope.row.userType"/>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>>
 | 
			
		||||
      <el-table-column label="应用名" align="center" prop="applicationName" />
 | 
			
		||||
      <el-table-column label="请求方法名" align="center" prop="requestMethod" />
 | 
			
		||||
      <el-table-column label="请求地址" align="center" prop="requestUrl" width="250" />
 | 
			
		||||
      <el-table-column label="异常发生时间" align="center" prop="exceptionTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.exceptionTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="异常名" align="center" prop="exceptionName" width="250" />
 | 
			
		||||
      <el-table-column label="处理状态" align="center" prop="processStatus">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.INFRA_API_ERROR_LOG_PROCESS_STATUS" :value="scope.row.processStatus" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row,scope.index)"
 | 
			
		||||
                     v-hasPermi="['infra:api-access-log:query']">详细</el-button>
 | 
			
		||||
          <el-button type="text" size="mini" icon="el-icon-check"
 | 
			
		||||
              v-if="scope.row.processStatus === InfApiErrorLogProcessStatusEnum.INIT" v-hasPermi="['infra:api-error-log:update-status']"
 | 
			
		||||
              @click="handleProcessClick(scope.row, InfApiErrorLogProcessStatusEnum.DONE)">已处理</el-button>
 | 
			
		||||
          <el-button type="text" size="mini" icon="el-icon-check"
 | 
			
		||||
                     v-if="scope.row.processStatus === InfApiErrorLogProcessStatusEnum.INIT" v-hasPermi="['infra:api-error-log:update-status']"
 | 
			
		||||
                     @click="handleProcessClick(scope.row, InfApiErrorLogProcessStatusEnum.IGNORE)">已忽略</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 查看明细 -->
 | 
			
		||||
    <el-dialog title="API 异常日志详细" :visible.sync="open" width="1280px" append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" label-width="100px" size="mini">
 | 
			
		||||
        <el-row>
 | 
			
		||||
          <el-col :span="24">
 | 
			
		||||
            <el-form-item label="日志主键:">{{ form.id }}</el-form-item>
 | 
			
		||||
            <el-form-item label="链路追踪:">{{ form.traceId }}</el-form-item>
 | 
			
		||||
            <el-form-item label="应用名:">{{ form.applicationName }}</el-form-item>
 | 
			
		||||
            <el-form-item label="用户信息:">
 | 
			
		||||
              {{ form.userId }} <dict-tag :type="DICT_TYPE.USER_TYPE" :value="form.userType" /> | {{ form.userIp }} | {{ form.userAgent}}
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="请求信息:">{{ form.requestMethod }} | {{ form.requestUrl }} </el-form-item>
 | 
			
		||||
            <el-form-item label="请求参数:">{{ form.requestParams }}</el-form-item>
 | 
			
		||||
            <el-form-item label="异常时间:">{{ parseTime(form.exceptionTime) }}</el-form-item>
 | 
			
		||||
            <el-form-item label="异常名">{{ form.exceptionName }}</el-form-item>
 | 
			
		||||
            <el-form-item label="异常名">
 | 
			
		||||
              <el-input type="textarea" :readonly="true" :autosize="{ maxRows: 20}" v-model="form.exceptionStackTrace"></el-input>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="处理状态">
 | 
			
		||||
              <dict-tag :type="DICT_TYPE.INFRA_API_ERROR_LOG_PROCESS_STATUS" :value="form.processStatus" />
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="处理人">{{ form.processUserId }}</el-form-item>
 | 
			
		||||
            <el-form-item label="处理时间">{{ parseTime(form.processTime) }}</el-form-item>
 | 
			
		||||
          </el-col>
 | 
			
		||||
        </el-row>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button @click="open = false">关 闭</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { updateApiErrorLogProcess, getApiErrorLogPage, exportApiErrorLogExcel } from "@/api/infra/apiErrorLog";
 | 
			
		||||
import { InfraApiErrorLogProcessStatusEnum } from '@/utils/constants'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "InfraApiErrorLog",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 导出遮罩层
 | 
			
		||||
      exportLoading: false,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // API 错误日志列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        userId: null,
 | 
			
		||||
        userType: null,
 | 
			
		||||
        applicationName: null,
 | 
			
		||||
        requestUrl: null,
 | 
			
		||||
        processStatus: null,
 | 
			
		||||
        exceptionTime: []
 | 
			
		||||
      },
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {},
 | 
			
		||||
      // 枚举
 | 
			
		||||
      InfApiErrorLogProcessStatusEnum: InfraApiErrorLogProcessStatusEnum,
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getApiErrorLogPage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {};
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 详细按钮操作 */
 | 
			
		||||
    handleView(row) {
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.form = row;
 | 
			
		||||
    },
 | 
			
		||||
    /** 处理已处理 / 已忽略的操作 **/
 | 
			
		||||
    handleProcessClick(row, processStatus) {
 | 
			
		||||
      const processStatusText = this.getDictDataLabel(this.DICT_TYPE.INFRA_API_ERROR_LOG_PROCESS_STATUS, processStatus)
 | 
			
		||||
      this.$modal.confirm('确认标记为' + processStatusText).then(() => {
 | 
			
		||||
        updateApiErrorLogProcess(row.id, processStatus).then(() => {
 | 
			
		||||
          this.$modal.msgSuccess("修改成功");
 | 
			
		||||
          this.getList();
 | 
			
		||||
        });
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    /** 导出按钮操作 */
 | 
			
		||||
    handleExport() {
 | 
			
		||||
      // 处理查询参数
 | 
			
		||||
      let params = {...this.queryParams};
 | 
			
		||||
      params.pageNo = undefined;
 | 
			
		||||
      params.pageSize = undefined;
 | 
			
		||||
      // 执行导出
 | 
			
		||||
      this.$modal.confirm('是否确认导出所有API 错误日志数据项?').then(() => {
 | 
			
		||||
        this.exportLoading = true;
 | 
			
		||||
        return exportApiErrorLogExcel(params);
 | 
			
		||||
      }).then(response => {
 | 
			
		||||
        this.$download.excel(response, 'API 错误日志.xls');
 | 
			
		||||
        this.exportLoading = false;
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,22 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <router-view />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
  mounted() {
 | 
			
		||||
    // 取消开始的loading动画
 | 
			
		||||
    const preLoader = document.querySelector('#pre-loader')
 | 
			
		||||
    preLoader.style.display = 'none'
 | 
			
		||||
 | 
			
		||||
    // fix: firefox 下 拖拽 会新打卡一个选项卡
 | 
			
		||||
    // https://github.com/JakHuang/form-generator/issues/15
 | 
			
		||||
    document.body.ondrop = event => {
 | 
			
		||||
      event.preventDefault()
 | 
			
		||||
      event.stopPropagation()
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,110 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <el-dialog
 | 
			
		||||
      v-bind="$attrs"
 | 
			
		||||
      width="500px"
 | 
			
		||||
      :close-on-click-modal="false"
 | 
			
		||||
      :modal-append-to-body="false"
 | 
			
		||||
      v-on="$listeners"
 | 
			
		||||
      @open="onOpen"
 | 
			
		||||
      @close="onClose"
 | 
			
		||||
    >
 | 
			
		||||
      <el-row :gutter="15">
 | 
			
		||||
        <el-form
 | 
			
		||||
          ref="elForm"
 | 
			
		||||
          :model="formData"
 | 
			
		||||
          :rules="rules"
 | 
			
		||||
          size="medium"
 | 
			
		||||
          label-width="100px"
 | 
			
		||||
        >
 | 
			
		||||
          <el-col :span="24">
 | 
			
		||||
            <el-form-item label="生成类型" prop="type">
 | 
			
		||||
              <el-radio-group v-model="formData.type">
 | 
			
		||||
                <el-radio-button
 | 
			
		||||
                  v-for="(item, index) in typeOptions"
 | 
			
		||||
                  :key="index"
 | 
			
		||||
                  :label="item.value"
 | 
			
		||||
                  :disabled="item.disabled"
 | 
			
		||||
                >
 | 
			
		||||
                  {{ item.label }}
 | 
			
		||||
                </el-radio-button>
 | 
			
		||||
              </el-radio-group>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item v-if="showFileName" label="文件名" prop="fileName">
 | 
			
		||||
              <el-input v-model="formData.fileName" placeholder="请输入文件名" clearable />
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
          </el-col>
 | 
			
		||||
        </el-form>
 | 
			
		||||
      </el-row>
 | 
			
		||||
 | 
			
		||||
      <div slot="footer">
 | 
			
		||||
        <el-button @click="close">
 | 
			
		||||
          取消
 | 
			
		||||
        </el-button>
 | 
			
		||||
        <el-button type="primary" @click="handelConfirm">
 | 
			
		||||
          确定
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
  inheritAttrs: false,
 | 
			
		||||
  props: ['showFileName'],
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      formData: {
 | 
			
		||||
        fileName: undefined,
 | 
			
		||||
        type: 'file'
 | 
			
		||||
      },
 | 
			
		||||
      rules: {
 | 
			
		||||
        fileName: [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '请输入文件名',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        type: [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '生成类型不能为空',
 | 
			
		||||
          trigger: 'change'
 | 
			
		||||
        }]
 | 
			
		||||
      },
 | 
			
		||||
      typeOptions: [{
 | 
			
		||||
        label: '页面',
 | 
			
		||||
        value: 'file'
 | 
			
		||||
      }, {
 | 
			
		||||
        label: '弹窗',
 | 
			
		||||
        value: 'dialog'
 | 
			
		||||
      }]
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
  },
 | 
			
		||||
  watch: {},
 | 
			
		||||
  mounted() {},
 | 
			
		||||
  methods: {
 | 
			
		||||
    onOpen() {
 | 
			
		||||
      if (this.showFileName) {
 | 
			
		||||
        this.formData.fileName = `${+new Date()}.vue`
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    onClose() {
 | 
			
		||||
    },
 | 
			
		||||
    close(e) {
 | 
			
		||||
      this.$emit('update:visible', false)
 | 
			
		||||
    },
 | 
			
		||||
    handelConfirm() {
 | 
			
		||||
      this.$refs.elForm.validate(valid => {
 | 
			
		||||
        if (!valid) return
 | 
			
		||||
        this.$emit('confirm', { ...this.formData })
 | 
			
		||||
        this.close()
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,120 +0,0 @@
 | 
			
		||||
<script>
 | 
			
		||||
import draggable from 'vuedraggable'
 | 
			
		||||
import render from '@/components/render/render'
 | 
			
		||||
 | 
			
		||||
const components = {
 | 
			
		||||
  itemBtns(h, currentItem, index, list) {
 | 
			
		||||
    const { copyItem, deleteItem } = this.$listeners
 | 
			
		||||
    return [
 | 
			
		||||
      <span class="drawing-item-copy" title="复制" onClick={event => {
 | 
			
		||||
        copyItem(currentItem, list); event.stopPropagation()
 | 
			
		||||
      }}>
 | 
			
		||||
        <i class="el-icon-copy-document" />
 | 
			
		||||
      </span>,
 | 
			
		||||
      <span class="drawing-item-delete" title="删除" onClick={event => {
 | 
			
		||||
        deleteItem(index, list); event.stopPropagation()
 | 
			
		||||
      }}>
 | 
			
		||||
        <i class="el-icon-delete" />
 | 
			
		||||
      </span>
 | 
			
		||||
    ]
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
const layouts = {
 | 
			
		||||
  colFormItem(h, currentItem, index, list) {
 | 
			
		||||
    const { activeItem } = this.$listeners
 | 
			
		||||
    const config = currentItem.__config__
 | 
			
		||||
    const child = renderChildren.apply(this, arguments)
 | 
			
		||||
    let className = this.activeId === config.formId ? 'drawing-item active-from-item' : 'drawing-item'
 | 
			
		||||
    if (this.formConf.unFocusedComponentBorder) className += ' unfocus-bordered'
 | 
			
		||||
    let labelWidth = config.labelWidth ? `${config.labelWidth}px` : null
 | 
			
		||||
    if (config.showLabel === false) labelWidth = '0'
 | 
			
		||||
    return (
 | 
			
		||||
      <el-col span={config.span} class={className}
 | 
			
		||||
        nativeOnClick={event => { activeItem(currentItem); event.stopPropagation() }}>
 | 
			
		||||
        <el-form-item label-width={labelWidth}
 | 
			
		||||
          label={config.showLabel ? config.label : ''} required={config.required}>
 | 
			
		||||
          <render key={config.renderKey} conf={currentItem} onInput={ event => {
 | 
			
		||||
            this.$set(config, 'defaultValue', event)
 | 
			
		||||
          }}>
 | 
			
		||||
            {child}
 | 
			
		||||
          </render>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        {components.itemBtns.apply(this, arguments)}
 | 
			
		||||
      </el-col>
 | 
			
		||||
    )
 | 
			
		||||
  },
 | 
			
		||||
  rowFormItem(h, currentItem, index, list) {
 | 
			
		||||
    const { activeItem } = this.$listeners
 | 
			
		||||
    const config = currentItem.__config__
 | 
			
		||||
    const className = this.activeId === config.formId
 | 
			
		||||
      ? 'drawing-row-item active-from-item'
 | 
			
		||||
      : 'drawing-row-item'
 | 
			
		||||
    let child = renderChildren.apply(this, arguments)
 | 
			
		||||
    if (currentItem.type === 'flex') {
 | 
			
		||||
      child = <el-row type={currentItem.type} justify={currentItem.justify} align={currentItem.align}>
 | 
			
		||||
              {child}
 | 
			
		||||
            </el-row>
 | 
			
		||||
    }
 | 
			
		||||
    return (
 | 
			
		||||
      <el-col span={config.span}>
 | 
			
		||||
        <el-row gutter={config.gutter} class={className}
 | 
			
		||||
          nativeOnClick={event => { activeItem(currentItem); event.stopPropagation() }}>
 | 
			
		||||
          <span class="component-name">{config.componentName}</span>
 | 
			
		||||
          <draggable list={config.children || []} animation={340}
 | 
			
		||||
            group="componentsGroup" class="drag-wrapper">
 | 
			
		||||
            {child}
 | 
			
		||||
          </draggable>
 | 
			
		||||
          {components.itemBtns.apply(this, arguments)}
 | 
			
		||||
        </el-row>
 | 
			
		||||
      </el-col>
 | 
			
		||||
    )
 | 
			
		||||
  },
 | 
			
		||||
  raw(h, currentItem, index, list) {
 | 
			
		||||
    const config = currentItem.__config__
 | 
			
		||||
    const child = renderChildren.apply(this, arguments)
 | 
			
		||||
    return <render key={config.renderKey} conf={currentItem} onInput={ event => {
 | 
			
		||||
      this.$set(config, 'defaultValue', event)
 | 
			
		||||
    }}>
 | 
			
		||||
      {child}
 | 
			
		||||
    </render>
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function renderChildren(h, currentItem, index, list) {
 | 
			
		||||
  const config = currentItem.__config__
 | 
			
		||||
  if (!Array.isArray(config.children)) return null
 | 
			
		||||
  return config.children.map((el, i) => {
 | 
			
		||||
    const layout = layouts[el.__config__.layout]
 | 
			
		||||
    if (layout) {
 | 
			
		||||
      return layout.call(this, h, el, i, config.children)
 | 
			
		||||
    }
 | 
			
		||||
    return layoutIsNotFound.call(this)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function layoutIsNotFound() {
 | 
			
		||||
  throw new Error(`没有与${this.currentItem.__config__.layout}匹配的layout`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  components: {
 | 
			
		||||
    render,
 | 
			
		||||
    draggable
 | 
			
		||||
  },
 | 
			
		||||
  props: [
 | 
			
		||||
    'currentItem',
 | 
			
		||||
    'index',
 | 
			
		||||
    'drawingList',
 | 
			
		||||
    'activeId',
 | 
			
		||||
    'formConf'
 | 
			
		||||
  ],
 | 
			
		||||
  render(h) {
 | 
			
		||||
    const layout = layouts[this.currentItem.__config__.layout]
 | 
			
		||||
 | 
			
		||||
    if (layout) {
 | 
			
		||||
      return layout.call(this, h, this.currentItem, this.index, this.drawingList)
 | 
			
		||||
    }
 | 
			
		||||
    return layoutIsNotFound.call(this)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,331 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <el-drawer v-bind="$attrs" v-on="$listeners" @opened="onOpen" @close="onClose">
 | 
			
		||||
      <div style="height:100%">
 | 
			
		||||
        <el-row style="height:100%;overflow:auto">
 | 
			
		||||
          <el-col :md="24" :lg="12" class="left-editor">
 | 
			
		||||
            <div class="setting" title="资源引用" @click="showResource">
 | 
			
		||||
              <el-badge :is-dot="!!resources.length" class="item">
 | 
			
		||||
                <i class="el-icon-setting" />
 | 
			
		||||
              </el-badge>
 | 
			
		||||
            </div>
 | 
			
		||||
            <el-tabs v-model="activeTab" type="card" class="editor-tabs">
 | 
			
		||||
              <el-tab-pane name="html">
 | 
			
		||||
                <span slot="label">
 | 
			
		||||
                  <i v-if="activeTab==='html'" class="el-icon-edit" />
 | 
			
		||||
                  <i v-else class="el-icon-document" />
 | 
			
		||||
                  template
 | 
			
		||||
                </span>
 | 
			
		||||
              </el-tab-pane>
 | 
			
		||||
              <el-tab-pane name="js">
 | 
			
		||||
                <span slot="label">
 | 
			
		||||
                  <i v-if="activeTab==='js'" class="el-icon-edit" />
 | 
			
		||||
                  <i v-else class="el-icon-document" />
 | 
			
		||||
                  script
 | 
			
		||||
                </span>
 | 
			
		||||
              </el-tab-pane>
 | 
			
		||||
              <el-tab-pane name="css">
 | 
			
		||||
                <span slot="label">
 | 
			
		||||
                  <i v-if="activeTab==='css'" class="el-icon-edit" />
 | 
			
		||||
                  <i v-else class="el-icon-document" />
 | 
			
		||||
                  css
 | 
			
		||||
                </span>
 | 
			
		||||
              </el-tab-pane>
 | 
			
		||||
            </el-tabs>
 | 
			
		||||
            <div v-show="activeTab==='html'" id="editorHtml" class="tab-editor" />
 | 
			
		||||
            <div v-show="activeTab==='js'" id="editorJs" class="tab-editor" />
 | 
			
		||||
            <div v-show="activeTab==='css'" id="editorCss" class="tab-editor" />
 | 
			
		||||
          </el-col>
 | 
			
		||||
          <el-col :md="24" :lg="12" class="right-preview">
 | 
			
		||||
            <div class="action-bar" :style="{'text-align': 'left'}">
 | 
			
		||||
              <span class="bar-btn" @click="runCode">
 | 
			
		||||
                <i class="el-icon-refresh" />
 | 
			
		||||
                刷新
 | 
			
		||||
              </span>
 | 
			
		||||
              <span class="bar-btn" @click="exportFile">
 | 
			
		||||
                <i class="el-icon-download" />
 | 
			
		||||
                导出vue文件
 | 
			
		||||
              </span>
 | 
			
		||||
              <span ref="copyBtn" class="bar-btn copy-btn">
 | 
			
		||||
                <i class="el-icon-document-copy" />
 | 
			
		||||
                复制代码
 | 
			
		||||
              </span>
 | 
			
		||||
              <span class="bar-btn delete-btn" @click="$emit('update:visible', false)">
 | 
			
		||||
                <i class="el-icon-circle-close" />
 | 
			
		||||
                关闭
 | 
			
		||||
              </span>
 | 
			
		||||
            </div>
 | 
			
		||||
            <iframe
 | 
			
		||||
              v-show="isIframeLoaded"
 | 
			
		||||
              ref="previewPage"
 | 
			
		||||
              class="result-wrapper"
 | 
			
		||||
              frameborder="0"
 | 
			
		||||
              src="preview.html"
 | 
			
		||||
              @load="iframeLoad"
 | 
			
		||||
            />
 | 
			
		||||
            <div v-show="!isIframeLoaded" v-loading="true" class="result-wrapper" />
 | 
			
		||||
          </el-col>
 | 
			
		||||
        </el-row>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-drawer>
 | 
			
		||||
    <resource-dialog
 | 
			
		||||
      :visible.sync="resourceVisible"
 | 
			
		||||
      :origin-resource="resources"
 | 
			
		||||
      @save="setResource"
 | 
			
		||||
    />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
import { parse } from '@babel/parser'
 | 
			
		||||
import ClipboardJS from 'clipboard'
 | 
			
		||||
import { saveAs } from 'file-saver'
 | 
			
		||||
import {
 | 
			
		||||
  makeUpHtml, vueTemplate, vueScript, cssStyle
 | 
			
		||||
} from '@/components/generator/html'
 | 
			
		||||
import { makeUpJs } from '@/components/generator/js'
 | 
			
		||||
import { makeUpCss } from '@/components/generator/css'
 | 
			
		||||
import { exportDefault, beautifierConf } from '@/utils'
 | 
			
		||||
import ResourceDialog from './ResourceDialog'
 | 
			
		||||
import loadMonaco from '@/utils/loadMonaco'
 | 
			
		||||
import loadBeautifier from '@/utils/loadBeautifier'
 | 
			
		||||
 | 
			
		||||
const editorObj = {
 | 
			
		||||
  html: null,
 | 
			
		||||
  js: null,
 | 
			
		||||
  css: null
 | 
			
		||||
}
 | 
			
		||||
const mode = {
 | 
			
		||||
  html: 'html',
 | 
			
		||||
  js: 'javascript',
 | 
			
		||||
  css: 'css'
 | 
			
		||||
}
 | 
			
		||||
let beautifier
 | 
			
		||||
let monaco
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  components: { ResourceDialog },
 | 
			
		||||
  props: ['formData', 'generateConf'],
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      activeTab: 'html',
 | 
			
		||||
      htmlCode: '',
 | 
			
		||||
      jsCode: '',
 | 
			
		||||
      cssCode: '',
 | 
			
		||||
      codeFrame: '',
 | 
			
		||||
      isIframeLoaded: false,
 | 
			
		||||
      isInitcode: false, // 保证open后两个异步只执行一次runcode
 | 
			
		||||
      isRefreshCode: false, // 每次打开都需要重新刷新代码
 | 
			
		||||
      resourceVisible: false,
 | 
			
		||||
      scripts: [],
 | 
			
		||||
      links: [],
 | 
			
		||||
      monaco: null
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
    resources() {
 | 
			
		||||
      return this.scripts.concat(this.links)
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  watch: {},
 | 
			
		||||
  created() {
 | 
			
		||||
  },
 | 
			
		||||
  mounted() {
 | 
			
		||||
    window.addEventListener('keydown', this.preventDefaultSave)
 | 
			
		||||
    const clipboard = new ClipboardJS('.copy-btn', {
 | 
			
		||||
      text: trigger => {
 | 
			
		||||
        const codeStr = this.generateCode()
 | 
			
		||||
        this.$notify({
 | 
			
		||||
          title: '成功',
 | 
			
		||||
          message: '代码已复制到剪切板,可粘贴。',
 | 
			
		||||
          type: 'success'
 | 
			
		||||
        })
 | 
			
		||||
        return codeStr
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    clipboard.on('error', e => {
 | 
			
		||||
      this.$message.error('代码复制失败')
 | 
			
		||||
    })
 | 
			
		||||
  },
 | 
			
		||||
  beforeDestroy() {
 | 
			
		||||
    window.removeEventListener('keydown', this.preventDefaultSave)
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    preventDefaultSave(e) {
 | 
			
		||||
      if (e.key === 's' && (e.metaKey || e.ctrlKey)) {
 | 
			
		||||
        e.preventDefault()
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    onOpen() {
 | 
			
		||||
      const { type } = this.generateConf
 | 
			
		||||
      this.htmlCode = makeUpHtml(this.formData, type)
 | 
			
		||||
      this.jsCode = makeUpJs(this.formData, type)
 | 
			
		||||
      this.cssCode = makeUpCss(this.formData)
 | 
			
		||||
 | 
			
		||||
      loadBeautifier(btf => {
 | 
			
		||||
        beautifier = btf
 | 
			
		||||
        this.htmlCode = beautifier.html(this.htmlCode, beautifierConf.html)
 | 
			
		||||
        this.jsCode = beautifier.js(this.jsCode, beautifierConf.js)
 | 
			
		||||
        this.cssCode = beautifier.css(this.cssCode, beautifierConf.html)
 | 
			
		||||
 | 
			
		||||
        loadMonaco(val => {
 | 
			
		||||
          monaco = val
 | 
			
		||||
          this.setEditorValue('editorHtml', 'html', this.htmlCode)
 | 
			
		||||
          this.setEditorValue('editorJs', 'js', this.jsCode)
 | 
			
		||||
          this.setEditorValue('editorCss', 'css', this.cssCode)
 | 
			
		||||
          if (!this.isInitcode) {
 | 
			
		||||
            this.isRefreshCode = true
 | 
			
		||||
            this.isIframeLoaded && (this.isInitcode = true) && this.runCode()
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    onClose() {
 | 
			
		||||
      this.isInitcode = false
 | 
			
		||||
      this.isRefreshCode = false
 | 
			
		||||
    },
 | 
			
		||||
    iframeLoad() {
 | 
			
		||||
      if (!this.isInitcode) {
 | 
			
		||||
        this.isIframeLoaded = true
 | 
			
		||||
        this.isRefreshCode && (this.isInitcode = true) && this.runCode()
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    setEditorValue(id, type, codeStr) {
 | 
			
		||||
      if (editorObj[type]) {
 | 
			
		||||
        editorObj[type].setValue(codeStr)
 | 
			
		||||
      } else {
 | 
			
		||||
        editorObj[type] = monaco.editor.create(document.getElementById(id), {
 | 
			
		||||
          value: codeStr,
 | 
			
		||||
          theme: 'vs-dark',
 | 
			
		||||
          language: mode[type],
 | 
			
		||||
          automaticLayout: true
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
      // ctrl + s 刷新
 | 
			
		||||
      editorObj[type].onKeyDown(e => {
 | 
			
		||||
        if (e.keyCode === 49 && (e.metaKey || e.ctrlKey)) {
 | 
			
		||||
          this.runCode()
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    runCode() {
 | 
			
		||||
      const jsCodeStr = editorObj.js.getValue()
 | 
			
		||||
      try {
 | 
			
		||||
        const ast = parse(jsCodeStr, { sourceType: 'module' })
 | 
			
		||||
        const astBody = ast.program.body
 | 
			
		||||
        if (astBody.length > 1) {
 | 
			
		||||
          this.$confirm(
 | 
			
		||||
            'js格式不能识别,仅支持修改export default的对象内容',
 | 
			
		||||
            '提示',
 | 
			
		||||
            {
 | 
			
		||||
              type: 'warning'
 | 
			
		||||
            }).catch(() => {});
 | 
			
		||||
          return
 | 
			
		||||
        }
 | 
			
		||||
        if (astBody[0].type === 'ExportDefaultDeclaration') {
 | 
			
		||||
          const postData = {
 | 
			
		||||
            type: 'refreshFrame',
 | 
			
		||||
            data: {
 | 
			
		||||
              generateConf: this.generateConf,
 | 
			
		||||
              html: editorObj.html.getValue(),
 | 
			
		||||
              js: jsCodeStr.replace(exportDefault, ''),
 | 
			
		||||
              css: editorObj.css.getValue(),
 | 
			
		||||
              scripts: this.scripts,
 | 
			
		||||
              links: this.links
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          this.$refs.previewPage.contentWindow.postMessage(
 | 
			
		||||
            postData,
 | 
			
		||||
            location.origin
 | 
			
		||||
          )
 | 
			
		||||
        } else {
 | 
			
		||||
          this.$message.error('请使用export default')
 | 
			
		||||
        }
 | 
			
		||||
      } catch (err) {
 | 
			
		||||
        this.$message.error(`js错误:${err}`)
 | 
			
		||||
        console.error(err)
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    generateCode() {
 | 
			
		||||
      const html = vueTemplate(editorObj.html.getValue())
 | 
			
		||||
      const script = vueScript(editorObj.js.getValue())
 | 
			
		||||
      const css = cssStyle(editorObj.css.getValue())
 | 
			
		||||
      return beautifier.html(html + script + css, beautifierConf.html)
 | 
			
		||||
    },
 | 
			
		||||
    exportFile() {
 | 
			
		||||
      this.$prompt('文件名:', '导出文件', {
 | 
			
		||||
        inputValue: `${+new Date()}.vue`,
 | 
			
		||||
        closeOnClickModal: false,
 | 
			
		||||
        inputPlaceholder: '请输入文件名'
 | 
			
		||||
      }).then(({ value }) => {
 | 
			
		||||
        if (!value) value = `${+new Date()}.vue`
 | 
			
		||||
        const codeStr = this.generateCode()
 | 
			
		||||
        const blob = new Blob([codeStr], { type: 'text/plain;charset=utf-8' })
 | 
			
		||||
        saveAs(blob, value)
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    showResource() {
 | 
			
		||||
      this.resourceVisible = true
 | 
			
		||||
    },
 | 
			
		||||
    setResource(arr) {
 | 
			
		||||
      const scripts = []; const
 | 
			
		||||
        links = []
 | 
			
		||||
      if (Array.isArray(arr)) {
 | 
			
		||||
        arr.forEach(item => {
 | 
			
		||||
          if (item.endsWith('.css')) {
 | 
			
		||||
            links.push(item)
 | 
			
		||||
          } else {
 | 
			
		||||
            scripts.push(item)
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
        this.scripts = scripts
 | 
			
		||||
        this.links = links
 | 
			
		||||
      } else {
 | 
			
		||||
        this.scripts = []
 | 
			
		||||
        this.links = []
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
@import '@/styles/mixin.scss';
 | 
			
		||||
.tab-editor {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  top: 33px;
 | 
			
		||||
  bottom: 0;
 | 
			
		||||
  left: 0;
 | 
			
		||||
  right: 0;
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
}
 | 
			
		||||
.left-editor {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  background: #1e1e1e;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
.setting{
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  right: 15px;
 | 
			
		||||
  top: 3px;
 | 
			
		||||
  color: #a9f122;
 | 
			
		||||
  font-size: 18px;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  z-index: 1;
 | 
			
		||||
}
 | 
			
		||||
.right-preview {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  .result-wrapper {
 | 
			
		||||
    height: calc(100vh - 33px);
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    overflow: auto;
 | 
			
		||||
    padding: 12px;
 | 
			
		||||
    box-sizing: border-box;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@include action-bar;
 | 
			
		||||
:deep(.el-drawer__header) {
 | 
			
		||||
  display: none;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,123 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="icon-dialog">
 | 
			
		||||
    <el-dialog
 | 
			
		||||
      v-bind="$attrs"
 | 
			
		||||
      width="980px"
 | 
			
		||||
      :modal-append-to-body="false"
 | 
			
		||||
      v-on="$listeners"
 | 
			
		||||
      @open="onOpen"
 | 
			
		||||
      @close="onClose"
 | 
			
		||||
    >
 | 
			
		||||
      <div slot="title">
 | 
			
		||||
        选择图标
 | 
			
		||||
        <el-input
 | 
			
		||||
          v-model="key"
 | 
			
		||||
          size="mini"
 | 
			
		||||
          :style="{width: '260px'}"
 | 
			
		||||
          placeholder="请输入图标名称"
 | 
			
		||||
          prefix-icon="el-icon-search"
 | 
			
		||||
          clearable
 | 
			
		||||
        />
 | 
			
		||||
      </div>
 | 
			
		||||
      <ul class="icon-ul">
 | 
			
		||||
        <li
 | 
			
		||||
          v-for="icon in iconList"
 | 
			
		||||
          :key="icon"
 | 
			
		||||
          :class="active===icon?'active-item':''"
 | 
			
		||||
          @click="onSelect(icon)"
 | 
			
		||||
        >
 | 
			
		||||
          <i :class="icon" />
 | 
			
		||||
          <div>{{ icon }}</div>
 | 
			
		||||
        </li>
 | 
			
		||||
      </ul>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
import iconList from '@/utils/icon.json'
 | 
			
		||||
 | 
			
		||||
const originList = iconList.map(name => `el-icon-${name}`)
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  inheritAttrs: false,
 | 
			
		||||
  props: ['current'],
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      iconList: originList,
 | 
			
		||||
      active: null,
 | 
			
		||||
      key: ''
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  watch: {
 | 
			
		||||
    key(val) {
 | 
			
		||||
      if (val) {
 | 
			
		||||
        this.iconList = originList.filter(name => name.indexOf(val) > -1)
 | 
			
		||||
      } else {
 | 
			
		||||
        this.iconList = originList
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    onOpen() {
 | 
			
		||||
      this.active = this.current
 | 
			
		||||
      this.key = ''
 | 
			
		||||
    },
 | 
			
		||||
    onClose() {},
 | 
			
		||||
    onSelect(icon) {
 | 
			
		||||
      this.active = icon
 | 
			
		||||
      this.$emit('select', icon)
 | 
			
		||||
      this.$emit('update:visible', false)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
.icon-ul {
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  font-size: 0;
 | 
			
		||||
  li {
 | 
			
		||||
    list-style-type: none;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    font-size: 14px;
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    width: 16.66%;
 | 
			
		||||
    box-sizing: border-box;
 | 
			
		||||
    height: 108px;
 | 
			
		||||
    padding: 15px 6px 6px 6px;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    &:hover {
 | 
			
		||||
      background: #f2f2f2;
 | 
			
		||||
    }
 | 
			
		||||
    &.active-item{
 | 
			
		||||
      background: #e1f3fb;
 | 
			
		||||
      color: #7a6df0
 | 
			
		||||
    }
 | 
			
		||||
    > i {
 | 
			
		||||
      font-size: 30px;
 | 
			
		||||
      line-height: 50px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.icon-dialog {
 | 
			
		||||
  :deep(.el-dialog) {
 | 
			
		||||
    border-radius: 8px;
 | 
			
		||||
    margin-bottom: 0;
 | 
			
		||||
    margin-top: 4vh !important;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    max-height: 92vh;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    box-sizing: border-box;
 | 
			
		||||
    .el-dialog__header {
 | 
			
		||||
      padding-top: 14px;
 | 
			
		||||
    }
 | 
			
		||||
    .el-dialog__body {
 | 
			
		||||
      margin: 0 20px 20px 20px;
 | 
			
		||||
      padding: 0;
 | 
			
		||||
      overflow: auto;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,144 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <el-drawer v-bind="$attrs" v-on="$listeners" @opened="onOpen" @close="onClose">
 | 
			
		||||
      <div class="action-bar" :style="{'text-align': 'left'}">
 | 
			
		||||
        <span class="bar-btn" @click="refresh">
 | 
			
		||||
          <i class="el-icon-refresh" />
 | 
			
		||||
          刷新
 | 
			
		||||
        </span>
 | 
			
		||||
        <span ref="copyBtn" class="bar-btn copy-json-btn">
 | 
			
		||||
          <i class="el-icon-document-copy" />
 | 
			
		||||
          复制JSON
 | 
			
		||||
        </span>
 | 
			
		||||
        <span class="bar-btn" @click="exportJsonFile">
 | 
			
		||||
          <i class="el-icon-download" />
 | 
			
		||||
          导出JSON文件
 | 
			
		||||
        </span>
 | 
			
		||||
        <span class="bar-btn delete-btn" @click="$emit('update:visible', false)">
 | 
			
		||||
          <i class="el-icon-circle-close" />
 | 
			
		||||
          关闭
 | 
			
		||||
        </span>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div id="editorJson" class="json-editor" />
 | 
			
		||||
    </el-drawer>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { beautifierConf } from '@/utils'
 | 
			
		||||
import ClipboardJS from 'clipboard'
 | 
			
		||||
import { saveAs } from 'file-saver'
 | 
			
		||||
import loadMonaco from '@/utils/loadMonaco'
 | 
			
		||||
import loadBeautifier from '@/utils/loadBeautifier'
 | 
			
		||||
 | 
			
		||||
let beautifier
 | 
			
		||||
let monaco
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  components: {},
 | 
			
		||||
  props: {
 | 
			
		||||
    jsonStr: {
 | 
			
		||||
      type: String,
 | 
			
		||||
      required: true
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {}
 | 
			
		||||
  },
 | 
			
		||||
  computed: {},
 | 
			
		||||
  watch: {},
 | 
			
		||||
  created() {},
 | 
			
		||||
  mounted() {
 | 
			
		||||
    window.addEventListener('keydown', this.preventDefaultSave)
 | 
			
		||||
    const clipboard = new ClipboardJS('.copy-json-btn', {
 | 
			
		||||
      text: trigger => {
 | 
			
		||||
        this.$notify({
 | 
			
		||||
          title: '成功',
 | 
			
		||||
          message: '代码已复制到剪切板,可粘贴。',
 | 
			
		||||
          type: 'success'
 | 
			
		||||
        })
 | 
			
		||||
        return this.beautifierJson
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    clipboard.on('error', e => {
 | 
			
		||||
      this.$message.error('代码复制失败')
 | 
			
		||||
    })
 | 
			
		||||
  },
 | 
			
		||||
  beforeDestroy() {
 | 
			
		||||
    window.removeEventListener('keydown', this.preventDefaultSave)
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    preventDefaultSave(e) {
 | 
			
		||||
      if (e.key === 's' && (e.metaKey || e.ctrlKey)) {
 | 
			
		||||
        e.preventDefault()
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    onOpen() {
 | 
			
		||||
      loadBeautifier(btf => {
 | 
			
		||||
        beautifier = btf
 | 
			
		||||
        this.beautifierJson = beautifier.js(this.jsonStr, beautifierConf.js)
 | 
			
		||||
 | 
			
		||||
        loadMonaco(val => {
 | 
			
		||||
          monaco = val
 | 
			
		||||
          this.setEditorValue('editorJson', this.beautifierJson)
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    onClose() {},
 | 
			
		||||
    setEditorValue(id, codeStr) {
 | 
			
		||||
      if (this.jsonEditor) {
 | 
			
		||||
        this.jsonEditor.setValue(codeStr)
 | 
			
		||||
      } else {
 | 
			
		||||
        this.jsonEditor = monaco.editor.create(document.getElementById(id), {
 | 
			
		||||
          value: codeStr,
 | 
			
		||||
          theme: 'vs-dark',
 | 
			
		||||
          language: 'json',
 | 
			
		||||
          automaticLayout: true
 | 
			
		||||
        })
 | 
			
		||||
        // ctrl + s 刷新
 | 
			
		||||
        this.jsonEditor.onKeyDown(e => {
 | 
			
		||||
          if (e.keyCode === 49 && (e.metaKey || e.ctrlKey)) {
 | 
			
		||||
            this.refresh()
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    exportJsonFile() {
 | 
			
		||||
      this.$prompt('文件名:', '导出文件', {
 | 
			
		||||
        inputValue: `${+new Date()}.json`,
 | 
			
		||||
        closeOnClickModal: false,
 | 
			
		||||
        inputPlaceholder: '请输入文件名'
 | 
			
		||||
      }).then(({ value }) => {
 | 
			
		||||
        if (!value) value = `${+new Date()}.json`
 | 
			
		||||
        const codeStr = this.jsonEditor.getValue()
 | 
			
		||||
        const blob = new Blob([codeStr], { type: 'text/plain;charset=utf-8' })
 | 
			
		||||
        saveAs(blob, value)
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    refresh() {
 | 
			
		||||
      try {
 | 
			
		||||
        this.$emit('refresh', JSON.parse(this.jsonEditor.getValue()))
 | 
			
		||||
      } catch (error) {
 | 
			
		||||
        this.$notify({
 | 
			
		||||
          title: '错误',
 | 
			
		||||
          message: 'JSON格式错误,请检查',
 | 
			
		||||
          type: 'error'
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
@import '@/styles/mixin.scss';
 | 
			
		||||
 | 
			
		||||
:deep(.el-drawer__header) {
 | 
			
		||||
  display: none;
 | 
			
		||||
}
 | 
			
		||||
@include action-bar;
 | 
			
		||||
 | 
			
		||||
.json-editor{
 | 
			
		||||
  height: calc(100vh - 33px);
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,116 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <el-dialog
 | 
			
		||||
      v-bind="$attrs"
 | 
			
		||||
      title="外部资源引用"
 | 
			
		||||
      width="600px"
 | 
			
		||||
      :close-on-click-modal="false"
 | 
			
		||||
      v-on="$listeners"
 | 
			
		||||
      @open="onOpen"
 | 
			
		||||
      @close="onClose"
 | 
			
		||||
    >
 | 
			
		||||
      <el-input
 | 
			
		||||
        v-for="(item, index) in resources"
 | 
			
		||||
        :key="index"
 | 
			
		||||
        v-model="resources[index]"
 | 
			
		||||
        class="url-item"
 | 
			
		||||
        placeholder="请输入 css 或 js 资源路径"
 | 
			
		||||
        prefix-icon="el-icon-link"
 | 
			
		||||
        clearable
 | 
			
		||||
      >
 | 
			
		||||
        <el-button
 | 
			
		||||
          slot="append"
 | 
			
		||||
          icon="el-icon-delete"
 | 
			
		||||
          @click="deleteOne(index)"
 | 
			
		||||
        />
 | 
			
		||||
      </el-input>
 | 
			
		||||
      <el-button-group class="add-item">
 | 
			
		||||
        <el-button
 | 
			
		||||
          plain
 | 
			
		||||
          @click="addOne('https://lib.baomitu.com/jquery/1.8.3/jquery.min.js')"
 | 
			
		||||
        >
 | 
			
		||||
          jQuery1.8.3
 | 
			
		||||
        </el-button>
 | 
			
		||||
        <el-button
 | 
			
		||||
          plain
 | 
			
		||||
          @click="addOne('https://unpkg.com/http-vue-loader')"
 | 
			
		||||
        >
 | 
			
		||||
          http-vue-loader
 | 
			
		||||
        </el-button>
 | 
			
		||||
        <el-button
 | 
			
		||||
          icon="el-icon-circle-plus-outline"
 | 
			
		||||
          plain
 | 
			
		||||
          @click="addOne('')"
 | 
			
		||||
        >
 | 
			
		||||
          添加其他
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </el-button-group>
 | 
			
		||||
      <div slot="footer">
 | 
			
		||||
        <el-button @click="close">
 | 
			
		||||
          取消
 | 
			
		||||
        </el-button>
 | 
			
		||||
        <el-button
 | 
			
		||||
          type="primary"
 | 
			
		||||
          @click="handelConfirm"
 | 
			
		||||
        >
 | 
			
		||||
          确定
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
import { deepClone } from '@/utils'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  components: {},
 | 
			
		||||
  inheritAttrs: false,
 | 
			
		||||
  props: ['originResource'],
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      resources: null
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  computed: {},
 | 
			
		||||
  watch: {},
 | 
			
		||||
  created() {},
 | 
			
		||||
  mounted() {},
 | 
			
		||||
  methods: {
 | 
			
		||||
    onOpen() {
 | 
			
		||||
      this.resources = this.originResource.length ? deepClone(this.originResource) : ['']
 | 
			
		||||
    },
 | 
			
		||||
    onClose() {
 | 
			
		||||
    },
 | 
			
		||||
    close() {
 | 
			
		||||
      this.$emit('update:visible', false)
 | 
			
		||||
    },
 | 
			
		||||
    handelConfirm() {
 | 
			
		||||
      const results = this.resources.filter(item => !!item) || []
 | 
			
		||||
      this.$emit('save', results)
 | 
			
		||||
      this.close()
 | 
			
		||||
      if (results.length) {
 | 
			
		||||
        this.resources = results
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    deleteOne(index) {
 | 
			
		||||
      this.resources.splice(index, 1)
 | 
			
		||||
    },
 | 
			
		||||
    addOne(url) {
 | 
			
		||||
      if (this.resources.indexOf(url) > -1) {
 | 
			
		||||
        this.$message('资源已存在')
 | 
			
		||||
      } else {
 | 
			
		||||
        this.resources.push(url)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
.add-item{
 | 
			
		||||
  margin-top: 8px;
 | 
			
		||||
}
 | 
			
		||||
.url-item{
 | 
			
		||||
  margin-bottom: 12px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,158 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <el-dialog
 | 
			
		||||
      v-bind="$attrs"
 | 
			
		||||
      :close-on-click-modal="false"
 | 
			
		||||
      :modal-append-to-body="false"
 | 
			
		||||
      v-on="$listeners"
 | 
			
		||||
      @open="onOpen"
 | 
			
		||||
      @close="onClose"
 | 
			
		||||
    >
 | 
			
		||||
      <el-row :gutter="0">
 | 
			
		||||
        <el-form
 | 
			
		||||
          ref="elForm"
 | 
			
		||||
          :model="formData"
 | 
			
		||||
          :rules="rules"
 | 
			
		||||
          size="small"
 | 
			
		||||
          label-width="100px"
 | 
			
		||||
        >
 | 
			
		||||
          <el-col :span="24">
 | 
			
		||||
            <el-form-item
 | 
			
		||||
              label="选项名"
 | 
			
		||||
              prop="label"
 | 
			
		||||
            >
 | 
			
		||||
              <el-input
 | 
			
		||||
                v-model="formData.label"
 | 
			
		||||
                placeholder="请输入选项名"
 | 
			
		||||
                clearable
 | 
			
		||||
              />
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
          </el-col>
 | 
			
		||||
          <el-col :span="24">
 | 
			
		||||
            <el-form-item
 | 
			
		||||
              label="选项值"
 | 
			
		||||
              prop="value"
 | 
			
		||||
            >
 | 
			
		||||
              <el-input
 | 
			
		||||
                v-model="formData.value"
 | 
			
		||||
                placeholder="请输入选项值"
 | 
			
		||||
                clearable
 | 
			
		||||
              >
 | 
			
		||||
                <el-select
 | 
			
		||||
                  slot="append"
 | 
			
		||||
                  v-model="dataType"
 | 
			
		||||
                  :style="{width: '100px'}"
 | 
			
		||||
                >
 | 
			
		||||
                  <el-option
 | 
			
		||||
                    v-for="(item, index) in dataTypeOptions"
 | 
			
		||||
                    :key="index"
 | 
			
		||||
                    :label="item.label"
 | 
			
		||||
                    :value="item.value"
 | 
			
		||||
                    :disabled="item.disabled"
 | 
			
		||||
                  />
 | 
			
		||||
                </el-select>
 | 
			
		||||
              </el-input>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
          </el-col>
 | 
			
		||||
        </el-form>
 | 
			
		||||
      </el-row>
 | 
			
		||||
      <div slot="footer">
 | 
			
		||||
        <el-button
 | 
			
		||||
          type="primary"
 | 
			
		||||
          @click="handelConfirm"
 | 
			
		||||
        >
 | 
			
		||||
          确定
 | 
			
		||||
        </el-button>
 | 
			
		||||
        <el-button @click="close">
 | 
			
		||||
          取消
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
import { isNumberStr } from '@/utils'
 | 
			
		||||
import { getTreeNodeId, saveTreeNodeId } from '@/utils/db'
 | 
			
		||||
 | 
			
		||||
const id = getTreeNodeId()
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  components: {},
 | 
			
		||||
  inheritAttrs: false,
 | 
			
		||||
  props: [],
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      id,
 | 
			
		||||
      formData: {
 | 
			
		||||
        label: undefined,
 | 
			
		||||
        value: undefined
 | 
			
		||||
      },
 | 
			
		||||
      rules: {
 | 
			
		||||
        label: [
 | 
			
		||||
          {
 | 
			
		||||
            required: true,
 | 
			
		||||
            message: '请输入选项名',
 | 
			
		||||
            trigger: 'blur'
 | 
			
		||||
          }
 | 
			
		||||
        ],
 | 
			
		||||
        value: [
 | 
			
		||||
          {
 | 
			
		||||
            required: true,
 | 
			
		||||
            message: '请输入选项值',
 | 
			
		||||
            trigger: 'blur'
 | 
			
		||||
          }
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      dataType: 'string',
 | 
			
		||||
      dataTypeOptions: [
 | 
			
		||||
        {
 | 
			
		||||
          label: '字符串',
 | 
			
		||||
          value: 'string'
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          label: '数字',
 | 
			
		||||
          value: 'number'
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  computed: {},
 | 
			
		||||
  watch: {
 | 
			
		||||
    // eslint-disable-next-line func-names
 | 
			
		||||
    'formData.value': function (val) {
 | 
			
		||||
      this.dataType = isNumberStr(val) ? 'number' : 'string'
 | 
			
		||||
    },
 | 
			
		||||
    id(val) {
 | 
			
		||||
      saveTreeNodeId(val)
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  created() {},
 | 
			
		||||
  mounted() {},
 | 
			
		||||
  methods: {
 | 
			
		||||
    onOpen() {
 | 
			
		||||
      this.formData = {
 | 
			
		||||
        label: undefined,
 | 
			
		||||
        value: undefined
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    onClose() {},
 | 
			
		||||
    close() {
 | 
			
		||||
      this.$emit('update:visible', false)
 | 
			
		||||
    },
 | 
			
		||||
    handelConfirm() {
 | 
			
		||||
      this.$refs.elForm.validate(valid => {
 | 
			
		||||
        if (!valid) return
 | 
			
		||||
        if (this.dataType === 'number') {
 | 
			
		||||
          this.formData.value = parseFloat(this.formData.value)
 | 
			
		||||
        }
 | 
			
		||||
        this.formData.id = this.id++
 | 
			
		||||
        this.$emit('commit', this.formData)
 | 
			
		||||
        this.close()
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,470 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="container">
 | 
			
		||||
    <div class="left-board">
 | 
			
		||||
      <div class="logo-wrapper">
 | 
			
		||||
        <div class="logo">
 | 
			
		||||
          <img :src="logo" alt="logo"> Form Generator
 | 
			
		||||
          <a class="github" href="https://github.com/JakHuang/form-generator" target="_blank">
 | 
			
		||||
            <img src="https://github.githubassets.com/pinned-octocat.svg" alt>
 | 
			
		||||
          </a>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <el-scrollbar class="left-scrollbar">
 | 
			
		||||
        <div class="components-list">
 | 
			
		||||
          <div v-for="(item, listIndex) in leftComponents" :key="listIndex">
 | 
			
		||||
            <div class="components-title">
 | 
			
		||||
              <svg-icon icon-class="component" />
 | 
			
		||||
              {{ item.title }}
 | 
			
		||||
            </div>
 | 
			
		||||
            <draggable
 | 
			
		||||
              class="components-draggable"
 | 
			
		||||
              :list="item.list"
 | 
			
		||||
              :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
 | 
			
		||||
              :clone="cloneComponent"
 | 
			
		||||
              draggable=".components-item"
 | 
			
		||||
              :sort="false"
 | 
			
		||||
              @end="onEnd"
 | 
			
		||||
            >
 | 
			
		||||
              <div
 | 
			
		||||
                v-for="(element, index) in item.list"
 | 
			
		||||
                :key="index"
 | 
			
		||||
                class="components-item"
 | 
			
		||||
                @click="addComponent(element)"
 | 
			
		||||
              >
 | 
			
		||||
                <div class="components-body">
 | 
			
		||||
                  <svg-icon :icon-class="element.__config__.tagIcon" />
 | 
			
		||||
                  {{ element.__config__.label }}
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
            </draggable>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </el-scrollbar>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="center-board">
 | 
			
		||||
      <div class="action-bar">
 | 
			
		||||
<!--        <el-button icon="el-icon-video-play" type="text" @click="run">-->
 | 
			
		||||
<!--          运行-->
 | 
			
		||||
<!--        </el-button>-->
 | 
			
		||||
        <el-button icon="el-icon-view" type="text" @click="showJson">
 | 
			
		||||
          查看json
 | 
			
		||||
        </el-button>
 | 
			
		||||
        <el-button icon="el-icon-download" type="text" @click="download">
 | 
			
		||||
          导出vue文件
 | 
			
		||||
        </el-button>
 | 
			
		||||
        <el-button class="copy-btn-main" icon="el-icon-document-copy" type="text" @click="copy">
 | 
			
		||||
          复制代码
 | 
			
		||||
        </el-button>
 | 
			
		||||
        <el-button class="delete-btn" icon="el-icon-delete" type="text" @click="empty">
 | 
			
		||||
          清空
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
      <el-scrollbar class="center-scrollbar">
 | 
			
		||||
        <el-row class="center-board-row" :gutter="formConf.gutter">
 | 
			
		||||
          <el-form
 | 
			
		||||
            :size="formConf.size"
 | 
			
		||||
            :label-position="formConf.labelPosition"
 | 
			
		||||
            :disabled="formConf.disabled"
 | 
			
		||||
            :label-width="formConf.labelWidth + 'px'"
 | 
			
		||||
          >
 | 
			
		||||
            <draggable class="drawing-board" :list="drawingList" :animation="340" group="componentsGroup">
 | 
			
		||||
              <draggable-item
 | 
			
		||||
                v-for="(item, index) in drawingList"
 | 
			
		||||
                :key="item.renderKey"
 | 
			
		||||
                :drawing-list="drawingList"
 | 
			
		||||
                :current-item="item"
 | 
			
		||||
                :index="index"
 | 
			
		||||
                :active-id="activeId"
 | 
			
		||||
                :form-conf="formConf"
 | 
			
		||||
                @activeItem="activeFormItem"
 | 
			
		||||
                @copyItem="drawingItemCopy"
 | 
			
		||||
                @deleteItem="drawingItemDelete"
 | 
			
		||||
              />
 | 
			
		||||
            </draggable>
 | 
			
		||||
            <div v-show="!drawingList.length" class="empty-info">
 | 
			
		||||
              从左侧拖入或点选组件进行表单设计
 | 
			
		||||
            </div>
 | 
			
		||||
          </el-form>
 | 
			
		||||
        </el-row>
 | 
			
		||||
      </el-scrollbar>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <right-panel
 | 
			
		||||
      :active-data="activeData"
 | 
			
		||||
      :form-conf="formConf"
 | 
			
		||||
      :show-field="!!drawingList.length"
 | 
			
		||||
      @tag-change="tagChange"
 | 
			
		||||
      @fetch-data="fetchData"
 | 
			
		||||
    />
 | 
			
		||||
 | 
			
		||||
    <form-drawer
 | 
			
		||||
      :visible.sync="drawerVisible"
 | 
			
		||||
      :form-data="formData"
 | 
			
		||||
      size="100%"
 | 
			
		||||
      :generate-conf="generateConf"
 | 
			
		||||
    />
 | 
			
		||||
    <json-drawer
 | 
			
		||||
      size="60%"
 | 
			
		||||
      :visible.sync="jsonDrawerVisible"
 | 
			
		||||
      :json-str="JSON.stringify(formData)"
 | 
			
		||||
      @refresh="refreshJson"
 | 
			
		||||
    />
 | 
			
		||||
    <code-type-dialog
 | 
			
		||||
      :visible.sync="dialogVisible"
 | 
			
		||||
      title="选择生成类型"
 | 
			
		||||
      :show-file-name="showFileName"
 | 
			
		||||
      @confirm="generate"
 | 
			
		||||
    />
 | 
			
		||||
    <input id="copyNode" type="hidden">
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import draggable from 'vuedraggable'
 | 
			
		||||
import { debounce } from 'throttle-debounce'
 | 
			
		||||
import { saveAs } from 'file-saver'
 | 
			
		||||
import ClipboardJS from 'clipboard'
 | 
			
		||||
import render from '@/components/render/render'
 | 
			
		||||
import FormDrawer from './FormDrawer'
 | 
			
		||||
import JsonDrawer from './JsonDrawer'
 | 
			
		||||
import RightPanel from './RightPanel'
 | 
			
		||||
import {
 | 
			
		||||
  inputComponents, selectComponents, layoutComponents, formConf
 | 
			
		||||
} from '@/components/generator/config'
 | 
			
		||||
import {
 | 
			
		||||
  beautifierConf, titleCase, deepClone
 | 
			
		||||
} from '@/utils'
 | 
			
		||||
import {
 | 
			
		||||
  makeUpHtml, vueTemplate, vueScript, cssStyle
 | 
			
		||||
} from '@/components/generator/html'
 | 
			
		||||
import { makeUpJs } from '@/components/generator/js'
 | 
			
		||||
import { makeUpCss } from '@/components/generator/css'
 | 
			
		||||
import drawingDefalut from '@/components/generator/drawingDefalut'
 | 
			
		||||
import logo from '@/assets/logo/logo.png'
 | 
			
		||||
import CodeTypeDialog from './CodeTypeDialog'
 | 
			
		||||
import DraggableItem from './DraggableItem'
 | 
			
		||||
import {
 | 
			
		||||
  getDrawingList, saveDrawingList, getIdGlobal, saveIdGlobal, getFormConf
 | 
			
		||||
} from '@/utils/db'
 | 
			
		||||
import loadBeautifier from '@/utils/loadBeautifier'
 | 
			
		||||
 | 
			
		||||
let beautifier
 | 
			
		||||
const emptyActiveData = { style: {}, autosize: {} }
 | 
			
		||||
let oldActiveId
 | 
			
		||||
let tempActiveData
 | 
			
		||||
const drawingListInDB = getDrawingList()
 | 
			
		||||
const formConfInDB = getFormConf()
 | 
			
		||||
const idGlobal = getIdGlobal()
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "InfraBuild",
 | 
			
		||||
  components: {
 | 
			
		||||
    draggable,
 | 
			
		||||
    render,
 | 
			
		||||
    FormDrawer,
 | 
			
		||||
    JsonDrawer,
 | 
			
		||||
    RightPanel,
 | 
			
		||||
    CodeTypeDialog,
 | 
			
		||||
    DraggableItem
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      logo,
 | 
			
		||||
      idGlobal,
 | 
			
		||||
      formConf,
 | 
			
		||||
      inputComponents,
 | 
			
		||||
      selectComponents,
 | 
			
		||||
      layoutComponents,
 | 
			
		||||
      labelWidth: 100,
 | 
			
		||||
      drawingList: drawingDefalut,
 | 
			
		||||
      drawingData: {},
 | 
			
		||||
      activeId: drawingDefalut[0].formId,
 | 
			
		||||
      drawerVisible: false,
 | 
			
		||||
      formData: {},
 | 
			
		||||
      dialogVisible: false,
 | 
			
		||||
      jsonDrawerVisible: false,
 | 
			
		||||
      generateConf: null,
 | 
			
		||||
      showFileName: false,
 | 
			
		||||
      activeData: drawingDefalut[0],
 | 
			
		||||
      saveDrawingListDebounce: debounce(340, saveDrawingList),
 | 
			
		||||
      saveIdGlobalDebounce: debounce(340, saveIdGlobal),
 | 
			
		||||
      leftComponents: [
 | 
			
		||||
        {
 | 
			
		||||
          title: '输入型组件',
 | 
			
		||||
          list: inputComponents
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          title: '选择型组件',
 | 
			
		||||
          list: selectComponents
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          title: '布局型组件',
 | 
			
		||||
          list: layoutComponents
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
  },
 | 
			
		||||
  watch: {
 | 
			
		||||
    // eslint-disable-next-line func-names
 | 
			
		||||
    'activeData.__config__.label': function (val, oldVal) {
 | 
			
		||||
      if (
 | 
			
		||||
        this.activeData.placeholder === undefined
 | 
			
		||||
        || !this.activeData.__config__.tag
 | 
			
		||||
        || oldActiveId !== this.activeId
 | 
			
		||||
      ) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
      this.activeData.placeholder = this.activeData.placeholder.replace(oldVal, '') + val
 | 
			
		||||
    },
 | 
			
		||||
    activeId: {
 | 
			
		||||
      handler(val) {
 | 
			
		||||
        oldActiveId = val
 | 
			
		||||
      },
 | 
			
		||||
      immediate: true
 | 
			
		||||
    },
 | 
			
		||||
    drawingList: {
 | 
			
		||||
      handler(val) {
 | 
			
		||||
        this.saveDrawingListDebounce(val)
 | 
			
		||||
        if (val.length === 0) this.idGlobal = 100
 | 
			
		||||
      },
 | 
			
		||||
      deep: true
 | 
			
		||||
    },
 | 
			
		||||
    idGlobal: {
 | 
			
		||||
      handler(val) {
 | 
			
		||||
        this.saveIdGlobalDebounce(val)
 | 
			
		||||
      },
 | 
			
		||||
      immediate: true
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  mounted() {
 | 
			
		||||
    if (Array.isArray(drawingListInDB) && drawingListInDB.length > 0) {
 | 
			
		||||
      this.drawingList = drawingListInDB
 | 
			
		||||
    } else {
 | 
			
		||||
      this.drawingList = drawingDefalut
 | 
			
		||||
    }
 | 
			
		||||
    this.activeFormItem(this.drawingList[0])
 | 
			
		||||
    if (formConfInDB) {
 | 
			
		||||
      this.formConf = formConfInDB
 | 
			
		||||
    }
 | 
			
		||||
    loadBeautifier(btf => {
 | 
			
		||||
      beautifier = btf
 | 
			
		||||
    })
 | 
			
		||||
    const clipboard = new ClipboardJS('#copyNode', {
 | 
			
		||||
      text: trigger => {
 | 
			
		||||
        const codeStr = this.generateCode()
 | 
			
		||||
        this.$notify({
 | 
			
		||||
          title: '成功',
 | 
			
		||||
          message: '代码已复制到剪切板,可粘贴。',
 | 
			
		||||
          type: 'success'
 | 
			
		||||
        })
 | 
			
		||||
        return codeStr
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    clipboard.on('error', e => {
 | 
			
		||||
      this.$message.error('代码复制失败')
 | 
			
		||||
    })
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    setObjectValueReduce(obj, strKeys, data) {
 | 
			
		||||
      const arr = strKeys.split('.')
 | 
			
		||||
      arr.reduce((pre, item, i) => {
 | 
			
		||||
        if (arr.length === i + 1) {
 | 
			
		||||
          pre[item] = data
 | 
			
		||||
        } else if (pre[item]===undefined) {
 | 
			
		||||
          pre[item] = {}
 | 
			
		||||
        }
 | 
			
		||||
        return pre[item]
 | 
			
		||||
      }, obj)
 | 
			
		||||
    },
 | 
			
		||||
    setRespData(component, resp) {
 | 
			
		||||
      const { dataPath, renderKey, dataConsumer } = component.__config__
 | 
			
		||||
      if (!dataPath || !dataConsumer) return
 | 
			
		||||
      const respData = dataPath.split('.').reduce((pre, item) => pre[item], resp)
 | 
			
		||||
 | 
			
		||||
      // 将请求回来的数据,赋值到指定属性。
 | 
			
		||||
      // 以el-tabel为例,根据Element文档,应该将数据赋值给el-tabel的data属性,所以dataConsumer的值应为'data';
 | 
			
		||||
      // 此时赋值代码可写成 component[dataConsumer] = respData;
 | 
			
		||||
      // 但为支持更深层级的赋值(如:dataConsumer的值为'options.data'),使用setObjectValueReduce
 | 
			
		||||
      this.setObjectValueReduce(component, dataConsumer, respData)
 | 
			
		||||
      const i = this.drawingList.findIndex(item => item.__config__.renderKey === renderKey)
 | 
			
		||||
      if (i > -1) this.$set(this.drawingList, i, component)
 | 
			
		||||
    },
 | 
			
		||||
    fetchData(component) {
 | 
			
		||||
      const { dataType, method, url } = component.__config__
 | 
			
		||||
      if (dataType === 'dynamic' && method && url) {
 | 
			
		||||
        this.setLoading(component, true)
 | 
			
		||||
        this.$axios({
 | 
			
		||||
          method,
 | 
			
		||||
          url
 | 
			
		||||
        }).then(resp => {
 | 
			
		||||
          this.setLoading(component, false)
 | 
			
		||||
          this.setRespData(component, resp)
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    setLoading(component, val) {
 | 
			
		||||
      const { directives } = component
 | 
			
		||||
      if (Array.isArray(directives)) {
 | 
			
		||||
        const t = directives.find(d => d.name === 'loading')
 | 
			
		||||
        if (t) t.value = val
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    activeFormItem(currentItem) {
 | 
			
		||||
      this.activeData = currentItem
 | 
			
		||||
      this.activeId = currentItem.__config__.formId
 | 
			
		||||
    },
 | 
			
		||||
    onEnd(obj) {
 | 
			
		||||
      if (obj.from !== obj.to) {
 | 
			
		||||
        this.fetchData(tempActiveData)
 | 
			
		||||
        this.activeData = tempActiveData
 | 
			
		||||
        this.activeId = this.idGlobal
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    addComponent(item) {
 | 
			
		||||
      const clone = this.cloneComponent(item)
 | 
			
		||||
      this.fetchData(clone)
 | 
			
		||||
      this.drawingList.push(clone)
 | 
			
		||||
      this.activeFormItem(clone)
 | 
			
		||||
    },
 | 
			
		||||
    cloneComponent(origin) {
 | 
			
		||||
      const clone = deepClone(origin)
 | 
			
		||||
      const config = clone.__config__
 | 
			
		||||
      config.span = this.formConf.span // 生成代码时,会根据span做精简判断
 | 
			
		||||
      this.createIdAndKey(clone)
 | 
			
		||||
      clone.placeholder !== undefined && (clone.placeholder += config.label)
 | 
			
		||||
      tempActiveData = clone
 | 
			
		||||
      return tempActiveData
 | 
			
		||||
    },
 | 
			
		||||
    createIdAndKey(item) {
 | 
			
		||||
      const config = item.__config__
 | 
			
		||||
      config.formId = ++this.idGlobal
 | 
			
		||||
      config.renderKey = `${config.formId}${+new Date()}` // 改变renderKey后可以实现强制更新组件
 | 
			
		||||
      if (config.layout === 'colFormItem') {
 | 
			
		||||
        item.__vModel__ = `field${this.idGlobal}`
 | 
			
		||||
      } else if (config.layout === 'rowFormItem') {
 | 
			
		||||
        config.componentName = `row${this.idGlobal}`
 | 
			
		||||
        !Array.isArray(config.children) && (config.children = [])
 | 
			
		||||
        delete config.label // rowFormItem无需配置label属性
 | 
			
		||||
      }
 | 
			
		||||
      if (Array.isArray(config.children)) {
 | 
			
		||||
        config.children = config.children.map(childItem => this.createIdAndKey(childItem))
 | 
			
		||||
      }
 | 
			
		||||
      return item
 | 
			
		||||
    },
 | 
			
		||||
    AssembleFormData() {
 | 
			
		||||
      this.formData = {
 | 
			
		||||
        fields: deepClone(this.drawingList),
 | 
			
		||||
        ...this.formConf
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    generate(data) {
 | 
			
		||||
      const func = this[`exec${titleCase(this.operationType)}`]
 | 
			
		||||
      this.generateConf = data
 | 
			
		||||
      func && func(data)
 | 
			
		||||
    },
 | 
			
		||||
    execRun(data) {
 | 
			
		||||
      this.AssembleFormData()
 | 
			
		||||
      this.drawerVisible = true
 | 
			
		||||
    },
 | 
			
		||||
    execDownload(data) {
 | 
			
		||||
      const codeStr = this.generateCode()
 | 
			
		||||
      const blob = new Blob([codeStr], { type: 'text/plain;charset=utf-8' })
 | 
			
		||||
      saveAs(blob, data.fileName)
 | 
			
		||||
    },
 | 
			
		||||
    execCopy(data) {
 | 
			
		||||
      document.getElementById('copyNode').click()
 | 
			
		||||
    },
 | 
			
		||||
    empty() {
 | 
			
		||||
      this.$confirm('确定要清空所有组件吗?', '提示', { type: 'warning' }).then(
 | 
			
		||||
        () => {
 | 
			
		||||
          this.drawingList = []
 | 
			
		||||
          this.idGlobal = 100
 | 
			
		||||
        }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    drawingItemCopy(item, list) {
 | 
			
		||||
      let clone = deepClone(item)
 | 
			
		||||
      clone = this.createIdAndKey(clone)
 | 
			
		||||
      list.push(clone)
 | 
			
		||||
      this.activeFormItem(clone)
 | 
			
		||||
    },
 | 
			
		||||
    drawingItemDelete(index, list) {
 | 
			
		||||
      list.splice(index, 1)
 | 
			
		||||
      this.$nextTick(() => {
 | 
			
		||||
        const len = this.drawingList.length
 | 
			
		||||
        if (len) {
 | 
			
		||||
          this.activeFormItem(this.drawingList[len - 1])
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    generateCode() {
 | 
			
		||||
      const { type } = this.generateConf
 | 
			
		||||
      this.AssembleFormData()
 | 
			
		||||
      const script = vueScript(makeUpJs(this.formData, type))
 | 
			
		||||
      const html = vueTemplate(makeUpHtml(this.formData, type))
 | 
			
		||||
      const css = cssStyle(makeUpCss(this.formData))
 | 
			
		||||
      return beautifier.html(html + script + css, beautifierConf.html)
 | 
			
		||||
    },
 | 
			
		||||
    showJson() {
 | 
			
		||||
      this.AssembleFormData()
 | 
			
		||||
      this.jsonDrawerVisible = true
 | 
			
		||||
    },
 | 
			
		||||
    download() {
 | 
			
		||||
      this.dialogVisible = true
 | 
			
		||||
      this.showFileName = true
 | 
			
		||||
      this.operationType = 'download'
 | 
			
		||||
    },
 | 
			
		||||
    run() {
 | 
			
		||||
      this.dialogVisible = true
 | 
			
		||||
      this.showFileName = false
 | 
			
		||||
      this.operationType = 'run'
 | 
			
		||||
    },
 | 
			
		||||
    copy() {
 | 
			
		||||
      this.dialogVisible = true
 | 
			
		||||
      this.showFileName = false
 | 
			
		||||
      this.operationType = 'copy'
 | 
			
		||||
    },
 | 
			
		||||
    tagChange(newTag) {
 | 
			
		||||
      newTag = this.cloneComponent(newTag)
 | 
			
		||||
      const config = newTag.__config__
 | 
			
		||||
      newTag.__vModel__ = this.activeData.__vModel__
 | 
			
		||||
      config.formId = this.activeId
 | 
			
		||||
      config.span = this.activeData.__config__.span
 | 
			
		||||
      this.activeData.__config__.tag = config.tag
 | 
			
		||||
      this.activeData.__config__.tagIcon = config.tagIcon
 | 
			
		||||
      this.activeData.__config__.document = config.document
 | 
			
		||||
      if (typeof this.activeData.__config__.defaultValue === typeof config.defaultValue) {
 | 
			
		||||
        config.defaultValue = this.activeData.__config__.defaultValue
 | 
			
		||||
      }
 | 
			
		||||
      Object.keys(newTag).forEach(key => {
 | 
			
		||||
        if (this.activeData[key] !== undefined) {
 | 
			
		||||
          newTag[key] = this.activeData[key]
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
      this.activeData = newTag
 | 
			
		||||
      this.updateDrawingList(newTag, this.drawingList)
 | 
			
		||||
    },
 | 
			
		||||
    updateDrawingList(newTag, list) {
 | 
			
		||||
      const index = list.findIndex(item => item.__config__.formId === this.activeId)
 | 
			
		||||
      if (index > -1) {
 | 
			
		||||
        list.splice(index, 1, newTag)
 | 
			
		||||
      } else {
 | 
			
		||||
        list.forEach(item => {
 | 
			
		||||
          if (Array.isArray(item.__config__.children)) this.updateDrawingList(newTag, item.__config__.children)
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    refreshJson(data) {
 | 
			
		||||
      this.drawingList = deepClone(data.fields)
 | 
			
		||||
      delete data.fields
 | 
			
		||||
      this.formConf = data
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang='scss'>
 | 
			
		||||
@import '@/styles/home';
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,19 +0,0 @@
 | 
			
		||||
import Vue from 'vue'
 | 
			
		||||
import App from './App.vue'
 | 
			
		||||
import router from '@/router'
 | 
			
		||||
import '@/styles/index.scss'
 | 
			
		||||
import '@/assets/icons'
 | 
			
		||||
import axios from 'axios'
 | 
			
		||||
import Tinymce from '@/components/tinymce/index.vue'
 | 
			
		||||
 | 
			
		||||
Vue.component('tinymce', Tinymce)
 | 
			
		||||
 | 
			
		||||
Vue.config.productionTip = false
 | 
			
		||||
Vue.prototype.$axios = axios
 | 
			
		||||
 | 
			
		||||
// add by 芋道源码:引用自 https://github.com/JakHuang/form-generator/tree/dev/src/views/index
 | 
			
		||||
 | 
			
		||||
new Vue({
 | 
			
		||||
  router,
 | 
			
		||||
  render: h => h(App)
 | 
			
		||||
}).$mount('#app')
 | 
			
		||||
@@ -1,67 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <el-form ref="basicInfoForm" :model="info" :rules="rules" label-width="150px">
 | 
			
		||||
    <el-row>
 | 
			
		||||
      <el-col :span="12">
 | 
			
		||||
        <el-form-item label="表名称" prop="tableName">
 | 
			
		||||
          <el-input placeholder="请输入仓库名称" v-model="info.tableName" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <el-col :span="12">
 | 
			
		||||
        <el-form-item label="表描述" prop="tableComment">
 | 
			
		||||
          <el-input placeholder="请输入" v-model="info.tableComment" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
 | 
			
		||||
      <el-col :span="12">
 | 
			
		||||
        <el-form-item prop="className">
 | 
			
		||||
          <span slot="label">
 | 
			
		||||
            实体类名称
 | 
			
		||||
            <el-tooltip content="默认去除表名的前缀。如果存在重复,则需要手动添加前缀,避免 MyBatis 报 Alias 重复的问题。" placement="top">
 | 
			
		||||
              <i class="el-icon-question"></i>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </span>
 | 
			
		||||
          <el-input placeholder="请输入" v-model="info.className" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <el-col :span="12">
 | 
			
		||||
        <el-form-item label="作者" prop="author">
 | 
			
		||||
          <el-input placeholder="请输入" v-model="info.author" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <el-col :span="24">
 | 
			
		||||
        <el-form-item label="备注" prop="remark">
 | 
			
		||||
          <el-input type="textarea" :rows="3" v-model="info.remark"></el-input>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
    </el-row>
 | 
			
		||||
  </el-form>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
  name: "BasicInfoForm",
 | 
			
		||||
  props: {
 | 
			
		||||
    info: {
 | 
			
		||||
      type: Object,
 | 
			
		||||
      default: null
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      rules: {
 | 
			
		||||
        tableName: [
 | 
			
		||||
          { required: true, message: "请输入表名称", trigger: "blur" }
 | 
			
		||||
        ],
 | 
			
		||||
        tableComment: [
 | 
			
		||||
          { required: true, message: "请输入表描述", trigger: "blur" }
 | 
			
		||||
        ],
 | 
			
		||||
        className: [
 | 
			
		||||
          { required: true, message: "请输入实体类名称", trigger: "blur" }
 | 
			
		||||
        ],
 | 
			
		||||
        author: [
 | 
			
		||||
          { required: true, message: "请输入作者", trigger: "blur" }
 | 
			
		||||
        ]
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,235 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <el-card>
 | 
			
		||||
    <el-tabs v-model="activeName">
 | 
			
		||||
      <el-tab-pane label="基本信息" name="basic">
 | 
			
		||||
        <basic-info-form ref="basicInfo" :info="table" />
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
      <el-tab-pane label="字段信息" name="cloum">
 | 
			
		||||
        <el-table ref="dragTable" :data="columns" row-key="columnId" :max-height="tableHeight">
 | 
			
		||||
          <el-table-column
 | 
			
		||||
            label="字段列名"
 | 
			
		||||
            prop="columnName"
 | 
			
		||||
            min-width="10%"
 | 
			
		||||
            :show-overflow-tooltip="true"
 | 
			
		||||
          />
 | 
			
		||||
          <el-table-column label="字段描述" min-width="10%">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <el-input v-model="scope.row.columnComment"></el-input>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column
 | 
			
		||||
            label="物理类型"
 | 
			
		||||
            prop="dataType"
 | 
			
		||||
            min-width="10%"
 | 
			
		||||
            :show-overflow-tooltip="true"
 | 
			
		||||
          />
 | 
			
		||||
          <el-table-column label="Java类型" min-width="11%">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <el-select v-model="scope.row.javaType">
 | 
			
		||||
                <el-option label="Long" value="Long" />
 | 
			
		||||
                <el-option label="String" value="String" />
 | 
			
		||||
                <el-option label="Integer" value="Integer" />
 | 
			
		||||
                <el-option label="Double" value="Double" />
 | 
			
		||||
                <el-option label="BigDecimal" value="BigDecimal" />
 | 
			
		||||
                <el-option label="LocalDateTime" value="LocalDateTime" />
 | 
			
		||||
                <el-option label="Boolean" value="Boolean" />
 | 
			
		||||
              </el-select>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="java属性" min-width="10%">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <el-input v-model="scope.row.javaField"></el-input>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="插入" min-width="4%">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <el-checkbox true-label="true" false-label="false" v-model="scope.row.createOperation"></el-checkbox>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="编辑" min-width="4%">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <el-checkbox true-label="true" false-label="false" v-model="scope.row.updateOperation"></el-checkbox>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="列表" min-width="4%">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <el-checkbox true-label="true" false-label="false" v-model="scope.row.listOperationResult"></el-checkbox>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="查询" min-width="4%">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <el-checkbox true-label="true" false-label="false" v-model="scope.row.listOperation"></el-checkbox>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="查询方式" min-width="10%">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <el-select v-model="scope.row.listOperationCondition">
 | 
			
		||||
                <el-option label="=" value="=" />
 | 
			
		||||
                <el-option label="!=" value="!=" />
 | 
			
		||||
                <el-option label=">" value=">" />
 | 
			
		||||
                <el-option label=">=" value=">=" />
 | 
			
		||||
                <el-option label="<" value="<>" />
 | 
			
		||||
                <el-option label="<=" value="<=" />
 | 
			
		||||
                <el-option label="LIKE" value="LIKE" />
 | 
			
		||||
                <el-option label="BETWEEN" value="BETWEEN" />
 | 
			
		||||
              </el-select>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="允许空" min-width="5%">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <el-checkbox true-label="true" false-label="false" v-model="scope.row.nullable"></el-checkbox>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="显示类型" min-width="12%">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <el-select v-model="scope.row.htmlType">
 | 
			
		||||
                <el-option label="文本框" value="input" />
 | 
			
		||||
                <el-option label="文本域" value="textarea" />
 | 
			
		||||
                <el-option label="下拉框" value="select" />
 | 
			
		||||
                <el-option label="单选框" value="radio" />
 | 
			
		||||
                <el-option label="复选框" value="checkbox" />
 | 
			
		||||
                <el-option label="日期控件" value="datetime" />
 | 
			
		||||
                <el-option label="图片上传" value="imageUpload" />
 | 
			
		||||
                <el-option label="文件上传" value="fileUpload" />
 | 
			
		||||
                <el-option label="富文本控件" value="editor" />
 | 
			
		||||
              </el-select>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="字典类型" min-width="12%">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <el-select v-model="scope.row.dictType" clearable filterable placeholder="请选择">
 | 
			
		||||
                <el-option
 | 
			
		||||
                    v-for="dict in dictOptions"
 | 
			
		||||
                    :key="dict.id"
 | 
			
		||||
                    :label="dict.name"
 | 
			
		||||
                    :value="dict.type"
 | 
			
		||||
                />
 | 
			
		||||
              </el-select>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="示例" min-width="10%">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <el-input v-model="scope.row.example"></el-input>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table>
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
      <el-tab-pane label="生成信息" name="genInfo">
 | 
			
		||||
        <gen-info-form ref="genInfo" :info="table" :tables="tables" :menus="menus"/>
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
    </el-tabs>
 | 
			
		||||
    <el-form label-width="100px">
 | 
			
		||||
      <el-form-item style="text-align: center;margin-left:-100px;margin-top:10px;">
 | 
			
		||||
        <el-button type="primary" @click="submitForm()">提交</el-button>
 | 
			
		||||
        <el-button @click="close()">返回</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
  </el-card>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
import { getCodegenDetail, updateCodegen } from "@/api/infra/codegen";
 | 
			
		||||
import { listAllSimple as listAllSimpleDictType } from "@/api/system/dict/type";
 | 
			
		||||
import { listSimpleMenus } from "@/api/system/menu";
 | 
			
		||||
import basicInfoForm from "./basicInfoForm";
 | 
			
		||||
import genInfoForm from "./genInfoForm";
 | 
			
		||||
import Sortable from 'sortablejs'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "GenEdit",
 | 
			
		||||
  components: {
 | 
			
		||||
    basicInfoForm,
 | 
			
		||||
    genInfoForm
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 选中选项卡的 name
 | 
			
		||||
      activeName: "cloum",
 | 
			
		||||
      // 表格的高度
 | 
			
		||||
      tableHeight: document.documentElement.scrollHeight - 245 + "px",
 | 
			
		||||
      // 表信息
 | 
			
		||||
      tables: [],
 | 
			
		||||
      // 表列信息
 | 
			
		||||
      columns: [],
 | 
			
		||||
      // 字典信息
 | 
			
		||||
      dictOptions: [],
 | 
			
		||||
      // 菜单信息
 | 
			
		||||
      menus: [],
 | 
			
		||||
      // 表详细信息
 | 
			
		||||
      table: {}
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    const tableId = this.$route.params && this.$route.params.tableId;
 | 
			
		||||
    if (tableId) {
 | 
			
		||||
      // 获取表详细信息
 | 
			
		||||
      getCodegenDetail(tableId).then(res => {
 | 
			
		||||
        this.table = res.data.table;
 | 
			
		||||
        this.columns = res.data.columns;
 | 
			
		||||
      });
 | 
			
		||||
      /** 查询字典下拉列表 */
 | 
			
		||||
      listAllSimpleDictType().then(response => {
 | 
			
		||||
        this.dictOptions = response.data;
 | 
			
		||||
      });
 | 
			
		||||
      /** 查询菜单下拉列表 */
 | 
			
		||||
      listSimpleMenus().then(response => {
 | 
			
		||||
        this.menus = [];
 | 
			
		||||
        this.menus.push(...this.handleTree(response.data, "id"));
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm() {
 | 
			
		||||
      const basicForm = this.$refs.basicInfo.$refs.basicInfoForm;
 | 
			
		||||
      const genForm = this.$refs.genInfo.$refs.genInfoForm;
 | 
			
		||||
      Promise.all([basicForm, genForm].map(this.getFormPromise)).then(res => {
 | 
			
		||||
        const validateResult = res.every(item => !!item);
 | 
			
		||||
        if (validateResult) {
 | 
			
		||||
          const genTable = {};
 | 
			
		||||
          genTable.table = Object.assign({}, basicForm.model, genForm.model);
 | 
			
		||||
          genTable.columns = this.columns;
 | 
			
		||||
          genTable.params = {
 | 
			
		||||
            treeCode: genTable.treeCode,
 | 
			
		||||
            treeName: genTable.treeName,
 | 
			
		||||
            treeParentCode: genTable.treeParentCode,
 | 
			
		||||
            parentMenuId: genTable.parentMenuId
 | 
			
		||||
          };
 | 
			
		||||
          updateCodegen(genTable).then(res => {
 | 
			
		||||
            this.$modal.msgSuccess("修改成功!");
 | 
			
		||||
            this.close();
 | 
			
		||||
          });
 | 
			
		||||
        } else {
 | 
			
		||||
          this.$modal.msgError("表单校验未通过,请重新检查提交内容");
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    getFormPromise(form) {
 | 
			
		||||
      return new Promise(resolve => {
 | 
			
		||||
        form.validate(res => {
 | 
			
		||||
          resolve(res);
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 关闭按钮 */
 | 
			
		||||
    close() {
 | 
			
		||||
      this.$tab.closeOpenPage({
 | 
			
		||||
        path: "/infra/codegen",
 | 
			
		||||
        query: { t: Date.now(), pageNum: this.$route.query.pageNum } }
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  mounted() {
 | 
			
		||||
    const el = this.$refs.dragTable.$el.querySelectorAll(".el-table__body-wrapper > table > tbody")[0];
 | 
			
		||||
    const sortable = Sortable.create(el, {
 | 
			
		||||
      handle: ".allowDrag",
 | 
			
		||||
      onEnd: evt => {
 | 
			
		||||
        const targetRow = this.columns.splice(evt.oldIndex, 1)[0];
 | 
			
		||||
        this.columns.splice(evt.newIndex, 0, targetRow);
 | 
			
		||||
        for (let index in this.columns) {
 | 
			
		||||
          this.columns[index].sort = parseInt(index) + 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,339 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <el-form ref="genInfoForm" :model="info" :rules="rules" label-width="150px">
 | 
			
		||||
    <el-row>
 | 
			
		||||
      <el-col :span="12">
 | 
			
		||||
        <el-form-item prop="templateType">
 | 
			
		||||
          <span slot="label">生成模板</span>
 | 
			
		||||
          <el-select v-model="info.templateType" @change="tplSelectChange">
 | 
			
		||||
            <el-option v-for="dict in this.getDictDatas(DICT_TYPE.INFRA_CODEGEN_TEMPLATE_TYPE)"
 | 
			
		||||
                :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <el-col :span="12">
 | 
			
		||||
        <el-form-item prop="templateType">
 | 
			
		||||
          <span slot="label">前端类型</span>
 | 
			
		||||
          <el-select v-model="info.frontType">
 | 
			
		||||
            <el-option v-for="dict in this.getDictDatas(DICT_TYPE.INFRA_CODEGEN_FRONT_TYPE)"
 | 
			
		||||
                       :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
 | 
			
		||||
      <el-col :span="12">
 | 
			
		||||
        <el-form-item prop="scene">
 | 
			
		||||
          <span slot="label">生成场景</span>
 | 
			
		||||
          <el-select v-model="info.scene">
 | 
			
		||||
            <el-option v-for="dict in this.getDictDatas(DICT_TYPE.INFRA_CODEGEN_SCENE)"
 | 
			
		||||
                       :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <el-col :span="12">
 | 
			
		||||
        <el-form-item>
 | 
			
		||||
          <span slot="label">
 | 
			
		||||
            上级菜单
 | 
			
		||||
            <el-tooltip content="分配到指定菜单下,例如 系统管理" placement="top">
 | 
			
		||||
              <i class="el-icon-question"></i>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </span>
 | 
			
		||||
          <treeselect :append-to-body="true" v-model="info.parentMenuId" :options="menus"
 | 
			
		||||
                      :normalizer="normalizer" :show-count="true" placeholder="请选择系统菜单" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
 | 
			
		||||
<!--      <el-col :span="12">-->
 | 
			
		||||
<!--        <el-form-item prop="packageName">-->
 | 
			
		||||
<!--          <span slot="label">-->
 | 
			
		||||
<!--            生成包路径-->
 | 
			
		||||
<!--            <el-tooltip content="生成在哪个java包下,例如 com.ruoyi.system" placement="top">-->
 | 
			
		||||
<!--              <i class="el-icon-question"></i>-->
 | 
			
		||||
<!--            </el-tooltip>-->
 | 
			
		||||
<!--          </span>-->
 | 
			
		||||
<!--          <el-input v-model="info.packageName" />-->
 | 
			
		||||
<!--        </el-form-item>-->
 | 
			
		||||
<!--      </el-col>-->
 | 
			
		||||
 | 
			
		||||
      <el-col :span="12">
 | 
			
		||||
        <el-form-item prop="moduleName">
 | 
			
		||||
          <span slot="label">
 | 
			
		||||
            模块名
 | 
			
		||||
            <el-tooltip content="模块名,即一级目录,例如 system、infra、tool 等等" placement="top">
 | 
			
		||||
              <i class="el-icon-question"></i>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </span>
 | 
			
		||||
          <el-input v-model="info.moduleName" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
 | 
			
		||||
      <el-col :span="12">
 | 
			
		||||
        <el-form-item prop="businessName">
 | 
			
		||||
          <span slot="label">
 | 
			
		||||
            业务名
 | 
			
		||||
            <el-tooltip content="业务名,即二级目录,例如 user、permission、dict 等等" placement="top">
 | 
			
		||||
              <i class="el-icon-question"></i>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </span>
 | 
			
		||||
          <el-input v-model="info.businessName" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
 | 
			
		||||
<!--      <el-col :span="12">-->
 | 
			
		||||
<!--        <el-form-item prop="businessPackage">-->
 | 
			
		||||
<!--          <span slot="label">-->
 | 
			
		||||
<!--            业务包-->
 | 
			
		||||
<!--            <el-tooltip content="业务包,自定义二级目录。例如说,我们希望将 dictType 和 dictData 归类成 dict 业务" placement="top">-->
 | 
			
		||||
<!--              <i class="el-icon-question"></i>-->
 | 
			
		||||
<!--            </el-tooltip>-->
 | 
			
		||||
<!--          </span>-->
 | 
			
		||||
<!--          <el-input v-model="info.businessPackage" />-->
 | 
			
		||||
<!--        </el-form-item>-->
 | 
			
		||||
<!--      </el-col>-->
 | 
			
		||||
 | 
			
		||||
      <el-col :span="12">
 | 
			
		||||
        <el-form-item prop="className">
 | 
			
		||||
          <span slot="label">
 | 
			
		||||
            类名称
 | 
			
		||||
            <el-tooltip content="类名称(首字母大写),例如SysUser、SysMenu、SysDictData 等等" placement="top">
 | 
			
		||||
              <i class="el-icon-question"></i>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </span>
 | 
			
		||||
          <el-input v-model="info.className" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
 | 
			
		||||
      <el-col :span="12">
 | 
			
		||||
        <el-form-item prop="classComment">
 | 
			
		||||
          <span slot="label">
 | 
			
		||||
            类描述
 | 
			
		||||
            <el-tooltip content="用作类描述,例如 用户" placement="top">
 | 
			
		||||
              <i class="el-icon-question"></i>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </span>
 | 
			
		||||
          <el-input v-model="info.classComment" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
 | 
			
		||||
      <el-col :span="24" v-if="info.genType === '1'">
 | 
			
		||||
        <el-form-item prop="genPath">
 | 
			
		||||
          <span slot="label">
 | 
			
		||||
            自定义路径
 | 
			
		||||
            <el-tooltip content="填写磁盘绝对路径,若不填写,则生成到当前Web项目下" placement="top">
 | 
			
		||||
              <i class="el-icon-question"></i>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </span>
 | 
			
		||||
          <el-input v-model="info.genPath">
 | 
			
		||||
            <el-dropdown slot="append">
 | 
			
		||||
              <el-button type="primary">
 | 
			
		||||
                最近路径快速选择
 | 
			
		||||
                <i class="el-icon-arrow-down el-icon--right"></i>
 | 
			
		||||
              </el-button>
 | 
			
		||||
              <el-dropdown-menu slot="dropdown">
 | 
			
		||||
                <el-dropdown-item @click.native="info.genPath = '/'">恢复默认的生成基础路径</el-dropdown-item>
 | 
			
		||||
              </el-dropdown-menu>
 | 
			
		||||
            </el-dropdown>
 | 
			
		||||
          </el-input>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <el-row v-show="info.tplCategory === 'tree'">
 | 
			
		||||
      <h4 class="form-header">其他信息</h4>
 | 
			
		||||
      <el-col :span="12">
 | 
			
		||||
        <el-form-item>
 | 
			
		||||
          <span slot="label">
 | 
			
		||||
            树编码字段
 | 
			
		||||
            <el-tooltip content="树显示的编码字段名, 如:dept_id" placement="top">
 | 
			
		||||
              <i class="el-icon-question"></i>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </span>
 | 
			
		||||
          <el-select v-model="info.treeCode" placeholder="请选择">
 | 
			
		||||
            <el-option
 | 
			
		||||
              v-for="(column, index) in info.columns"
 | 
			
		||||
              :key="index"
 | 
			
		||||
              :label="column.columnName + ':' + column.columnComment"
 | 
			
		||||
              :value="column.columnName"
 | 
			
		||||
            ></el-option>
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <el-col :span="12">
 | 
			
		||||
        <el-form-item>
 | 
			
		||||
          <span slot="label">
 | 
			
		||||
            树父编码字段
 | 
			
		||||
            <el-tooltip content="树显示的父编码字段名, 如:parent_Id" placement="top">
 | 
			
		||||
              <i class="el-icon-question"></i>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </span>
 | 
			
		||||
          <el-select v-model="info.treeParentCode" placeholder="请选择">
 | 
			
		||||
            <el-option
 | 
			
		||||
              v-for="(column, index) in info.columns"
 | 
			
		||||
              :key="index"
 | 
			
		||||
              :label="column.columnName + ':' + column.columnComment"
 | 
			
		||||
              :value="column.columnName"
 | 
			
		||||
            ></el-option>
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <el-col :span="12">
 | 
			
		||||
        <el-form-item>
 | 
			
		||||
          <span slot="label">
 | 
			
		||||
            树名称字段
 | 
			
		||||
            <el-tooltip content="树节点的显示名称字段名, 如:dept_name" placement="top">
 | 
			
		||||
              <i class="el-icon-question"></i>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </span>
 | 
			
		||||
          <el-select v-model="info.treeName" placeholder="请选择">
 | 
			
		||||
            <el-option
 | 
			
		||||
              v-for="(column, index) in info.columns"
 | 
			
		||||
              :key="index"
 | 
			
		||||
              :label="column.columnName + ':' + column.columnComment"
 | 
			
		||||
              :value="column.columnName"
 | 
			
		||||
            ></el-option>
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
    </el-row>
 | 
			
		||||
    <el-row v-show="info.tplCategory === 'sub'">
 | 
			
		||||
      <h4 class="form-header">关联信息</h4>
 | 
			
		||||
      <el-col :span="12">
 | 
			
		||||
        <el-form-item>
 | 
			
		||||
          <span slot="label">
 | 
			
		||||
            关联子表的表名
 | 
			
		||||
            <el-tooltip content="关联子表的表名, 如:sys_user" placement="top">
 | 
			
		||||
              <i class="el-icon-question"></i>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </span>
 | 
			
		||||
          <el-select v-model="info.subTableName" placeholder="请选择" @change="subSelectChange">
 | 
			
		||||
            <el-option
 | 
			
		||||
              v-for="(table, index) in tables"
 | 
			
		||||
              :key="index"
 | 
			
		||||
              :label="table.tableName + ':' + table.tableComment"
 | 
			
		||||
              :value="table.tableName"
 | 
			
		||||
            ></el-option>
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <el-col :span="12">
 | 
			
		||||
        <el-form-item>
 | 
			
		||||
          <span slot="label">
 | 
			
		||||
            子表关联的外键名
 | 
			
		||||
            <el-tooltip content="子表关联的外键名, 如:user_id" placement="top">
 | 
			
		||||
              <i class="el-icon-question"></i>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </span>
 | 
			
		||||
          <el-select v-model="info.subTableFkName" placeholder="请选择">
 | 
			
		||||
            <el-option
 | 
			
		||||
              v-for="(column, index) in subColumns"
 | 
			
		||||
              :key="index"
 | 
			
		||||
              :label="column.columnName + ':' + column.columnComment"
 | 
			
		||||
              :value="column.columnName"
 | 
			
		||||
            ></el-option>
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-col>
 | 
			
		||||
    </el-row>
 | 
			
		||||
  </el-form>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
import Treeselect from "@riophae/vue-treeselect";
 | 
			
		||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "BasicInfoForm",
 | 
			
		||||
  components: { Treeselect },
 | 
			
		||||
  props: {
 | 
			
		||||
    info: {
 | 
			
		||||
      type: Object,
 | 
			
		||||
      default: null
 | 
			
		||||
    },
 | 
			
		||||
    tables: {
 | 
			
		||||
      type: Array,
 | 
			
		||||
      default: null
 | 
			
		||||
    },
 | 
			
		||||
    menus: {
 | 
			
		||||
      type: Array,
 | 
			
		||||
      default: []
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      subColumns: [],
 | 
			
		||||
      rules: {
 | 
			
		||||
        templateType: [
 | 
			
		||||
          { required: true, message: "请选择生成模板", trigger: "blur" }
 | 
			
		||||
        ],
 | 
			
		||||
        scene: [
 | 
			
		||||
          { required: true, message: "请选择生成场景", trigger: "blur" }
 | 
			
		||||
        ],
 | 
			
		||||
        frontType: [
 | 
			
		||||
          { required: true, message: "请选择前端类型", trigger: "blur" }
 | 
			
		||||
        ],
 | 
			
		||||
        // packageName: [
 | 
			
		||||
        //   { required: true, message: "请输入生成包路径", trigger: "blur" }
 | 
			
		||||
        // ],
 | 
			
		||||
        moduleName: [
 | 
			
		||||
          { required: true, message: "请输入生成模块名", trigger: "blur" }
 | 
			
		||||
        ],
 | 
			
		||||
        businessName: [
 | 
			
		||||
          { required: true, message: "请输入生成业务名", trigger: "blur" }
 | 
			
		||||
        ],
 | 
			
		||||
        businessPackage: [
 | 
			
		||||
          { required: true, message: "请输入生成业务包", trigger: "blur" }
 | 
			
		||||
        ],
 | 
			
		||||
        className: [
 | 
			
		||||
          { required: true, message: "请输入生成类名称", trigger: "blur" }
 | 
			
		||||
        ],
 | 
			
		||||
        classComment: [
 | 
			
		||||
          { required: true, message: "请输入生成类描述", trigger: "blur" }
 | 
			
		||||
        ],
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {},
 | 
			
		||||
  watch: {
 | 
			
		||||
    'info.subTableName': function(val) {
 | 
			
		||||
      this.setSubTableColumns(val);
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 转换菜单数据结构 */
 | 
			
		||||
    normalizer(node) {
 | 
			
		||||
      if (node.children && !node.children.length) {
 | 
			
		||||
        delete node.children;
 | 
			
		||||
      }
 | 
			
		||||
      return {
 | 
			
		||||
        id: node.id,
 | 
			
		||||
        label: node.name,
 | 
			
		||||
        children: node.children
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
    /** 选择子表名触发 */
 | 
			
		||||
    subSelectChange(value) {
 | 
			
		||||
      this.info.subTableFkName = '';
 | 
			
		||||
    },
 | 
			
		||||
    /** 选择生成模板触发 */
 | 
			
		||||
    tplSelectChange(value) {
 | 
			
		||||
      if (value !== 1) {
 | 
			
		||||
        // TODO 芋艿:暂时不考虑支持树形结构
 | 
			
		||||
        this.$modal.msgError('暂时不考虑支持【树形】和【主子表】的代码生成。原因是:导致 vm 模板过于复杂,不利于胖友二次开发');
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
      if(value !== 'sub') {
 | 
			
		||||
        this.info.subTableName = '';
 | 
			
		||||
        this.info.subTableFkName = '';
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    /** 设置关联外键 */
 | 
			
		||||
    setSubTableColumns(value) {
 | 
			
		||||
      for (let item in this.tables) {
 | 
			
		||||
        const name = this.tables[item].tableName;
 | 
			
		||||
        if (value === name) {
 | 
			
		||||
          this.subColumns = this.tables[item].columns;
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,114 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <!-- 导入表 -->
 | 
			
		||||
  <el-dialog title="导入表" :visible.sync="visible" width="800px" top="5vh" append-to-body>
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
 | 
			
		||||
      <el-form-item label="数据源" prop="dataSourceConfigId">
 | 
			
		||||
        <el-select v-model="queryParams.dataSourceConfigId" placeholder="请选择数据源" clearable>
 | 
			
		||||
          <el-option v-for="config in dataSourceConfigs"
 | 
			
		||||
                     :key="config.id" :label="config.name" :value="config.id"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="表名称" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入表名称" clearable  @keyup.enter.native="handleQuery" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="表描述" prop="comment">
 | 
			
		||||
        <el-input v-model="queryParams.comment" placeholder="请输入表描述" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
    <el-row>
 | 
			
		||||
      <el-table v-loading="loading" @row-click="clickRow" ref="table" :data="dbTableList"
 | 
			
		||||
                @selection-change="handleSelectionChange" height="260px">
 | 
			
		||||
        <el-table-column type="selection" width="55" />
 | 
			
		||||
        <el-table-column prop="name" label="表名称" :show-overflow-tooltip="true" />
 | 
			
		||||
        <el-table-column prop="comment" label="表描述" :show-overflow-tooltip="true" />
 | 
			
		||||
      </el-table>
 | 
			
		||||
    </el-row>
 | 
			
		||||
    <div slot="footer" class="dialog-footer">
 | 
			
		||||
      <el-button type="primary" @click="handleImportTable">确 定</el-button>
 | 
			
		||||
      <el-button @click="visible = false">取 消</el-button>
 | 
			
		||||
    </div>
 | 
			
		||||
  </el-dialog>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { getSchemaTableList, createCodegenList } from "@/api/infra/codegen";
 | 
			
		||||
import {getDataSourceConfigList} from "@/api/infra/dataSourceConfig";
 | 
			
		||||
export default {
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: false,
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      visible: false,
 | 
			
		||||
      // 选中数组值
 | 
			
		||||
      tables: [],
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 表数据
 | 
			
		||||
      dbTableList: [],
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        dataSourceConfigId: undefined,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        comment: undefined,
 | 
			
		||||
      },
 | 
			
		||||
      // 数据源列表
 | 
			
		||||
      dataSourceConfigs: [],
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    // 显示弹框
 | 
			
		||||
    show() {
 | 
			
		||||
      this.visible = true;
 | 
			
		||||
      // 加载数据源
 | 
			
		||||
      getDataSourceConfigList().then(response => {
 | 
			
		||||
        this.dataSourceConfigs = response.data;
 | 
			
		||||
        this.queryParams.dataSourceConfigId = this.dataSourceConfigs[0].id;
 | 
			
		||||
        // 加载表列表
 | 
			
		||||
        this.getList();
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    clickRow(row) {
 | 
			
		||||
      this.$refs.table.toggleRowSelection(row);
 | 
			
		||||
    },
 | 
			
		||||
    // 多选框选中数据
 | 
			
		||||
    handleSelectionChange(selection) {
 | 
			
		||||
      this.tables = selection.map(item => item.name);
 | 
			
		||||
    },
 | 
			
		||||
    // 查询表数据
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      getSchemaTableList(this.queryParams).then(res => {
 | 
			
		||||
        this.dbTableList = res.data;
 | 
			
		||||
      }).finally(() => {
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.queryParams.dataSourceConfigId = this.dataSourceConfigs[0].id;
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 导入按钮操作 */
 | 
			
		||||
    handleImportTable() {
 | 
			
		||||
      createCodegenList({
 | 
			
		||||
        dataSourceConfigId: this.queryParams.dataSourceConfigId,
 | 
			
		||||
        tableNames: this.tables
 | 
			
		||||
      }).then(res => {
 | 
			
		||||
        this.$modal.msgSuccess("导入成功");
 | 
			
		||||
        this.visible = false;
 | 
			
		||||
        this.$emit("ok");
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,317 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="代码生成" url="https://doc.iocoder.cn/new-feature/" />
 | 
			
		||||
    <doc-alert title="单元测试" url="https://doc.iocoder.cn/unit-test/" />
 | 
			
		||||
    <!-- 操作工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="表名称" prop="tableName">
 | 
			
		||||
        <el-input v-model="queryParams.tableName" placeholder="请输入表名称" clearable
 | 
			
		||||
                  @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="表描述" prop="tableComment">
 | 
			
		||||
        <el-input v-model="queryParams.tableComment" placeholder="请输入表描述" clearable
 | 
			
		||||
                  @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工作栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="info" plain icon="el-icon-upload" size="mini" @click="openImportTable"
 | 
			
		||||
                   v-hasPermi="['infra:codegen:create']">导入</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="tableList">
 | 
			
		||||
      <el-table-column label="数据源" align="center" :formatter="dataSourceConfigNameFormat"/>
 | 
			
		||||
      <el-table-column label="表名称" align="center" prop="tableName" width="200"/>
 | 
			
		||||
      <el-table-column label="表描述" align="center" prop="tableComment" :show-overflow-tooltip="true" width="120"/>
 | 
			
		||||
      <el-table-column label="实体" align="center" prop="className" width="200"/>
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="更新时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.updateTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" width="300px" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button type="text" size="small" icon="el-icon-view" @click="handlePreview(scope.row)" v-hasPermi="['infra:codegen:preview']">预览</el-button>
 | 
			
		||||
          <el-button type="text" size="small" icon="el-icon-edit" @click="handleEditTable(scope.row)" v-hasPermi="['infra:codegen:update']">编辑</el-button>
 | 
			
		||||
          <el-button type="text" size="small" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['infra:codegen:delete']">删除</el-button>
 | 
			
		||||
          <el-button type="text" size="small" icon="el-icon-refresh" @click="handleSynchDb(scope.row)" v-hasPermi="['infra:codegen:update']">同步</el-button>
 | 
			
		||||
          <el-button type="text" size="small" icon="el-icon-download" @click="handleGenTable(scope.row)" v-hasPermi="['infra:codegen:download']">生成代码</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 预览界面 -->
 | 
			
		||||
    <el-dialog :title="preview.title" :visible.sync="preview.open" width="90%" top="5vh" append-to-body class="scrollbar">
 | 
			
		||||
      <el-row>
 | 
			
		||||
        <el-col :span="7">
 | 
			
		||||
          <el-tree :data="preview.fileTree" :expand-on-click-node="false" default-expand-all highlight-current
 | 
			
		||||
                   @node-click="handleNodeClick"/>
 | 
			
		||||
        </el-col>
 | 
			
		||||
        <el-col :span="17">
 | 
			
		||||
          <el-tabs v-model="preview.activeName">
 | 
			
		||||
            <el-tab-pane v-for="item in preview.data" :label="item.filePath.substring(item.filePath.lastIndexOf('/') + 1)"
 | 
			
		||||
                         :name="item.filePath" :key="item.filePath">
 | 
			
		||||
              <el-link :underline="false" icon="el-icon-document-copy" v-clipboard:copy="item.code" v-clipboard:success="clipboardSuccess" style="float:right">复制</el-link>
 | 
			
		||||
              <pre><code class="hljs" v-html="highlightedCode(item)"></code></pre>
 | 
			
		||||
            </el-tab-pane>
 | 
			
		||||
          </el-tabs>
 | 
			
		||||
        </el-col>
 | 
			
		||||
      </el-row>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
 | 
			
		||||
    <!-- 基于 DB 导入 -->
 | 
			
		||||
    <import-table ref="import" @ok="handleQuery" />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { getCodegenTablePage, previewCodegen, downloadCodegen, deleteCodegen,
 | 
			
		||||
  syncCodegenFromDB } from "@/api/infra/codegen";
 | 
			
		||||
 | 
			
		||||
import importTable from "./importTable";
 | 
			
		||||
// 代码高亮插件
 | 
			
		||||
import hljs from "highlight.js/lib/highlight";
 | 
			
		||||
import "highlight.js/styles/github-gist.css";
 | 
			
		||||
import {getDataSourceConfigList} from "@/api/infra/dataSourceConfig";
 | 
			
		||||
hljs.registerLanguage("java", require("highlight.js/lib/languages/java"));
 | 
			
		||||
hljs.registerLanguage("xml", require("highlight.js/lib/languages/xml"));
 | 
			
		||||
hljs.registerLanguage("html", require("highlight.js/lib/languages/xml"));
 | 
			
		||||
hljs.registerLanguage("vue", require("highlight.js/lib/languages/xml"));
 | 
			
		||||
hljs.registerLanguage("javascript", require("highlight.js/lib/languages/javascript"));
 | 
			
		||||
hljs.registerLanguage("sql", require("highlight.js/lib/languages/sql"));
 | 
			
		||||
hljs.registerLanguage("typescript", require("highlight.js/lib/languages/typescript"));
 | 
			
		||||
export default {
 | 
			
		||||
  name: "InfraCodegen",
 | 
			
		||||
  components: { importTable },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 唯一标识符
 | 
			
		||||
      uniqueId: "",
 | 
			
		||||
      // 选中表数组
 | 
			
		||||
      tableNames: [],
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 表数据
 | 
			
		||||
      tableList: [],
 | 
			
		||||
      // 日期范围
 | 
			
		||||
      dateRange: "",
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        tableName: undefined,
 | 
			
		||||
        tableComment: undefined,
 | 
			
		||||
        createTime: []
 | 
			
		||||
      },
 | 
			
		||||
      // 预览参数
 | 
			
		||||
      preview: {
 | 
			
		||||
        open: false,
 | 
			
		||||
        title: "代码预览",
 | 
			
		||||
        fileTree: [],
 | 
			
		||||
        data: {},
 | 
			
		||||
        activeName: "",
 | 
			
		||||
      },
 | 
			
		||||
      // 数据源列表
 | 
			
		||||
      dataSourceConfigs: [],
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
    // 加载数据源
 | 
			
		||||
    getDataSourceConfigList().then(response => {
 | 
			
		||||
      this.dataSourceConfigs = response.data;
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
  activated() {
 | 
			
		||||
    const time = this.$route.query.t;
 | 
			
		||||
    if (time != null && time !== this.uniqueId) {
 | 
			
		||||
      this.uniqueId = time;
 | 
			
		||||
      this.resetQuery();
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询表集合 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      getCodegenTablePage(this.queryParams).then(response => {
 | 
			
		||||
            this.tableList = response.data.list;
 | 
			
		||||
            this.total = response.data.total;
 | 
			
		||||
            this.loading = false;
 | 
			
		||||
          }
 | 
			
		||||
      );
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 生成代码操作 */
 | 
			
		||||
    handleGenTable(row) {
 | 
			
		||||
      downloadCodegen(row.id).then(response => {
 | 
			
		||||
        this.$download.zip(response, 'codegen-' + row.tableName + '.zip');
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    /** 同步数据库操作 */
 | 
			
		||||
    handleSynchDb(row) {
 | 
			
		||||
      // 基于 DB 同步
 | 
			
		||||
      const tableName = row.tableName;
 | 
			
		||||
      this.$modal.confirm('确认要强制同步"' + tableName + '"表结构吗?').then(function() {
 | 
			
		||||
          return syncCodegenFromDB(row.id);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
          this.$modal.msgSuccess("同步成功");
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    /** 打开导入表弹窗 */
 | 
			
		||||
    openImportTable() {
 | 
			
		||||
      this.$refs.import.show();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 预览按钮 */
 | 
			
		||||
    handlePreview(row) {
 | 
			
		||||
      previewCodegen(row.id).then(response => {
 | 
			
		||||
        this.preview.data = response.data;
 | 
			
		||||
        let files = this.handleFiles(response.data);
 | 
			
		||||
        this.preview.fileTree = this.handleTree(files, "id", "parentId", "children",
 | 
			
		||||
            "/"); // "/" 为根节点
 | 
			
		||||
        // console.log(this.preview.fileTree)
 | 
			
		||||
        this.preview.activeName = response.data[0].filePath;
 | 
			
		||||
        this.preview.open = true;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 高亮显示 */
 | 
			
		||||
    highlightedCode(item) {
 | 
			
		||||
      // const vmName = key.substring(key.lastIndexOf("/") + 1, key.indexOf(".vm"));
 | 
			
		||||
      // var language = vmName.substring(vmName.indexOf(".") + 1, vmName.length);
 | 
			
		||||
      const language = item.filePath.substring(item.filePath.lastIndexOf('.') + 1)
 | 
			
		||||
      const result = hljs.highlight(language, item.code || "", true);
 | 
			
		||||
      return result.value || ' ';
 | 
			
		||||
    },
 | 
			
		||||
    /** 复制代码成功 */
 | 
			
		||||
    clipboardSuccess() {
 | 
			
		||||
      this.$modal.msgSuccess("复制成功");
 | 
			
		||||
    },
 | 
			
		||||
    /** 生成 files 目录 **/
 | 
			
		||||
    handleFiles(datas) {
 | 
			
		||||
      let exists = {}; // key:file 的 id;value:true
 | 
			
		||||
      let files = [];
 | 
			
		||||
      // 遍历每个元素
 | 
			
		||||
      for (const data of datas) {
 | 
			
		||||
        let paths = data.filePath.split('/');
 | 
			
		||||
        let fullPath = ''; // 从头开始的路径,用于生成 id
 | 
			
		||||
        // 特殊处理 java 文件
 | 
			
		||||
        if (paths[paths.length - 1].indexOf('.java') >= 0) {
 | 
			
		||||
          let newPaths = [];
 | 
			
		||||
          for (let i = 0; i < paths.length; i++) {
 | 
			
		||||
            let path = paths[i];
 | 
			
		||||
            if (path !== 'java') {
 | 
			
		||||
              newPaths.push(path);
 | 
			
		||||
              continue;
 | 
			
		||||
            }
 | 
			
		||||
            newPaths.push(path);
 | 
			
		||||
            // 特殊处理中间的 package,进行合并
 | 
			
		||||
            let tmp = undefined;
 | 
			
		||||
            while (i < paths.length) {
 | 
			
		||||
              path = paths[i + 1];
 | 
			
		||||
              if (path === 'controller'
 | 
			
		||||
                || path === 'convert'
 | 
			
		||||
                || path === 'dal'
 | 
			
		||||
                || path === 'enums'
 | 
			
		||||
                || path === 'service'
 | 
			
		||||
                || path === 'vo' // 下面三个,主要是兜底。可能考虑到有人改了包结构
 | 
			
		||||
                || path === 'mysql'
 | 
			
		||||
                || path === 'dataobject') {
 | 
			
		||||
                break;
 | 
			
		||||
              }
 | 
			
		||||
              tmp = tmp ? tmp + '.' + path : path;
 | 
			
		||||
              i++;
 | 
			
		||||
            }
 | 
			
		||||
            if (tmp) {
 | 
			
		||||
              newPaths.push(tmp);
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          paths = newPaths;
 | 
			
		||||
        }
 | 
			
		||||
        // 遍历每个 path, 拼接成树
 | 
			
		||||
        for (let i = 0; i < paths.length; i++) {
 | 
			
		||||
          // 已经添加到 files 中,则跳过
 | 
			
		||||
          let oldFullPath = fullPath;
 | 
			
		||||
          // 下面的 replaceAll 的原因,是因为上面包处理了,导致和 tabs 不匹配,所以 replaceAll 下
 | 
			
		||||
          fullPath = fullPath.length === 0 ? paths[i] : fullPath.replaceAll('.', '/') + '/' + paths[i];
 | 
			
		||||
          if (exists[fullPath]) {
 | 
			
		||||
            continue;
 | 
			
		||||
          }
 | 
			
		||||
          // 添加到 files 中
 | 
			
		||||
          exists[fullPath] = true;
 | 
			
		||||
          files.push({
 | 
			
		||||
            id: fullPath,
 | 
			
		||||
            label: paths[i],
 | 
			
		||||
            parentId: oldFullPath || '/'  // "/" 为根节点
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      return files;
 | 
			
		||||
    },
 | 
			
		||||
    /** 节点单击事件 **/
 | 
			
		||||
    handleNodeClick(data, node) {
 | 
			
		||||
      if (node && !node.isLeaf) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
      // 判断,如果非子节点,不允许选中
 | 
			
		||||
      this.preview.activeName = data.id;
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleEditTable(row) {
 | 
			
		||||
      const tableId = row.id;
 | 
			
		||||
      const tableName = row.tableName || this.tableNames[0];
 | 
			
		||||
      const params = { pageNum: this.queryParams.pageNum };
 | 
			
		||||
      this.$tab.openPage("修改[" + tableName + "]生成配置", '/codegen/edit/' + tableId, params);
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const tableIds = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认删除表名称为"' + row.tableName + '"的数据项?').then(function() {
 | 
			
		||||
          return deleteCodegen(tableIds);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
          this.getList();
 | 
			
		||||
          this.$modal.msgSuccess("删除成功");
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    // 数据源配置的名字
 | 
			
		||||
    dataSourceConfigNameFormat(row, column) {
 | 
			
		||||
      for (const config of this.dataSourceConfigs) {
 | 
			
		||||
        if (row.dataSourceConfigId === config.id) {
 | 
			
		||||
          return config.name;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      return '未知【' + row.leaderUserId + '】';
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,262 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="配置中心" url="https://doc.iocoder.cn/config-center/" />
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="参数名称" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入参数名称" clearable style="width: 240px"
 | 
			
		||||
                  @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="参数键名" prop="key">
 | 
			
		||||
        <el-input v-model="queryParams.key" placeholder="请输入参数键名" clearable style="width: 240px"
 | 
			
		||||
                  @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="系统内置" prop="type">
 | 
			
		||||
        <el-select v-model="queryParams.type" placeholder="系统内置" clearable>
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.INFRA_CONFIG_TYPE)" :key="parseInt(dict.value)"
 | 
			
		||||
                     :label="dict.label" :value="parseInt(dict.value)"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['infra:config:create']">新增</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport" :loading="exportLoading"
 | 
			
		||||
                   v-hasPermi="['infra:config:export']">导出</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <el-table v-loading="loading" :data="configList">
 | 
			
		||||
      <el-table-column label="参数主键" align="center" prop="id" />
 | 
			
		||||
      <el-table-column label="参数分类" align="center" prop="category" />
 | 
			
		||||
      <el-table-column label="参数名称" align="center" prop="name" :show-overflow-tooltip="true" />
 | 
			
		||||
      <el-table-column label="参数键名" align="center" prop="key" :show-overflow-tooltip="true" />
 | 
			
		||||
      <el-table-column label="参数键值" align="center" prop="value" />
 | 
			
		||||
      <el-table-column label="系统内置" align="center" prop="type">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.INFRA_CONFIG_TYPE" :value="scope.row.type" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="是否可见" align="center" prop="visible">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ scope.row.visible ? '是' : '否' }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                     v-hasPermi="['infra:config:update']">修改</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-hasPermi="['infra:config:delete']">删除</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
 | 
			
		||||
    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 添加或修改参数配置对话框 -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
 | 
			
		||||
        <el-form-item label="参数分类" prop="category">
 | 
			
		||||
          <el-input v-model="form.category" placeholder="请输入参数分类" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="参数名称" prop="name">
 | 
			
		||||
          <el-input v-model="form.name" placeholder="请输入参数名称" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="参数键名" prop="key">
 | 
			
		||||
          <el-input v-model="form.key" placeholder="请输入参数键名" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="参数键值" prop="value">
 | 
			
		||||
          <el-input v-model="form.value" placeholder="请输入参数键值" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="是否可见" prop="type">
 | 
			
		||||
          <el-radio-group v-model="form.visible">
 | 
			
		||||
            <el-radio :key="true" :label="true">是</el-radio>
 | 
			
		||||
            <el-radio :key="false" :label="false">否</el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="备注" prop="remark">
 | 
			
		||||
          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { listConfig, getConfig, delConfig, addConfig, updateConfig, exportConfig } from "@/api/infra/config";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "InfraConfig",
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 导出遮罩层
 | 
			
		||||
      exportLoading: false,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 参数表格数据
 | 
			
		||||
      configList: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 类型数据字典
 | 
			
		||||
      typeOptions: [],
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        key: undefined,
 | 
			
		||||
        type: undefined,
 | 
			
		||||
        createTime: []
 | 
			
		||||
      },
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {},
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        category: [
 | 
			
		||||
          { required: true, message: "参数分类不能为空", trigger: "blur" }
 | 
			
		||||
        ],
 | 
			
		||||
        name: [
 | 
			
		||||
          { required: true, message: "参数名称不能为空", trigger: "blur" }
 | 
			
		||||
        ],
 | 
			
		||||
        key: [
 | 
			
		||||
          { required: true, message: "参数键名不能为空", trigger: "blur" }
 | 
			
		||||
        ],
 | 
			
		||||
        value: [
 | 
			
		||||
          { required: true, message: "参数键值不能为空", trigger: "blur" }
 | 
			
		||||
        ]
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询参数列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      listConfig(this.queryParams).then(response => {
 | 
			
		||||
          this.configList = response.data.list;
 | 
			
		||||
          this.total = response.data.total;
 | 
			
		||||
          this.loading = false;
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
    },
 | 
			
		||||
    // 取消按钮
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    // 表单重置
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        key: undefined,
 | 
			
		||||
        value: undefined,
 | 
			
		||||
        remark: undefined
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.title = "添加参数";
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      const id = row.id || this.ids
 | 
			
		||||
      getConfig(id).then(response => {
 | 
			
		||||
        this.form = response.data;
 | 
			
		||||
        this.open = true;
 | 
			
		||||
        this.title = "修改参数";
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm: function() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (valid) {
 | 
			
		||||
          if (this.form.id !== undefined) {
 | 
			
		||||
            updateConfig(this.form).then(response => {
 | 
			
		||||
              this.$modal.msgSuccess("修改成功");
 | 
			
		||||
              this.open = false;
 | 
			
		||||
              this.getList();
 | 
			
		||||
            });
 | 
			
		||||
          } else {
 | 
			
		||||
            addConfig(this.form).then(response => {
 | 
			
		||||
              this.$modal.msgSuccess("新增成功");
 | 
			
		||||
              this.open = false;
 | 
			
		||||
              this.getList();
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const ids = row.id || this.ids;
 | 
			
		||||
      this.$modal.confirm('是否确认删除参数编号为"' + ids + '"的数据项?').then(function() {
 | 
			
		||||
          return delConfig(ids);
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          this.getList();
 | 
			
		||||
          this.$modal.msgSuccess("删除成功");
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    /** 导出按钮操作 */
 | 
			
		||||
    handleExport() {
 | 
			
		||||
      this.$modal.confirm('是否确认导出所有参数数据项?').then(() => {
 | 
			
		||||
          // 处理查询参数
 | 
			
		||||
          let params = {...this.queryParams};
 | 
			
		||||
          params.pageNo = undefined;
 | 
			
		||||
          params.pageSize = undefined;
 | 
			
		||||
          this.exportLoading = true;
 | 
			
		||||
          return exportConfig(params);
 | 
			
		||||
        }).then(response => {
 | 
			
		||||
          this.$download.excel(response, '参数配置.xls');
 | 
			
		||||
          this.exportLoading = false;
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,166 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['infra:data-source-config:create']">新增</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="主键编号" align="center" prop="id" />
 | 
			
		||||
      <el-table-column label="数据源名称" align="center" prop="name" />
 | 
			
		||||
      <el-table-column label="数据源连接" align="center" prop="url" />
 | 
			
		||||
      <el-table-column label="用户名" align="center" prop="username" />
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                     v-hasPermi="['infra:data-source-config:update']">修改</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-hasPermi="['infra:data-source-config:delete']">删除</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
 | 
			
		||||
        <el-form-item label="数据源名称" prop="name">
 | 
			
		||||
          <el-input v-model="form.name" placeholder="请输入参数名称" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="数据源连接" prop="url">
 | 
			
		||||
          <el-input v-model="form.url" placeholder="请输入数据源连接" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="用户名" prop="username">
 | 
			
		||||
          <el-input v-model="form.username" placeholder="请输入用户名" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="密码" prop="password">
 | 
			
		||||
          <el-input v-model="form.password" placeholder="请输入密码" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { createDataSourceConfig, updateDataSourceConfig, deleteDataSourceConfig, getDataSourceConfig, getDataSourceConfigList } from "@/api/infra/dataSourceConfig";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "InfraDataSourceConfig",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 数据源配置列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {},
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        name: [{ required: true, message: "数据源名称不能为空", trigger: "blur" }],
 | 
			
		||||
        url: [{ required: true, message: "数据源连接不能为空", trigger: "blur" }],
 | 
			
		||||
        username: [{ required: true, message: "用户名不能为空", trigger: "blur" }],
 | 
			
		||||
        password: [{ required: true, message: "密码不能为空", trigger: "blur" }],
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getDataSourceConfigList().then(response => {
 | 
			
		||||
        this.list = response.data;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        url: undefined,
 | 
			
		||||
        username: undefined,
 | 
			
		||||
        password: undefined,
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.title = "添加数据源配置";
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      getDataSourceConfig(id).then(response => {
 | 
			
		||||
        this.form = response.data;
 | 
			
		||||
        this.open = true;
 | 
			
		||||
        this.title = "修改数据源配置";
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 修改的提交
 | 
			
		||||
        if (this.form.id != null) {
 | 
			
		||||
          updateDataSourceConfig(this.form).then(response => {
 | 
			
		||||
            this.$modal.msgSuccess("修改成功");
 | 
			
		||||
            this.open = false;
 | 
			
		||||
            this.getList();
 | 
			
		||||
          });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 添加的提交
 | 
			
		||||
        createDataSourceConfig(this.form).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("新增成功");
 | 
			
		||||
          this.open = false;
 | 
			
		||||
          this.getList();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认删除数据源配置编号为"' + id + '"的数据项?').then(function() {
 | 
			
		||||
          return deleteDataSourceConfig(id);
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          this.getList();
 | 
			
		||||
          this.$modal.msgSuccess("删除成功");
 | 
			
		||||
        }).catch(() => {});
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,70 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="数据库文档" url="https://doc.iocoder.cn/db-doc/" />
 | 
			
		||||
    <!-- 操作工作栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleExportHtml">导出 HTML</el-button>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleExportWord">导出 Word</el-button>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleExportMarkdown">导出 Markdown</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 展示文档 -->
 | 
			
		||||
    <div v-loading="loading" :style="'height:'+ height">
 | 
			
		||||
      <i-frame :src="src" />
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
import { exportHtml, exportWord, exportMarkdown} from "@/api/infra/dbDoc";
 | 
			
		||||
import iFrame from "@/components/iFrame/index";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "InfraDBDoc",
 | 
			
		||||
  components: { iFrame },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      height: document.documentElement.clientHeight - 94.5 + "px;",
 | 
			
		||||
      loading: true,
 | 
			
		||||
      src: "undefined",
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  mounted: function() {
 | 
			
		||||
    setTimeout(() => {
 | 
			
		||||
      this.loading = false;
 | 
			
		||||
    }, 230);
 | 
			
		||||
    const that = this;
 | 
			
		||||
    window.onresize = function temp() {
 | 
			
		||||
      that.height = document.documentElement.clientHeight - 94.5 + "px;";
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    // 加载 Html,进行预览
 | 
			
		||||
    exportHtml().then(response => {
 | 
			
		||||
      let blob = new Blob([response], {type : 'text/html'});
 | 
			
		||||
      this.src = window.URL.createObjectURL(blob);
 | 
			
		||||
    })
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 处理导出 HTML */
 | 
			
		||||
    handleExportHtml() {
 | 
			
		||||
      exportHtml().then(response => {
 | 
			
		||||
        this.$download.html(response, '数据库文档.html');
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    /** 处理导出 Word */
 | 
			
		||||
    handleExportWord() {
 | 
			
		||||
      exportWord().then(response => {
 | 
			
		||||
        this.$download.word(response, '数据库文档.doc');
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    /** 处理导出 Markdown */
 | 
			
		||||
    handleExportMarkdown() {
 | 
			
		||||
      exportMarkdown().then(response => {
 | 
			
		||||
        this.$download.markdown(response, '数据库文档.md');
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,32 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <doc-alert title="数据库 MyBatis" url="https://doc.iocoder.cn/mybatis/" />
 | 
			
		||||
    <doc-alert title="多数据源(读写分离)" url="https://doc.iocoder.cn/dynamic-datasource/" />
 | 
			
		||||
 | 
			
		||||
    <i-frame v-if="!loading" :src="url" />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
import iFrame from "@/components/iFrame/index";
 | 
			
		||||
import { getConfigKey } from "@/api/infra/config";
 | 
			
		||||
export default {
 | 
			
		||||
  name: "Druid",
 | 
			
		||||
  components: { iFrame },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      url: process.env.VUE_APP_BASE_API + "/druid/index.html",
 | 
			
		||||
      loading: true
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    getConfigKey("url.druid").then(response => {
 | 
			
		||||
      if (!response.data || response.data.length === 0) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
      this.url = response.data;
 | 
			
		||||
    }).finally(() => {
 | 
			
		||||
      this.loading = false;
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,216 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="上传下载" url="https://doc.iocoder.cn/file/"/>
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="文件路径" prop="path">
 | 
			
		||||
        <el-input v-model="queryParams.path" placeholder="请输入文件路径" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss"
 | 
			
		||||
                        type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
 | 
			
		||||
                        :default-time="['00:00:00', '23:59:59']"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">上传文件</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="文件名" :show-overflow-tooltip="true" align="center" min-width="200px" prop="name"/>
 | 
			
		||||
      <el-table-column label="文件路径" :show-overflow-tooltip="true" align="center" min-width="250px" prop="path"/>
 | 
			
		||||
      <el-table-column label="文件 URL" :show-overflow-tooltip="true" align="center" min-width="300px" prop="url"/>
 | 
			
		||||
      <el-table-column label="文件大小" align="center" prop="size" min-width="120px" :formatter="sizeFormat"/>
 | 
			
		||||
      <el-table-column label="文件类型" :show-overflow-tooltip="true" align="center" prop="type" width="180px"/>
 | 
			
		||||
      <el-table-column label="文件内容" align="center" prop="content" min-width="150px">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <image-preview v-if="scope.row.type&&scope.row.type.indexOf('image/') === 0" :src="scope.row.url"
 | 
			
		||||
                         :width="'100px'"></image-preview>
 | 
			
		||||
          <video v-else-if="scope.row.type&&scope.row.type.indexOf('video/') === 0" :width="'100px'">
 | 
			
		||||
            <source :src="scope.row.url"/>
 | 
			
		||||
          </video>
 | 
			
		||||
          <i v-else>无法预览,点击
 | 
			
		||||
            <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" target="_blank"
 | 
			
		||||
                     :href="getFileUrl + scope.row.configId + '/get/' + scope.row.path">下载
 | 
			
		||||
            </el-link>
 | 
			
		||||
          </i>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="上传时间" align="center" prop="createTime" min-width="170px">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" min-width="100px">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-hasPermi="['infra:file:delete']">删除
 | 
			
		||||
          </el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
 | 
			
		||||
      <el-upload ref="upload" :limit="1" accept=".jpg, .png, .gif" :auto-upload="false" drag
 | 
			
		||||
                 :headers="upload.headers" :action="upload.url" :data="upload.data" :disabled="upload.isUploading"
 | 
			
		||||
                 :on-change="handleFileChange"
 | 
			
		||||
                 :on-progress="handleFileUploadProgress"
 | 
			
		||||
                 :on-success="handleFileSuccess">
 | 
			
		||||
        <i class="el-icon-upload"></i>
 | 
			
		||||
        <div class="el-upload__text">
 | 
			
		||||
          将文件拖到此处,或 <em>点击上传</em>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入 jpg、png、gif 格式文件!</div>
 | 
			
		||||
      </el-upload>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitFileForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="upload.open = false">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {deleteFile, getFilePage} from "@/api/infra/file";
 | 
			
		||||
import {getAccessToken} from "@/utils/auth";
 | 
			
		||||
import ImagePreview from "@/components/ImagePreview";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "InfraFile",
 | 
			
		||||
  components: {
 | 
			
		||||
    ImagePreview
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      getFileUrl: process.env.VUE_APP_BASE_API + '/admin-api/infra/file/',
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 文件列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        path: null,
 | 
			
		||||
        type: null,
 | 
			
		||||
        createTime: []
 | 
			
		||||
      },
 | 
			
		||||
      // 用户导入参数
 | 
			
		||||
      upload: {
 | 
			
		||||
        open: false, // 是否显示弹出层
 | 
			
		||||
        title: "", // 弹出层标题
 | 
			
		||||
        isUploading: false, // 是否禁用上传
 | 
			
		||||
        url: process.env.VUE_APP_BASE_API + "/admin-api/infra/file/upload", // 请求地址
 | 
			
		||||
        headers: {Authorization: "Bearer " + getAccessToken()}, // 设置上传的请求头部
 | 
			
		||||
        data: {} // 上传的额外数据,用于文件名
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getFilePage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        content: undefined,
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.upload.open = true;
 | 
			
		||||
      this.upload.title = "上传文件";
 | 
			
		||||
    },
 | 
			
		||||
    /** 处理上传的文件发生变化 */
 | 
			
		||||
    handleFileChange(file, fileList) {
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
    /** 处理文件上传中 */
 | 
			
		||||
    handleFileUploadProgress(event, file, fileList) {
 | 
			
		||||
      this.upload.isUploading = true; // 禁止修改
 | 
			
		||||
    },
 | 
			
		||||
    /** 发起文件上传 */
 | 
			
		||||
    submitFileForm() {
 | 
			
		||||
      this.$refs.upload.submit();
 | 
			
		||||
    },
 | 
			
		||||
    /** 文件上传成功处理 */
 | 
			
		||||
    handleFileSuccess(response, file, fileList) {
 | 
			
		||||
      // 清理
 | 
			
		||||
      this.upload.open = false;
 | 
			
		||||
      this.upload.isUploading = false;
 | 
			
		||||
      this.$refs.upload.clearFiles();
 | 
			
		||||
      // 提示成功,并刷新
 | 
			
		||||
      this.$modal.msgSuccess("上传成功");
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认删除文件编号为"' + id + '"的数据项?').then(function () {
 | 
			
		||||
        return deleteFile(id);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("删除成功");
 | 
			
		||||
      }).catch(() => {
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    // 用户昵称展示
 | 
			
		||||
    sizeFormat(row, column) {
 | 
			
		||||
      const unitArr = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
 | 
			
		||||
      const srcSize = parseFloat(row.size);
 | 
			
		||||
      const index = Math.floor(Math.log(srcSize) / Math.log(1024));
 | 
			
		||||
      let size = srcSize / Math.pow(1024, index);
 | 
			
		||||
      size = size.toFixed(2);//保留的小数位数
 | 
			
		||||
      return size + ' ' + unitArr[index];
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,305 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="上传下载" url="https://doc.iocoder.cn/file/" />
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="配置名" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入配置名" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="存储器" prop="storage">
 | 
			
		||||
        <el-select v-model="queryParams.storage" placeholder="请选择存储器" clearable>
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.INFRA_FILE_STORAGE)"
 | 
			
		||||
                     :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['infra:file-config:create']">新增</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="编号" align="center" prop="id" />
 | 
			
		||||
      <el-table-column label="配置名" align="center" prop="name" />
 | 
			
		||||
      <el-table-column label="存储器" align="center" prop="storage">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.INFRA_FILE_STORAGE" :value="scope.row.storage" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="备注" align="center" prop="remark" />
 | 
			
		||||
      <el-table-column label="主配置" align="center" prop="primary">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.master" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="240">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                     v-hasPermi="['infra:file-config:update']">修改</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-attract" @click="handleMaster(scope.row)"
 | 
			
		||||
                     :disabled="scope.row.master" v-hasPermi="['infra:file-config:update']">主配置</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-share" @click="handleTest(scope.row)">测试</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-hasPermi="['infra:file-config:delete']">删除</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
 | 
			
		||||
        <el-form-item label="配置名" prop="name">
 | 
			
		||||
          <el-input v-model="form.name" placeholder="请输入配置名" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="备注" prop="remark">
 | 
			
		||||
          <el-input v-model="form.remark" placeholder="请输入备注" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="存储器" prop="storage">
 | 
			
		||||
          <el-select v-model="form.storage" placeholder="请选择存储器" :disabled="form.id !== undefined">
 | 
			
		||||
            <el-option v-for="dict in this.getDictDatas(DICT_TYPE.INFRA_FILE_STORAGE)"
 | 
			
		||||
                       :key="dict.value" :label="dict.label" :value="parseInt(dict.value)" />
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <!-- DB -->
 | 
			
		||||
        <!-- Local / FTP / SFTP -->
 | 
			
		||||
        <el-form-item v-if="form.storage >= 10 && form.storage <= 12" label="基础路径" prop="config.basePath">
 | 
			
		||||
          <el-input v-model="form.config.basePath" placeholder="请输入基础路径" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.storage >= 11 && form.storage <= 12" label="主机地址" prop="config.host">
 | 
			
		||||
          <el-input v-model="form.config.host" placeholder="请输入主机地址" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.storage >= 11 && form.storage <= 12" label="主机端口" prop="config.port">
 | 
			
		||||
          <el-input-number :min="0" v-model="form.config.port" placeholder="请输入主机端口" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.storage >= 11 && form.storage <= 12" label="用户名" prop="config.username">
 | 
			
		||||
          <el-input v-model="form.config.username" placeholder="请输入密码" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.storage >= 11 && form.storage <= 12" label="密码" prop="config.password">
 | 
			
		||||
          <el-input v-model="form.config.password" placeholder="请输入密码" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.storage === 11" label="连接模式" prop="config.mode">
 | 
			
		||||
          <el-radio-group v-model="form.config.mode">
 | 
			
		||||
            <el-radio key="Active" label="Active">主动模式</el-radio>
 | 
			
		||||
            <el-radio key="Passive" label="Passive">主动模式</el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <!-- S3 -->
 | 
			
		||||
        <el-form-item v-if="form.storage === 20" label="节点地址" prop="config.endpoint">
 | 
			
		||||
          <el-input v-model="form.config.endpoint" placeholder="请输入节点地址" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.storage === 20" label="存储 bucket" prop="config.bucket">
 | 
			
		||||
          <el-input v-model="form.config.bucket" placeholder="请输入 bucket" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.storage === 20" label="accessKey" prop="config.accessKey">
 | 
			
		||||
          <el-input v-model="form.config.accessKey" placeholder="请输入 accessKey" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.storage === 20" label="accessSecret" prop="config.accessSecret">
 | 
			
		||||
          <el-input v-model="form.config.accessSecret" placeholder="请输入 accessSecret" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <!-- 通用 -->
 | 
			
		||||
        <el-form-item v-if="form.storage === 20" label="自定义域名"> <!-- 无需参数校验,所以去掉 prop -->
 | 
			
		||||
          <el-input v-model="form.config.domain" placeholder="请输入自定义域名" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-else-if="form.storage" label="自定义域名" prop="config.domain">
 | 
			
		||||
          <el-input v-model="form.config.domain" placeholder="请输入自定义域名" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {
 | 
			
		||||
  createFileConfig,
 | 
			
		||||
  updateFileConfig,
 | 
			
		||||
  deleteFileConfig,
 | 
			
		||||
  getFileConfig,
 | 
			
		||||
  getFileConfigPage,
 | 
			
		||||
  testFileConfig, updateFileConfigMaster
 | 
			
		||||
} from "@/api/infra/fileConfig";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "InfraFileConfig",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 文件配置列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        name: null,
 | 
			
		||||
        storage: null,
 | 
			
		||||
        createTime: []
 | 
			
		||||
      },
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {
 | 
			
		||||
        storage: undefined,
 | 
			
		||||
        config: {}
 | 
			
		||||
      },
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        name: [{ required: true, message: "配置名不能为空", trigger: "blur" }],
 | 
			
		||||
        storage: [{ required: true, message: "存储器不能为空", trigger: "change" }],
 | 
			
		||||
        config: {
 | 
			
		||||
          basePath: [{ required: true, message: "基础路径不能为空", trigger: "blur" }],
 | 
			
		||||
          host: [{ required: true, message: "主机地址不能为空", trigger: "blur" }],
 | 
			
		||||
          port: [{ required: true, message: "主机端口不能为空", trigger: "blur" }],
 | 
			
		||||
          username: [{ required: true, message: "用户名不能为空", trigger: "blur" }],
 | 
			
		||||
          password: [{ required: true, message: "密码不能为空", trigger: "blur" }],
 | 
			
		||||
          mode: [{ required: true, message: "连接模式不能为空", trigger: "change" }],
 | 
			
		||||
          endpoint: [{ required: true, message: "节点地址不能为空", trigger: "blur" }],
 | 
			
		||||
          bucket: [{ required: true, message: "存储 bucket 不能为空", trigger: "blur" }],
 | 
			
		||||
          accessKey: [{ required: true, message: "accessKey 不能为空", trigger: "blur" }],
 | 
			
		||||
          accessSecret: [{ required: true, message: "accessSecret 不能为空", trigger: "blur" }],
 | 
			
		||||
          domain: [{ required: true, message: "自定义域名不能为空", trigger: "blur" }],
 | 
			
		||||
        },
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getFileConfigPage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        storage: undefined,
 | 
			
		||||
        remark: undefined,
 | 
			
		||||
        config: {},
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.title = "添加文件配置";
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      getFileConfig(id).then(response => {
 | 
			
		||||
        this.form = response.data;
 | 
			
		||||
        this.open = true;
 | 
			
		||||
        this.title = "修改文件配置";
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 修改的提交
 | 
			
		||||
        if (this.form.id != null) {
 | 
			
		||||
          updateFileConfig(this.form).then(response => {
 | 
			
		||||
            this.$modal.msgSuccess("修改成功");
 | 
			
		||||
            this.open = false;
 | 
			
		||||
            this.getList();
 | 
			
		||||
          });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 添加的提交
 | 
			
		||||
        createFileConfig(this.form).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("新增成功");
 | 
			
		||||
          this.open = false;
 | 
			
		||||
          this.getList();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认删除文件配置编号为"' + id + '"的数据项?').then(function() {
 | 
			
		||||
        return deleteFileConfig(id);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("删除成功");
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    /** 主配置按钮操作 */
 | 
			
		||||
    handleMaster(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认修改配置编号为"' + id + '"的数据项为主配置?').then(function() {
 | 
			
		||||
        return updateFileConfigMaster(id);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("修改成功");
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    /** 测试按钮操作 */
 | 
			
		||||
    handleTest(row) {
 | 
			
		||||
      testFileConfig(row.id).then((response) => {
 | 
			
		||||
        this.$modal.alert("测试通过,上传文件成功!访问地址:" + response.data);
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,378 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="定时任务" url="https://doc.iocoder.cn/job/" />
 | 
			
		||||
    <doc-alert title="异步任务" url="https://doc.iocoder.cn/async-task/" />
 | 
			
		||||
    <doc-alert title="消息队列" url="https://doc.iocoder.cn/message-queue/" />
 | 
			
		||||
    <!-- 搜索栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px">
 | 
			
		||||
      <el-form-item label="任务名称" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入任务名称" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="任务状态" prop="status">
 | 
			
		||||
        <el-select v-model="queryParams.status" placeholder="请选择任务状态" clearable>
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.INFRA_JOB_STATUS)"
 | 
			
		||||
                     :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="处理器的名字" prop="handlerName">
 | 
			
		||||
        <el-input v-model="queryParams.handlerName" placeholder="请输入处理器的名字" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['infra:job:create']">新增</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport" :loading="exportLoading"
 | 
			
		||||
                   v-hasPermi="['infra:job:export']">导出</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="info" icon="el-icon-s-operation" size="mini" @click="handleJobLog"
 | 
			
		||||
                   v-hasPermi="['infra:job:query']">执行日志</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <el-table v-loading="loading" :data="jobList">
 | 
			
		||||
      <el-table-column label="任务编号" align="center" prop="id" />
 | 
			
		||||
      <el-table-column label="任务名称" align="center" prop="name" />
 | 
			
		||||
      <el-table-column label="任务状态" align="center" prop="status">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.INFRA_JOB_STATUS" :value="scope.row.status" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>>
 | 
			
		||||
      <el-table-column label="处理器的名字" align="center" prop="handlerName" />
 | 
			
		||||
      <el-table-column label="处理器的参数" align="center" prop="handlerParam" />
 | 
			
		||||
      <el-table-column label="CRON 表达式" align="center" prop="cronExpression" />
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                     v-hasPermi="['infra:job:update']">修改</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-check" @click="handleChangeStatus(scope.row, true)"
 | 
			
		||||
                     v-if="scope.row.status === InfJobStatusEnum.STOP" v-hasPermi="['infra:job:update']">开启</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-close" @click="handleChangeStatus(scope.row, false)"
 | 
			
		||||
                     v-if="scope.row.status === InfJobStatusEnum.NORMAL" v-hasPermi="['infra:job:update']">暂停</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-hasPermi="['infra:job:delete']">删除</el-button>
 | 
			
		||||
          <el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)"
 | 
			
		||||
                       v-hasPermi="['infra:job:trigger', 'infra:job:query']">
 | 
			
		||||
            <el-button size="mini" type="text" icon="el-icon-d-arrow-right">更多</el-button>
 | 
			
		||||
            <el-dropdown-menu slot="dropdown">
 | 
			
		||||
              <el-dropdown-item command="handleRun" icon="el-icon-caret-right"
 | 
			
		||||
                                v-hasPermi="['infra:job:trigger']">执行一次</el-dropdown-item>
 | 
			
		||||
              <el-dropdown-item command="handleView" icon="el-icon-view"
 | 
			
		||||
                                v-hasPermi="['infra:job:query']">任务详细</el-dropdown-item>
 | 
			
		||||
              <el-dropdown-item command="handleJobLog" icon="el-icon-s-operation"
 | 
			
		||||
                                v-hasPermi="['infra:job:query']">调度日志</el-dropdown-item>
 | 
			
		||||
            </el-dropdown-menu>
 | 
			
		||||
          </el-dropdown>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 添加或修改定时任务对话框 -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
 | 
			
		||||
        <el-form-item label="任务名称" prop="name">
 | 
			
		||||
          <el-input v-model="form.name" placeholder="请输入任务名称" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="处理器的名字" prop="handlerName">
 | 
			
		||||
          <el-input v-model="form.handlerName" placeholder="请输入处理器的名字" v-bind:readonly="form.id !== undefined" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="处理器的参数" prop="handlerParam">
 | 
			
		||||
          <el-input v-model="form.handlerParam" placeholder="请输入处理器的参数" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="CRON 表达式" prop="cronExpression">
 | 
			
		||||
          <el-input v-model="form.cronExpression" placeholder="请输入CRON 表达式">
 | 
			
		||||
            <template slot="append">
 | 
			
		||||
              <el-button type="primary" @click="handleShowCron">
 | 
			
		||||
                生成表达式
 | 
			
		||||
                <i class="el-icon-time el-icon--right"></i>
 | 
			
		||||
              </el-button>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-input>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="重试次数" prop="retryCount">
 | 
			
		||||
          <el-input v-model="form.retryCount" placeholder="请输入重试次数。设置为 0 时,不进行重试" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="重试间隔" prop="retryInterval">
 | 
			
		||||
          <el-input v-model="form.retryInterval" placeholder="请输入重试间隔,单位:毫秒。设置为 0 时,无需间隔" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="监控超时时间" prop="monitorTimeout">
 | 
			
		||||
          <el-input v-model="form.monitorTimeout" placeholder="请输入监控超时时间,单位:毫秒" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
 | 
			
		||||
    <el-dialog title="Cron表达式生成器" :visible.sync="openCron" append-to-body class="scrollbar" destroy-on-close>
 | 
			
		||||
      <crontab @hide="openCron=false" @fill="crontabFill" :expression="expression"></crontab>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
 | 
			
		||||
    <!-- 任务详细 -->
 | 
			
		||||
    <el-dialog title="任务详细" :visible.sync="openView" width="700px" append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" label-width="200px" size="mini">
 | 
			
		||||
        <el-row>
 | 
			
		||||
          <el-col :span="24">
 | 
			
		||||
            <el-form-item label="任务编号:">{{ form.id }}</el-form-item>
 | 
			
		||||
            <el-form-item label="任务名称:">{{ form.name }}</el-form-item>
 | 
			
		||||
            <el-form-item label="任务名称:">
 | 
			
		||||
              <dict-tag :type="DICT_TYPE.INFRA_JOB_STATUS" :value="form.status" />
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="处理器的名字:">{{ form.handlerName }}</el-form-item>
 | 
			
		||||
            <el-form-item label="处理器的参数:">{{ form.handlerParam }}</el-form-item>
 | 
			
		||||
            <el-form-item label="cron表达式:">{{ form.cronExpression }}</el-form-item>
 | 
			
		||||
            <el-form-item label="重试次数:">{{ form.retryCount }}</el-form-item>
 | 
			
		||||
            <el-form-item label="重试间隔:">{{ form.retryInterval + " 毫秒" }}</el-form-item>
 | 
			
		||||
            <el-form-item label="监控超时时间:">{{ form.monitorTimeout > 0 ? form.monitorTimeout + " 毫秒" : "未开启" }}</el-form-item>
 | 
			
		||||
            <el-form-item label="后续执行时间:">{{ Array.from(nextTimes, x => parseTime(x)).join('; ')}}</el-form-item>
 | 
			
		||||
          </el-col>
 | 
			
		||||
        </el-row>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button @click="openView = false">关 闭</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { listJob, getJob, delJob, addJob, updateJob, exportJob, runJob, updateJobStatus, getJobNextTimes } from "@/api/infra/job";
 | 
			
		||||
import { InfraJobStatusEnum } from "@/utils/constants";
 | 
			
		||||
import Crontab from '@/components/Crontab'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  components: { Crontab },
 | 
			
		||||
  name: "InfraJob",
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 导出遮罩层
 | 
			
		||||
      exportLoading: false,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 定时任务表格数据
 | 
			
		||||
      jobList: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 是否显示详细弹出层
 | 
			
		||||
      openView: false,
 | 
			
		||||
      // 是否显示Cron表达式弹出层
 | 
			
		||||
      openCron: false,
 | 
			
		||||
      // 传入的表达式
 | 
			
		||||
      expression: "",
 | 
			
		||||
      // 状态字典
 | 
			
		||||
      statusOptions: [],
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        status: undefined,
 | 
			
		||||
        handlerName: undefined
 | 
			
		||||
      },
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {},
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        name: [{ required: true, message: "任务名称不能为空", trigger: "blur" }],
 | 
			
		||||
        handlerName: [{ required: true, message: "处理器的名字不能为空", trigger: "blur" }],
 | 
			
		||||
        cronExpression: [{ required: true, message: "CRON 表达式不能为空", trigger: "blur" }],
 | 
			
		||||
        retryCount: [{ required: true, message: "重试次数不能为空", trigger: "blur" }],
 | 
			
		||||
        retryInterval: [{ required: true, message: "重试间隔不能为空", trigger: "blur" }],
 | 
			
		||||
      },
 | 
			
		||||
      nextTimes: [], // 后续执行时间
 | 
			
		||||
 | 
			
		||||
      // 枚举
 | 
			
		||||
      InfJobStatusEnum: InfraJobStatusEnum
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询定时任务列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      listJob(this.queryParams).then(response => {
 | 
			
		||||
        this.jobList = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        handlerName: undefined,
 | 
			
		||||
        handlerParam: undefined,
 | 
			
		||||
        cronExpression: undefined,
 | 
			
		||||
        retryCount: undefined,
 | 
			
		||||
        retryInterval: undefined,
 | 
			
		||||
        monitorTimeout: undefined,
 | 
			
		||||
      };
 | 
			
		||||
      this.nextTimes = [];
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 立即执行一次 **/
 | 
			
		||||
    handleRun(row) {
 | 
			
		||||
      this.$modal.confirm('确认要立即执行一次"' + row.name + '"任务吗?').then(function() {
 | 
			
		||||
          return runJob(row.id);
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          this.$modal.msgSuccess("执行成功");
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    /** 任务详细信息 */
 | 
			
		||||
    handleView(row) {
 | 
			
		||||
      getJob(row.id).then(response => {
 | 
			
		||||
        this.form = response.data;
 | 
			
		||||
        this.openView = true;
 | 
			
		||||
      });
 | 
			
		||||
      // 获取下一次执行时间
 | 
			
		||||
      getJobNextTimes(row.id).then(response => {
 | 
			
		||||
        this.nextTimes = response.data;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** cron表达式按钮操作 */
 | 
			
		||||
    handleShowCron() {
 | 
			
		||||
      this.expression = this.form.cronExpression;
 | 
			
		||||
      this.openCron = true;
 | 
			
		||||
    },
 | 
			
		||||
    /** 确定后回传值 */
 | 
			
		||||
    crontabFill(value) {
 | 
			
		||||
      this.form.cronExpression = value;
 | 
			
		||||
    },
 | 
			
		||||
    /** 任务日志列表查询 */
 | 
			
		||||
    handleJobLog(row) {
 | 
			
		||||
      if (row.id) {
 | 
			
		||||
        this.$router.push({
 | 
			
		||||
          path:"/job/log",
 | 
			
		||||
          query:{
 | 
			
		||||
            jobId: row.id
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      } else {
 | 
			
		||||
        this.$router.push("/job/log");
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.title = "添加任务";
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      getJob(id).then(response => {
 | 
			
		||||
        this.form = response.data;
 | 
			
		||||
        this.open = true;
 | 
			
		||||
        this.title = "修改任务";
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm: function() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (valid) {
 | 
			
		||||
          if (this.form.id !== undefined) {
 | 
			
		||||
            updateJob(this.form).then(response => {
 | 
			
		||||
              this.$modal.msgSuccess("修改成功");
 | 
			
		||||
              this.open = false;
 | 
			
		||||
              this.getList();
 | 
			
		||||
            });
 | 
			
		||||
          } else {
 | 
			
		||||
            addJob(this.form).then(response => {
 | 
			
		||||
              this.$modal.msgSuccess("新增成功");
 | 
			
		||||
              this.open = false;
 | 
			
		||||
              this.getList();
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const ids = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认删除定时任务编号为"' + ids + '"的数据项?').then(function() {
 | 
			
		||||
          return delJob(ids);
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          this.getList();
 | 
			
		||||
          this.$modal.msgSuccess("删除成功");
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    /** 更新状态操作 */
 | 
			
		||||
    handleChangeStatus(row, open) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      let status = open ? InfraJobStatusEnum.NORMAL : InfraJobStatusEnum.STOP;
 | 
			
		||||
      let statusStr = open ? '开启' : '关闭';
 | 
			
		||||
      this.$modal.confirm('是否确认' + statusStr + '定时任务编号为"' + id + '"的数据项?').then(function() {
 | 
			
		||||
        return updateJobStatus(id, status);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess(statusStr + "成功");
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    // 更多操作触发
 | 
			
		||||
    handleCommand(command, row) {
 | 
			
		||||
      switch (command) {
 | 
			
		||||
        case "handleRun":
 | 
			
		||||
          this.handleRun(row);
 | 
			
		||||
          break;
 | 
			
		||||
        case "handleView":
 | 
			
		||||
          this.handleView(row);
 | 
			
		||||
          break;
 | 
			
		||||
        case "handleJobLog":
 | 
			
		||||
          this.handleJobLog(row);
 | 
			
		||||
          break;
 | 
			
		||||
        default:
 | 
			
		||||
          break;
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    /** 导出按钮操作 */
 | 
			
		||||
    handleExport() {
 | 
			
		||||
      const queryParams = this.queryParams;
 | 
			
		||||
      this.$modal.confirm("是否确认导出所有定时任务数据项?").then(() => {
 | 
			
		||||
          this.exportLoading = true;
 | 
			
		||||
          return exportJob(queryParams);
 | 
			
		||||
        }).then(response => {
 | 
			
		||||
          this.$download.excel(response, '定时任务.xls');
 | 
			
		||||
          this.exportLoading = false;
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,181 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="定时任务" url="https://doc.iocoder.cn/job/" />
 | 
			
		||||
    <doc-alert title="异步任务" url="https://doc.iocoder.cn/async-task/" />
 | 
			
		||||
    <doc-alert title="消息队列" url="https://doc.iocoder.cn/message-queue/" />
 | 
			
		||||
    <!-- 搜索栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
 | 
			
		||||
      <el-form-item label="处理器的名字" prop="handlerName">
 | 
			
		||||
        <el-input v-model="queryParams.handlerName" placeholder="请输入处理器的名字" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="开始执行时间" prop="beginTime">
 | 
			
		||||
        <el-date-picker clearable v-model="queryParams.beginTime" type="date" value-format="yyyy-MM-dd" placeholder="选择开始执行时间" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="结束执行时间" prop="endTime">
 | 
			
		||||
        <el-date-picker clearable v-model="queryParams.endTime" type="date" value-format="yyyy-MM-dd" placeholder="选择结束执行时间" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="任务状态" prop="status">
 | 
			
		||||
        <el-select v-model="queryParams.status" placeholder="请选择任务状态" clearable>
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.INFRA_JOB_LOG_STATUS)"
 | 
			
		||||
                     :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport"
 | 
			
		||||
                   v-hasPermi="['infra:job:export']">导出</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="日志编号" align="center" prop="id" />
 | 
			
		||||
      <el-table-column label="任务编号" align="center" prop="jobId" />
 | 
			
		||||
      <el-table-column label="处理器的名字" align="center" prop="handlerName" />
 | 
			
		||||
      <el-table-column label="处理器的参数" align="center" prop="handlerParam" />
 | 
			
		||||
      <el-table-column label="第几次执行" align="center" prop="executeIndex" />
 | 
			
		||||
      <el-table-column label="执行时间" align="center" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.beginTime) + ' ~ ' + parseTime(scope.row.endTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="执行时长" align="center" prop="duration">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ scope.row.duration + ' 毫秒' }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="任务状态" align="center" prop="status">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.INFRA_JOB_LOG_STATUS" :value="scope.row.status" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)" :loading="exportLoading"
 | 
			
		||||
                     v-hasPermi="['infra:job:query']">详细</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
 | 
			
		||||
    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 调度日志详细 -->
 | 
			
		||||
    <el-dialog title="调度日志详细" :visible.sync="open" width="700px" append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" label-width="120px" size="mini">
 | 
			
		||||
        <el-row>
 | 
			
		||||
          <el-col :span="12">
 | 
			
		||||
            <el-form-item label="日志编号:">{{ form.id }}</el-form-item>
 | 
			
		||||
            <el-form-item label="任务编号:">{{ form.jobId }}</el-form-item>
 | 
			
		||||
            <el-form-item label="处理器的名字:">{{ form.handlerName }}</el-form-item>
 | 
			
		||||
            <el-form-item label="处理器的参数:">{{ form.handlerParam }}</el-form-item>
 | 
			
		||||
            <el-form-item label="第几次执行:">{{ form.executeIndex }}</el-form-item>
 | 
			
		||||
            <el-form-item label="执行时间:">{{ parseTime(form.beginTime) + ' ~ ' + parseTime(form.endTime) }}</el-form-item>
 | 
			
		||||
            <el-form-item label="执行时长:">{{ form.duration + ' 毫秒' }}</el-form-item>
 | 
			
		||||
            <el-form-item label="任务状态:">
 | 
			
		||||
              <dict-tag :type="DICT_TYPE.INFRA_JOB_LOG_STATUS" :value="form.status" />
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="执行结果:">{{ form.result }}</el-form-item>
 | 
			
		||||
          </el-col>
 | 
			
		||||
        </el-row>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button @click="open = false">关 闭</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { getJobLogPage, exportJobLogExcel } from "@/api/infra/jobLog";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "InfraJobLog",
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 导出遮罩层
 | 
			
		||||
      exportLoading: false,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 调度日志表格数据
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {},
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        handlerName: null,
 | 
			
		||||
        beginTime: null,
 | 
			
		||||
        endTime: null,
 | 
			
		||||
        status: null,
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.queryParams.jobId = this.$route.query && this.$route.query.jobId;
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询调度日志列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      getJobLogPage({
 | 
			
		||||
        ...this.queryParams,
 | 
			
		||||
        beginTime: this.queryParams.beginTime ? this.queryParams.beginTime + ' 00:00:00' : undefined,
 | 
			
		||||
        endTime: this.queryParams.endTime ? this.queryParams.endTime + ' 23:59:59' : undefined,
 | 
			
		||||
      }).then(response => {
 | 
			
		||||
          this.list = response.data.list;
 | 
			
		||||
          this.total = response.data.total;
 | 
			
		||||
          this.loading = false;
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 详细按钮操作 */
 | 
			
		||||
    handleView(row) {
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.form = row;
 | 
			
		||||
    },
 | 
			
		||||
    /** 导出按钮操作 */
 | 
			
		||||
    handleExport() {
 | 
			
		||||
      // 处理查询参数
 | 
			
		||||
      let params = {...this.queryParams,
 | 
			
		||||
        beginTime: this.queryParams.beginTime ? this.queryParams.beginTime + ' 00:00:00' : undefined,
 | 
			
		||||
        endTime: this.queryParams.endTime ? this.queryParams.endTime + ' 23:59:59' : undefined,
 | 
			
		||||
      };
 | 
			
		||||
      params.pageNo = undefined;
 | 
			
		||||
      params.pageSize = undefined;
 | 
			
		||||
      // 执行导出
 | 
			
		||||
      this.$modal.confirm('是否确认导出所有定时任务日志数据项?').then(() => {
 | 
			
		||||
        this.exportLoading = true;
 | 
			
		||||
        return exportJobLogExcel(params);
 | 
			
		||||
      }).then(response => {
 | 
			
		||||
        this.$download.excel(response, '定时任务日志.xls');
 | 
			
		||||
        this.exportLoading = false;
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,157 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="Redis 缓存" url="https://doc.iocoder.cn/redis-cache/" />
 | 
			
		||||
    <doc-alert title="本地缓存" url="https://doc.iocoder.cn/local-cache/" />
 | 
			
		||||
    <el-row>
 | 
			
		||||
      <el-col :span="24" class="card-box">
 | 
			
		||||
        <el-card>
 | 
			
		||||
          <div slot="header"><span>基本信息</span></div>
 | 
			
		||||
          <div class="el-table el-table--enable-row-hover el-table--medium">
 | 
			
		||||
            <table cellspacing="0" style="width: 100%">
 | 
			
		||||
              <tbody>
 | 
			
		||||
                <tr>
 | 
			
		||||
                  <td><div class="cell">Redis版本</div></td>
 | 
			
		||||
                  <td><div class="cell" v-if="cache.info">{{ cache.info.redis_version }}</div></td>
 | 
			
		||||
                  <td><div class="cell">运行模式</div></td>
 | 
			
		||||
                  <td><div class="cell" v-if="cache.info">{{ cache.info.redis_mode === "standalone" ? "单机" : "集群" }}</div></td>
 | 
			
		||||
                  <td><div class="cell">端口</div></td>
 | 
			
		||||
                  <td><div class="cell" v-if="cache.info">{{ cache.info.tcp_port }}</div></td>
 | 
			
		||||
                  <td><div class="cell">客户端数</div></td>
 | 
			
		||||
                  <td><div class="cell" v-if="cache.info">{{ cache.info.connected_clients }}</div></td>
 | 
			
		||||
                </tr>
 | 
			
		||||
                <tr>
 | 
			
		||||
                  <td><div class="cell">运行时间(天)</div></td>
 | 
			
		||||
                  <td><div class="cell" v-if="cache.info">{{ cache.info.uptime_in_days }}</div></td>
 | 
			
		||||
                  <td><div class="cell">使用内存</div></td>
 | 
			
		||||
                  <td><div class="cell" v-if="cache.info">{{ cache.info.used_memory_human }}</div></td>
 | 
			
		||||
                  <td><div class="cell">使用CPU</div></td>
 | 
			
		||||
                  <td><div class="cell" v-if="cache.info">{{ parseFloat(cache.info.used_cpu_user_children).toFixed(2) }}</div></td>
 | 
			
		||||
                  <td><div class="cell">内存配置</div></td>
 | 
			
		||||
                  <td><div class="cell" v-if="cache.info">{{ cache.info.maxmemory_human }}</div></td>
 | 
			
		||||
                </tr>
 | 
			
		||||
                <tr>
 | 
			
		||||
                  <td><div class="cell">AOF是否开启</div></td>
 | 
			
		||||
                  <td><div class="cell" v-if="cache.info">{{ cache.info.aof_enabled === "0" ? "否" : "是" }}</div></td>
 | 
			
		||||
                  <td><div class="cell">RDB是否成功</div></td>
 | 
			
		||||
                  <td><div class="cell" v-if="cache.info">{{ cache.info.rdb_last_bgsave_status }}</div></td>
 | 
			
		||||
                  <td><div class="cell">Key数量</div></td>
 | 
			
		||||
                  <td><div class="cell" v-if="cache.dbSize">{{ cache.dbSize }} </div></td>
 | 
			
		||||
                  <td><div class="cell">网络入口/出口</div></td>
 | 
			
		||||
                  <td><div class="cell" v-if="cache.info">{{ cache.info.instantaneous_input_kbps }}kps/{{cache.info.instantaneous_output_kbps}}kps</div></td>
 | 
			
		||||
                </tr>
 | 
			
		||||
              </tbody>
 | 
			
		||||
            </table>
 | 
			
		||||
          </div>
 | 
			
		||||
        </el-card>
 | 
			
		||||
      </el-col>
 | 
			
		||||
 | 
			
		||||
      <el-col :span="12" class="card-box">
 | 
			
		||||
        <el-card>
 | 
			
		||||
          <div slot="header"><span>命令统计</span></div>
 | 
			
		||||
          <div class="el-table el-table--enable-row-hover el-table--medium">
 | 
			
		||||
            <div ref="commandstats" style="height: 420px" />
 | 
			
		||||
          </div>
 | 
			
		||||
        </el-card>
 | 
			
		||||
      </el-col>
 | 
			
		||||
 | 
			
		||||
      <el-col :span="12" class="card-box">
 | 
			
		||||
        <el-card>
 | 
			
		||||
          <div slot="header">
 | 
			
		||||
            <span>内存信息</span>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div class="el-table el-table--enable-row-hover el-table--medium">
 | 
			
		||||
            <div ref="usedmemory" style="height: 420px" />
 | 
			
		||||
          </div>
 | 
			
		||||
        </el-card>
 | 
			
		||||
      </el-col>
 | 
			
		||||
    </el-row>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { getCache } from "@/api/infra/redis";
 | 
			
		||||
import * as echarts from 'echarts'
 | 
			
		||||
require('echarts/theme/macarons') // echarts theme
 | 
			
		||||
export default {
 | 
			
		||||
  name: "InfraRedis",
 | 
			
		||||
  data () {
 | 
			
		||||
    return {
 | 
			
		||||
      // 统计命令信息
 | 
			
		||||
      commandstats: null,
 | 
			
		||||
      // 使用内存
 | 
			
		||||
      usedmemory: null,
 | 
			
		||||
      // cache 信息
 | 
			
		||||
      cache: []
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created () {
 | 
			
		||||
    this.getList();
 | 
			
		||||
    this.openLoading();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查缓存询信息 */
 | 
			
		||||
    getList () {
 | 
			
		||||
      // 查询 Redis 监控信息
 | 
			
		||||
      getCache().then((response) => {
 | 
			
		||||
        this.cache = response.data;
 | 
			
		||||
        this.$modal.closeLoading();
 | 
			
		||||
 | 
			
		||||
        this.commandstats = echarts.init(this.$refs.commandstats, "macarons");
 | 
			
		||||
        const commandStats = [];
 | 
			
		||||
        response.data.commandStats.forEach(row => {
 | 
			
		||||
          commandStats.push({
 | 
			
		||||
            name: row.command,
 | 
			
		||||
            value: row.calls
 | 
			
		||||
          });
 | 
			
		||||
        })
 | 
			
		||||
        this.commandstats.setOption({
 | 
			
		||||
          tooltip: {
 | 
			
		||||
            trigger: "item",
 | 
			
		||||
            formatter: "{a} <br/>{b} : {c} ({d}%)",
 | 
			
		||||
          },
 | 
			
		||||
          series: [
 | 
			
		||||
            {
 | 
			
		||||
              name: "命令",
 | 
			
		||||
              type: "pie",
 | 
			
		||||
              roseType: "radius",
 | 
			
		||||
              radius: [15, 95],
 | 
			
		||||
              center: ["50%", "38%"],
 | 
			
		||||
              data: commandStats,
 | 
			
		||||
              animationEasing: "cubicInOut",
 | 
			
		||||
              animationDuration: 1000,
 | 
			
		||||
            },
 | 
			
		||||
          ],
 | 
			
		||||
        });
 | 
			
		||||
        this.usedmemory = echarts.init(this.$refs.usedmemory, "macarons");
 | 
			
		||||
        this.usedmemory.setOption({
 | 
			
		||||
          tooltip: {
 | 
			
		||||
            formatter: "{b} <br/>{a} : " + this.cache.info.used_memory_human,
 | 
			
		||||
          },
 | 
			
		||||
          series: [
 | 
			
		||||
            {
 | 
			
		||||
              name: "峰值",
 | 
			
		||||
              type: "gauge",
 | 
			
		||||
              min: 0,
 | 
			
		||||
              max: 1000,
 | 
			
		||||
              detail: {
 | 
			
		||||
                formatter: this.cache.info.used_memory_human,
 | 
			
		||||
              },
 | 
			
		||||
              data: [
 | 
			
		||||
                {
 | 
			
		||||
                  value: parseFloat(this.cache.info.used_memory_human),
 | 
			
		||||
                  name: "内存消耗",
 | 
			
		||||
                },
 | 
			
		||||
              ],
 | 
			
		||||
            },
 | 
			
		||||
          ],
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // 打开加载层
 | 
			
		||||
    openLoading () {
 | 
			
		||||
      this.$modal.loading("正在加载缓存监控数据,请稍后!");
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,30 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <doc-alert title="服务监控" url="https://doc.iocoder.cn/server-monitor/" />
 | 
			
		||||
    <i-frame v-if="!loading" :src="url" />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
import iFrame from "@/components/iFrame/index";
 | 
			
		||||
import { getConfigKey } from "@/api/infra/config";
 | 
			
		||||
export default {
 | 
			
		||||
  name: "InfraAdminServer",
 | 
			
		||||
  components: { iFrame },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      url: process.env.VUE_APP_BASE_API + "/admin/applications",
 | 
			
		||||
      loading: true
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    getConfigKey("url.spring-boot-admin").then(response => {
 | 
			
		||||
      if (!response.data || response.data.length === 0) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
      this.url = response.data;
 | 
			
		||||
    }).finally(() => {
 | 
			
		||||
      this.loading = false;
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,30 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <doc-alert title="服务监控" url="https://doc.iocoder.cn/server-monitor/" />
 | 
			
		||||
    <i-frame v-if="!loading" :src="url" />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
import iFrame from "@/components/iFrame/index";
 | 
			
		||||
import { getConfigKey } from "@/api/infra/config";
 | 
			
		||||
export default {
 | 
			
		||||
  name: "InfraSkyWalking",
 | 
			
		||||
  components: { iFrame },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      url: "http://skywalking.shop.iocoder.cn",
 | 
			
		||||
      loading: true
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    getConfigKey("url.skywalking").then(response => {
 | 
			
		||||
      if (!response.data || response.data.length === 0) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
      this.url = response.data;
 | 
			
		||||
    }).finally(() => {
 | 
			
		||||
      this.loading = false;
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,31 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <doc-alert title="接口文档" url="https://doc.iocoder.cn/api-doc/" />
 | 
			
		||||
    <i-frame v-if="!loading" :src="url" />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
import iFrame from "@/components/iFrame/index";
 | 
			
		||||
import { getConfigKey } from "@/api/infra/config";
 | 
			
		||||
export default {
 | 
			
		||||
  name: "InfraSwagger",
 | 
			
		||||
  components: { iFrame },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      url: process.env.VUE_APP_BASE_API + "/doc.html", // Knife4j UI
 | 
			
		||||
      // url: process.env.VUE_APP_BASE_API + "/swagger-ui", // Swagger UI
 | 
			
		||||
      loading: true
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    getConfigKey("url.swagger").then(response => {
 | 
			
		||||
      if (!response.data || response.data.length === 0) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
      this.url = response.data;
 | 
			
		||||
    }).finally(() => {
 | 
			
		||||
      this.loading = false;
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,257 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="名字" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入名字" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="状态" prop="status">
 | 
			
		||||
        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
 | 
			
		||||
          <el-option label="请选择字典生成" value="" />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="类型" prop="type">
 | 
			
		||||
        <el-select v-model="queryParams.type" placeholder="请选择类型" clearable>
 | 
			
		||||
          <el-option label="请选择字典生成" value="" />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="分类" prop="category">
 | 
			
		||||
        <el-input v-model="queryParams.category" placeholder="请输入分类" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="备注" prop="remark">
 | 
			
		||||
        <el-input v-model="queryParams.remark" placeholder="请输入备注" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['infra:test-demo:create']">新增</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" :loading="exportLoading"
 | 
			
		||||
                   v-hasPermi="['infra:test-demo:export']">导出</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="编号" align="center" prop="id" />
 | 
			
		||||
      <el-table-column label="名字" align="center" prop="name" />
 | 
			
		||||
      <el-table-column label="状态" align="center" prop="status" />
 | 
			
		||||
      <el-table-column label="类型" align="center" prop="type" />
 | 
			
		||||
      <el-table-column label="分类" align="center" prop="category" />
 | 
			
		||||
      <el-table-column label="备注" align="center" prop="remark" />
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                     v-hasPermi="['infra:test-demo:update']">修改</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-hasPermi="['infra:test-demo:delete']">删除</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
 | 
			
		||||
        <el-form-item label="名字" prop="name">
 | 
			
		||||
          <el-input v-model="form.name" placeholder="请输入名字" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="状态" prop="status">
 | 
			
		||||
          <el-radio-group v-model="form.status">
 | 
			
		||||
            <el-radio label="1">请选择字典生成</el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="类型" prop="type">
 | 
			
		||||
          <el-select v-model="form.type" placeholder="请选择类型">
 | 
			
		||||
            <el-option label="请选择字典生成" value="" />
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="分类" prop="category">
 | 
			
		||||
          <el-input v-model="form.category" placeholder="请输入分类" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="备注" prop="remark">
 | 
			
		||||
          <el-input v-model="form.remark" placeholder="请输入备注" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { createTestDemo, updateTestDemo, deleteTestDemo, getTestDemo, getTestDemoPage, exportTestDemoExcel } from "@/api/infra/testDemo";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "TestDemo",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 导出遮罩层
 | 
			
		||||
      exportLoading: false,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 字典类型列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        name: null,
 | 
			
		||||
        status: null,
 | 
			
		||||
        type: null,
 | 
			
		||||
        category: null,
 | 
			
		||||
        remark: null,
 | 
			
		||||
        createTime: []
 | 
			
		||||
      },
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {},
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        name: [{ required: true, message: "名字不能为空", trigger: "blur" }],
 | 
			
		||||
        status: [{ required: true, message: "状态不能为空", trigger: "blur" }],
 | 
			
		||||
        type: [{ required: true, message: "类型不能为空", trigger: "change" }],
 | 
			
		||||
        category: [{ required: true, message: "分类不能为空", trigger: "blur" }],
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getTestDemoPage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        status: undefined,
 | 
			
		||||
        type: undefined,
 | 
			
		||||
        category: undefined,
 | 
			
		||||
        remark: undefined,
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.title = "添加字典类型";
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      getTestDemo(id).then(response => {
 | 
			
		||||
        this.form = response.data;
 | 
			
		||||
        this.open = true;
 | 
			
		||||
        this.title = "修改字典类型";
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 修改的提交
 | 
			
		||||
        if (this.form.id != null) {
 | 
			
		||||
          updateTestDemo(this.form).then(response => {
 | 
			
		||||
            this.$modal.msgSuccess("修改成功");
 | 
			
		||||
            this.open = false;
 | 
			
		||||
            this.getList();
 | 
			
		||||
          });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 添加的提交
 | 
			
		||||
        createTestDemo(this.form).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("新增成功");
 | 
			
		||||
          this.open = false;
 | 
			
		||||
          this.getList();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认删除字典类型编号为"' + id + '"的数据项?').then(function() {
 | 
			
		||||
          return deleteTestDemo(id);
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          this.getList();
 | 
			
		||||
          this.$modal.msgSuccess("删除成功");
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    /** 导出按钮操作 */
 | 
			
		||||
    handleExport() {
 | 
			
		||||
      // 处理查询参数
 | 
			
		||||
      let params = {...this.queryParams};
 | 
			
		||||
      params.pageNo = undefined;
 | 
			
		||||
      params.pageSize = undefined;
 | 
			
		||||
      // 执行导出
 | 
			
		||||
      this.$modal.confirm('是否确认导出所有字典类型数据项?').then(() => {
 | 
			
		||||
          this.exportLoading = true;
 | 
			
		||||
          return exportTestDemoExcel(params);
 | 
			
		||||
        }).then(response => {
 | 
			
		||||
          this.$download.excel(response, '字典类型.xls');
 | 
			
		||||
          this.exportLoading = false;
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,92 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <el-form label-width="120px">
 | 
			
		||||
      <el-row type="flex" :gutter="0">
 | 
			
		||||
        <el-col :sm="12">
 | 
			
		||||
          <el-form-item label="WebSocket地址" size="small">
 | 
			
		||||
            <el-input v-model="url" type="text"/>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </el-col>
 | 
			
		||||
        <el-col :offset="1">
 | 
			
		||||
          <el-form-item label="" label-width="0px" size="small">
 | 
			
		||||
            <el-button @click="connect" type="primary" :disabled="ws&&ws.readyState===1">
 | 
			
		||||
              {{ ws && ws.readyState === 1 ? "已连接" : "连接" }}
 | 
			
		||||
            </el-button>
 | 
			
		||||
            <el-button @click="exit" type="danger">断开</el-button>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </el-col>
 | 
			
		||||
      </el-row>
 | 
			
		||||
      <el-form-item label="发送内容" size="small">
 | 
			
		||||
        <el-input type="textarea" v-model="message" :rows="5"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="" size="small">
 | 
			
		||||
        <el-button type="success" @click="send">发送消息</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="接收内容" size="small">
 | 
			
		||||
        <el-input type="textarea" v-model="content" :rows="12" disabled/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="" size="small">
 | 
			
		||||
        <el-button type="info" @click="content=''">清空消息</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import store from "@/store";
 | 
			
		||||
import {getNowDateTime} from "@/utils/ruoyi";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      url: process.env.VUE_APP_BASE_API + "/websocket/message",
 | 
			
		||||
      message: "",
 | 
			
		||||
      content: "",
 | 
			
		||||
      ws: null,
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.url = this.url.replace("http", "ws")
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    connect() {
 | 
			
		||||
      if (!'WebSocket' in window) {
 | 
			
		||||
        this.$modal.msgError("您的浏览器不支持WebSocket");
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      const userId = store.getters.userId;
 | 
			
		||||
      this.ws = new WebSocket(this.url + "?userId=" + userId);
 | 
			
		||||
      const self = this;
 | 
			
		||||
      this.ws.onopen = function (event) {
 | 
			
		||||
        self.content = self.content + "\n**********************连接开始**********************\n";
 | 
			
		||||
      };
 | 
			
		||||
      this.ws.onmessage = function (event) {
 | 
			
		||||
        self.content = self.content + "接收时间:" + getNowDateTime() + "\n" + event.data + "\n";
 | 
			
		||||
      };
 | 
			
		||||
      this.ws.onclose = function (event) {
 | 
			
		||||
        self.content = self.content + "**********************连接关闭**********************\n";
 | 
			
		||||
      };
 | 
			
		||||
      this.ws.error = function (event) {
 | 
			
		||||
        self.content = self.content + "**********************连接异常**********************\n";
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
    exit() {
 | 
			
		||||
      if (this.ws) {
 | 
			
		||||
        this.ws.close();
 | 
			
		||||
        this.ws = null;
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    send() {
 | 
			
		||||
      if (!this.ws || this.ws.readyState !== 1) {
 | 
			
		||||
        this.$modal.msgError("未连接到服务器");
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      if (!this.message) {
 | 
			
		||||
        this.$modal.msgError("请输入发送内容");
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      this.ws.send(this.message);
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,261 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="标题" prop="title">
 | 
			
		||||
        <el-input v-model="queryParams.title" placeholder="请输入标题" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="状态" prop="status">
 | 
			
		||||
        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
 | 
			
		||||
                     :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['market:banner:create']">新增
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="标题" align="center" prop="title"/>
 | 
			
		||||
 | 
			
		||||
      <el-table-column label="缩略图" align="center" prop="picUrl">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <img v-if="scope.row.picUrl" :src="scope.row.picUrl" alt="缩略图片" class="img-height"/>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="跳转链接" align="center" prop="url"/>
 | 
			
		||||
      <el-table-column label="排序" align="center" prop="sort"/>
 | 
			
		||||
      <el-table-column label="描述" align="center" prop="memo"/>
 | 
			
		||||
      <el-table-column label="状态" align="center" prop="status">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                     v-hasPermi="['market:banner:update']">修改
 | 
			
		||||
          </el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-hasPermi="['market:banner:delete']">删除
 | 
			
		||||
          </el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
 | 
			
		||||
        <el-form-item label="标题" prop="title">
 | 
			
		||||
          <el-input v-model="form.title" placeholder="请输入标题"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="缩略图" prop="picUrl">
 | 
			
		||||
          <imageUpload v-model="form.picUrl" :limit="1"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="跳转链接" prop="url">
 | 
			
		||||
          <el-input v-model="form.url" placeholder="请输入跳转链接"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="排序" prop="sort">
 | 
			
		||||
          <el-input v-model="form.sort" placeholder="请输入排序"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="描述" prop="memo">
 | 
			
		||||
          <el-input v-model="form.memo" type="textarea" placeholder="请输入描述"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="状态" prop="status">
 | 
			
		||||
          <el-radio-group v-model="form.status">
 | 
			
		||||
            <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
 | 
			
		||||
                      :key="dict.value" :label="parseInt(dict.value)">{{ dict.label }}
 | 
			
		||||
            </el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {
 | 
			
		||||
  createBanner,
 | 
			
		||||
  deleteBanner,
 | 
			
		||||
  getBanner,
 | 
			
		||||
  getBannerPage,
 | 
			
		||||
  updateBanner
 | 
			
		||||
} from "@/api/mall/market/banner";
 | 
			
		||||
import ImageUpload from '@/components/ImageUpload';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "Banner",
 | 
			
		||||
  components: {
 | 
			
		||||
    ImageUpload
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 导出遮罩层
 | 
			
		||||
      exportLoading: false,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 品牌列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        title: null,
 | 
			
		||||
        status: null,
 | 
			
		||||
        createTime: []
 | 
			
		||||
      },
 | 
			
		||||
      // 商品分类树选项
 | 
			
		||||
      categoryOptions: [],
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {},
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        title: [{required: true, message: "标题不能不空", trigger: "blur"}],
 | 
			
		||||
        picUrl: [{required: true, message: "图片地址不能为空", trigger: "blur"}],
 | 
			
		||||
        url: [{required: true, message: "跳转地址不能为空", trigger: "blur"}],
 | 
			
		||||
        sort: [{required: true, message: "排序不能为空", trigger: "blur"}],
 | 
			
		||||
        status: [{required: true, message: "状态不能为空", trigger: "change"}],
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getBannerPage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        title: undefined,
 | 
			
		||||
        link: undefined,
 | 
			
		||||
        imgUrl: undefined,
 | 
			
		||||
        sort: undefined,
 | 
			
		||||
        memo: undefined,
 | 
			
		||||
        status: undefined,
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.title = "添加Banner";
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      getBanner(id).then(response => {
 | 
			
		||||
        this.form = response.data;
 | 
			
		||||
        this.open = true;
 | 
			
		||||
        this.title = "修改Banner";
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 修改的提交
 | 
			
		||||
        if (this.form.id != null) {
 | 
			
		||||
          updateBanner(this.form).then(response => {
 | 
			
		||||
            this.$modal.msgSuccess("修改成功");
 | 
			
		||||
            this.open = false;
 | 
			
		||||
            this.getList();
 | 
			
		||||
          });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 添加的提交
 | 
			
		||||
        createBanner(this.form).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("新增成功");
 | 
			
		||||
          this.open = false;
 | 
			
		||||
          this.getList();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认删除Banner编号为"' + id + '"的数据项?').then(function () {
 | 
			
		||||
        return deleteBanner(id);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("删除成功");
 | 
			
		||||
      }).catch(() => {
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="scss">
 | 
			
		||||
//
 | 
			
		||||
.img-height {
 | 
			
		||||
  height: 150px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,247 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
 | 
			
		||||
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="品牌名称" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入品牌名称" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="状态" prop="status">
 | 
			
		||||
        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
 | 
			
		||||
                     :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['product:brand:create']">新增</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="品牌编号" align="center" prop="id"/>
 | 
			
		||||
      <el-table-column label="品牌名称" align="center" prop="name"/>
 | 
			
		||||
      <el-table-column label="品牌图片" align="center" prop="picUrl">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <img v-if="scope.row.picUrl" :src="scope.row.picUrl" alt="分类图片" style="height: 100px;" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="品牌排序" align="center" prop="sort"/>
 | 
			
		||||
      <el-table-column label="品牌描述" align="center" prop="description"/>
 | 
			
		||||
      <el-table-column label="状态" align="center" prop="status">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                     v-hasPermi="['product:brand:update']">修改
 | 
			
		||||
          </el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-hasPermi="['product:brand:delete']">删除
 | 
			
		||||
          </el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
 | 
			
		||||
        <el-form-item label="品牌名称" prop="name">
 | 
			
		||||
          <el-input v-model="form.name" placeholder="请输入品牌名称"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="品牌图片" prop="picUrl">
 | 
			
		||||
          <imageUpload v-model="form.picUrl" :limit="1"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="品牌排序" prop="sort">
 | 
			
		||||
          <el-input v-model="form.sort" placeholder="请输入品牌排序"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="品牌描述" prop="description">
 | 
			
		||||
          <el-input v-model="form.description" type="textarea" placeholder="请输入内容"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="状态" prop="status">
 | 
			
		||||
          <el-radio-group v-model="form.status">
 | 
			
		||||
            <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
 | 
			
		||||
                      :key="dict.value" :label="parseInt(dict.value)">{{ dict.label }}
 | 
			
		||||
            </el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {
 | 
			
		||||
  createBrand,
 | 
			
		||||
  deleteBrand,
 | 
			
		||||
  getBrand,
 | 
			
		||||
  getBrandPage,
 | 
			
		||||
  updateBrand
 | 
			
		||||
} from "@/api/mall/product/brand";
 | 
			
		||||
import ImageUpload from '@/components/ImageUpload';
 | 
			
		||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 | 
			
		||||
import {CommonStatusEnum} from "@/utils/constants";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "ProductBrand",
 | 
			
		||||
  components: {
 | 
			
		||||
    ImageUpload
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 导出遮罩层
 | 
			
		||||
      exportLoading: false,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 品牌列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        categoryId: null,
 | 
			
		||||
        name: null,
 | 
			
		||||
        status: null,
 | 
			
		||||
        createTime: []
 | 
			
		||||
      },
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {},
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        name: [{required: true, message: "品牌名称不能为空", trigger: "blur"}],
 | 
			
		||||
        picUrl: [{required: true, message: "品牌图片不能为空", trigger: "blur"}],
 | 
			
		||||
        sort: [{required: true, message: "品牌排序不能为空", trigger: "blur"}],
 | 
			
		||||
        status: [{required: true, message: "状态不能为空", trigger: "change"}],
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getBrandPage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        picUrl: undefined,
 | 
			
		||||
        sort: 0,
 | 
			
		||||
        description: undefined,
 | 
			
		||||
        status: CommonStatusEnum.ENABLE,
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.title = "添加品牌";
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      getBrand(id).then(response => {
 | 
			
		||||
        this.form = response.data;
 | 
			
		||||
        this.open = true;
 | 
			
		||||
        this.title = "修改品牌";
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 修改的提交
 | 
			
		||||
        if (this.form.id != null) {
 | 
			
		||||
          updateBrand(this.form).then(response => {
 | 
			
		||||
            this.$modal.msgSuccess("修改成功");
 | 
			
		||||
            this.open = false;
 | 
			
		||||
            this.getList();
 | 
			
		||||
          });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 添加的提交
 | 
			
		||||
        createBrand(this.form).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("新增成功");
 | 
			
		||||
          this.open = false;
 | 
			
		||||
          this.getList();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认删除品牌编号为"' + id + '"的数据项?').then(function () {
 | 
			
		||||
        return deleteBrand(id);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("删除成功");
 | 
			
		||||
      }).catch(() => {
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,270 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="分类名称" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入分类名称" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['product:category:create']">新增
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="info" plain icon="el-icon-sort" size="mini" @click="toggleExpandAll">展开/折叠</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-if="refreshTable" v-loading="loading" :data="list"  row-key="id" :default-expand-all="isExpandAll"
 | 
			
		||||
              :tree-props="{children: 'children', hasChildren: 'hasChildren'}">
 | 
			
		||||
      <el-table-column label="分类名称" prop="name"/>
 | 
			
		||||
      <el-table-column label="分类图片" align="center" prop="picUrl">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <img v-if="scope.row.picUrl" :src="scope.row.picUrl" alt="分类图片" style="height: 100px"/>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="分类排序" align="center" prop="sort"/>
 | 
			
		||||
      <el-table-column label="开启状态" align="center" prop="status">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                     v-hasPermi="['product:category:update']">修改
 | 
			
		||||
          </el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-hasPermi="['product:category:delete']">删除
 | 
			
		||||
          </el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
 | 
			
		||||
        <el-form-item label="上级分类" prop="parentId">
 | 
			
		||||
          <Treeselect v-model="form.parentId" :options="parentCategoryOptions" :normalizer="normalizer" :show-count="true"
 | 
			
		||||
                      :defaultExpandLevel="1" placeholder="上级分类"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="分类名称" prop="name">
 | 
			
		||||
          <el-input v-model="form.name" placeholder="请输入分类名称"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="分类图片" prop="picUrl">
 | 
			
		||||
          <ImageUpload v-model="form.picUrl" :limit="1" :is-show-tip="false" />
 | 
			
		||||
          <div v-if="form.parentId === 0" style="font-size: 10px">推荐 200x100 图片分辨率</div>
 | 
			
		||||
          <div v-else style="font-size: 10px">推荐 100x100 图片分辨率</div>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="分类排序" prop="sort">
 | 
			
		||||
          <el-input-number v-model="form.sort" controls-position="right" :min="0" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="开启状态" prop="status">
 | 
			
		||||
          <el-radio-group v-model="form.status">
 | 
			
		||||
            <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
 | 
			
		||||
                      :key="dict.value" :label="parseInt(dict.value)">{{ dict.label }}
 | 
			
		||||
            </el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="分类描述">
 | 
			
		||||
          <el-input v-model="form.description" type="textarea" placeholder="请输入分类描述" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {
 | 
			
		||||
  createProductCategory,
 | 
			
		||||
  deleteProductCategory,
 | 
			
		||||
  getProductCategory,
 | 
			
		||||
  getProductCategoryList,
 | 
			
		||||
  updateProductCategory
 | 
			
		||||
} from "@/api/mall/product/category";
 | 
			
		||||
import Editor from '@/components/Editor';
 | 
			
		||||
import Treeselect from "@riophae/vue-treeselect";
 | 
			
		||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 | 
			
		||||
import ImageUpload from '@/components/ImageUpload';
 | 
			
		||||
import {CommonStatusEnum} from "@/utils/constants";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "ProductCategory",
 | 
			
		||||
  components: {
 | 
			
		||||
    Editor, Treeselect, ImageUpload
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 商品分类列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 商品分类树选项
 | 
			
		||||
      parentCategoryOptions: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 是否展开,默认全部折叠
 | 
			
		||||
      isExpandAll: false,
 | 
			
		||||
      // 重新渲染表格状态
 | 
			
		||||
      refreshTable: true,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        name: null,
 | 
			
		||||
      },
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {},
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        parentId: [{required: true, message: "请选择上级分类", trigger: "blur"}],
 | 
			
		||||
        name: [{required: true, message: "分类名称不能为空", trigger: "blur"}],
 | 
			
		||||
        picUrl: [{required: true, message: "分类图片不能为空", trigger: "blur"}],
 | 
			
		||||
        sort: [{required: true, message: "分类排序不能为空", trigger: "blur"}],
 | 
			
		||||
        status: [{required: true, message: "开启状态不能为空", trigger: "blur"}],
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 处理查询参数
 | 
			
		||||
      let params = {...this.queryParams};
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getProductCategoryList(params).then(response => {
 | 
			
		||||
        this.list = this.handleTree(response.data, "id", "parentId");
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
        // 属性下拉框
 | 
			
		||||
        this.parentCategoryOptions = [];
 | 
			
		||||
        const menu = {id: 0, name: '顶级分类', children: []};
 | 
			
		||||
        menu.children = this.handleTree(response.data, "id", "parentId");
 | 
			
		||||
        this.parentCategoryOptions.push(menu);
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        parentId: undefined,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        pirUrl: undefined,
 | 
			
		||||
        sort: 0,
 | 
			
		||||
        description: undefined,
 | 
			
		||||
        status: CommonStatusEnum.ENABLE,
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 展开/折叠操作 */
 | 
			
		||||
    toggleExpandAll() {
 | 
			
		||||
      this.refreshTable = false;
 | 
			
		||||
      this.isExpandAll = !this.isExpandAll;
 | 
			
		||||
      this.$nextTick(() => {
 | 
			
		||||
        this.refreshTable = true;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 转换菜单数据结构 */
 | 
			
		||||
    normalizer(node) {
 | 
			
		||||
      if (node.children && !node.children.length) {
 | 
			
		||||
        delete node.children;
 | 
			
		||||
      }
 | 
			
		||||
      return {
 | 
			
		||||
        id: node.id,
 | 
			
		||||
        label: node.name,
 | 
			
		||||
        children: node.children
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.title = "添加商品分类";
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      getProductCategory(id).then(response => {
 | 
			
		||||
        this.form = response.data;
 | 
			
		||||
        this.open = true;
 | 
			
		||||
        this.title = "修改商品分类";
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 修改的提交
 | 
			
		||||
        if (this.form.id != null) {
 | 
			
		||||
          updateProductCategory(this.form).then(response => {
 | 
			
		||||
            this.$modal.msgSuccess("修改成功");
 | 
			
		||||
            this.open = false;
 | 
			
		||||
            this.getList();
 | 
			
		||||
          });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 添加的提交
 | 
			
		||||
        createProductCategory(this.form).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("新增成功");
 | 
			
		||||
          this.open = false;
 | 
			
		||||
          this.getList();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认删除商品分类编号为"' + id + '"的数据项?').then(function () {
 | 
			
		||||
        return deleteProductCategory(id);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("删除成功");
 | 
			
		||||
      }).catch(() => {
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,207 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="名称" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['product:property:create']">新增</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="编号" align="center" prop="id" />
 | 
			
		||||
      <el-table-column label="名称" align="center" :show-overflow-tooltip="true">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <router-link :to="'/property/value/' + scope.row.id" class="link-type">
 | 
			
		||||
            <span>{{ scope.row.name }}</span>
 | 
			
		||||
          </router-link>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="备注" align="center" prop="remark" />
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                     v-hasPermi="['product:property:update']">修改</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-hasPermi="['product:property:delete']">删除</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
 | 
			
		||||
        <el-form-item label="名称" prop="name">
 | 
			
		||||
          <el-input v-model="form.name" placeholder="请输入名称" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="备注" prop="remark">
 | 
			
		||||
          <el-input v-model="form.remark" placeholder="备注" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { createProperty, updateProperty, deleteProperty, getProperty, getPropertyPage } from "@/api/mall/product/property";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "ProductProperty",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 属性项列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        name: null,
 | 
			
		||||
        createTime: []
 | 
			
		||||
      },
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {
 | 
			
		||||
        name:'',
 | 
			
		||||
        remark:"",
 | 
			
		||||
        id: null,
 | 
			
		||||
      },
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        name: [
 | 
			
		||||
          { required: true, message: "名称不能为空", trigger: "blur" }
 | 
			
		||||
        ]
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getPropertyPage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        name:'',
 | 
			
		||||
        remark:"",
 | 
			
		||||
        id: null,
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.title = "添加属性项";
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      getProperty(id).then(response => {
 | 
			
		||||
        this.form = response.data;
 | 
			
		||||
        this.open = true;
 | 
			
		||||
        this.title = "修改属性项";
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 修改的提交
 | 
			
		||||
        if (this.form.id != null) {
 | 
			
		||||
          updateProperty(this.form).then(response => {
 | 
			
		||||
            this.$modal.msgSuccess("修改成功");
 | 
			
		||||
            this.open = false;
 | 
			
		||||
            this.getList();
 | 
			
		||||
          });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 添加的提交
 | 
			
		||||
        createProperty(this.form).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("新增成功");
 | 
			
		||||
          this.open = false;
 | 
			
		||||
          this.getList();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认删除名称为"' + row.name + '"的数据项?').then(function() {
 | 
			
		||||
          return deleteProperty(id);
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          this.getList();
 | 
			
		||||
          this.$modal.msgSuccess("删除成功");
 | 
			
		||||
        }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,240 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
 | 
			
		||||
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="属性项" prop="propertyId">
 | 
			
		||||
        <el-select v-model="queryParams.propertyId">
 | 
			
		||||
          <el-option v-for="item in propertyOptions" :key="item.id" :label="item.name" :value="item.id"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="名称" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['system:dict:create']">新增
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <el-table v-loading="loading" :data="dataList">
 | 
			
		||||
      <el-table-column label="编号" align="center" prop="id"/>
 | 
			
		||||
      <el-table-column label="名称" align="center" prop="name"/>
 | 
			
		||||
      <el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true"/>
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                     v-hasPermi="['system:dict:update']">修改
 | 
			
		||||
          </el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-hasPermi="['system:dict:delete']">删除
 | 
			
		||||
          </el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
 | 
			
		||||
    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 添加或修改参数配置对话框 -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="90px">
 | 
			
		||||
        <el-form-item label="属性项">
 | 
			
		||||
          <el-input v-model="form.propertyId" :disabled="true"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="名称" prop="name">
 | 
			
		||||
          <el-input v-model="form.name" placeholder="请输入名称"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="备注" prop="remark">
 | 
			
		||||
          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {
 | 
			
		||||
  createPropertyValue,
 | 
			
		||||
  deletePropertyValue,
 | 
			
		||||
  getProperty,
 | 
			
		||||
  getPropertyList,
 | 
			
		||||
  getPropertyValue,
 | 
			
		||||
  getPropertyValuePage,
 | 
			
		||||
  updatePropertyValue
 | 
			
		||||
} from '@/api/mall/product/property'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "ProductPropertyValue",
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 字典表格数据
 | 
			
		||||
      dataList: [],
 | 
			
		||||
      // 默认字典类型
 | 
			
		||||
      defaultPropertyId: "",
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 类型数据字典
 | 
			
		||||
      propertyOptions: [],
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        propertyId: undefined,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
      },
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {},
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        name: [
 | 
			
		||||
          {required: true, message: "名称不能为空", trigger: "blur"}
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    const propertyId = this.$route.params && this.$route.params.propertyId;
 | 
			
		||||
    this.getProperty(propertyId);
 | 
			
		||||
    this.getPropertyList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询字典类型详细 */
 | 
			
		||||
    getProperty(propertyId) {
 | 
			
		||||
      getProperty(propertyId).then(response => {
 | 
			
		||||
        this.queryParams.propertyId = response.data.id;
 | 
			
		||||
        this.defaultPropertyId = response.data.id;
 | 
			
		||||
        this.getList();
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 查询字典类型列表 */
 | 
			
		||||
    getPropertyList() {
 | 
			
		||||
      getPropertyList().then(response => {
 | 
			
		||||
        this.propertyOptions = response.data
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 查询字典数据列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      getPropertyValuePage(this.queryParams).then(response => {
 | 
			
		||||
        this.dataList = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    // 取消按钮
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    // 表单重置
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        propertyId: undefined,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        remark: undefined
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.queryParams.propertyId = this.defaultPropertyId;
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.title = "添加属性值";
 | 
			
		||||
      this.form.propertyId = this.queryParams.propertyId;
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      getPropertyValue(id).then(response => {
 | 
			
		||||
        this.form = response.data;
 | 
			
		||||
        this.open = true;
 | 
			
		||||
        this.title = "修改属性值";
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm: function () {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (valid) {
 | 
			
		||||
          if (this.form.id !== undefined) {
 | 
			
		||||
            updatePropertyValue(this.form).then(response => {
 | 
			
		||||
              this.$modal.msgSuccess("修改成功");
 | 
			
		||||
              this.open = false;
 | 
			
		||||
              this.getList();
 | 
			
		||||
            });
 | 
			
		||||
          } else {
 | 
			
		||||
            createPropertyValue(this.form).then(response => {
 | 
			
		||||
              this.$modal.msgSuccess("新增成功");
 | 
			
		||||
              this.open = false;
 | 
			
		||||
              this.getList();
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const ids = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认删除字典编码为"' + ids + '"的数据项?').then(function () {
 | 
			
		||||
        return deletePropertyValue(ids);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("删除成功");
 | 
			
		||||
      }).catch(() => {
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 导出按钮操作 */
 | 
			
		||||
    handleExport() {
 | 
			
		||||
      const queryParams = this.queryParams;
 | 
			
		||||
      this.$modal.confirm('是否确认导出所有数据项?').then(() => {
 | 
			
		||||
        this.exportLoading = true;
 | 
			
		||||
        return exportData(queryParams);
 | 
			
		||||
      }).then(response => {
 | 
			
		||||
        this.$download.excel(response, '字典数据.xls');
 | 
			
		||||
        this.exportLoading = false;
 | 
			
		||||
      }).catch(() => {
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,392 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
 | 
			
		||||
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="商品名称" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入商品名称" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="商品编码" prop="code">
 | 
			
		||||
        <el-input v-model="queryParams.code" placeholder="请输入商品编码" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="商品分类" prop="categoryIds">
 | 
			
		||||
        <el-cascader v-model="queryParams.categoryIds" placeholder="请输入商品分类"
 | 
			
		||||
                     :options="categoryList" :props="propName" clearable ref="category"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="商品品牌" prop="brandId">
 | 
			
		||||
        <el-select v-model="queryParams.brandId" placeholder="请输入商品品牌" clearable @keyup.enter.native="handleQuery">
 | 
			
		||||
          <el-option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <!-- TODO 待实现:商品类型 -->
 | 
			
		||||
      <!-- TODO 待实现:商品标签 -->
 | 
			
		||||
      <!-- TODO 待实现:营销活动 -->
 | 
			
		||||
      <!-- TODO 前端优化:商品销量、商品价格,排的整齐一点 -->
 | 
			
		||||
      <el-form-item label="商品销量">
 | 
			
		||||
        <el-col :span="7" style="padding-left:0">
 | 
			
		||||
          <el-form-item prop="salesCountMin">
 | 
			
		||||
            <el-input v-model="queryParams.salesCountMin" placeholder="最低销量" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </el-col>
 | 
			
		||||
        <el-col :span="1">-</el-col>
 | 
			
		||||
        <el-col :span="7" style="padding-left:0">
 | 
			
		||||
          <el-form-item prop="salesCountMax">
 | 
			
		||||
            <el-input v-model="queryParams.salesCountMax" placeholder="最高销量" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </el-col>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="商品价格" prop="code">
 | 
			
		||||
        <el-col :span="7" style="padding-left:0">
 | 
			
		||||
          <el-form-item prop="marketPriceMin">
 | 
			
		||||
            <el-input v-model="queryParams.marketPriceMin" placeholder="最低价格" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </el-col>
 | 
			
		||||
        <el-col :span="1">-</el-col>
 | 
			
		||||
        <el-col :span="7" style="padding-left:0">
 | 
			
		||||
          <el-form-item prop="marketPriceMax">
 | 
			
		||||
            <el-input v-model="queryParams.marketPriceMax" placeholder="最高价格" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </el-col>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['product:spu:create']">添加商品</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"/>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <el-tabs v-model="activeTabs" type="card" @tab-click="handleClick">
 | 
			
		||||
      <!-- 全部 -->
 | 
			
		||||
      <el-tab-pane label="全部" name="all">
 | 
			
		||||
        <!-- 列表 -->
 | 
			
		||||
        <el-table v-loading="loading" :data="list">
 | 
			
		||||
          <el-table-column label="商品信息" align="center" width="260">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <div class="product-info">
 | 
			
		||||
                <img v-if="scope.row.picUrls" :src="scope.row.picUrls[0]" alt="分类图片" class="img-height" />
 | 
			
		||||
                <div class="message">{{ scope.row.name }}</div>
 | 
			
		||||
              </div>
 | 
			
		||||
            </template>
 | 
			
		||||
            <!-- TODO 前端优化:可以有个 + 号,点击后,展示每个 sku -->
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="价格" align="center" prop="marketPrice" :formatter="formatPrice"/>
 | 
			
		||||
          <el-table-column label="库存" align="center" prop="totalStock"/>
 | 
			
		||||
          <el-table-column label="销量" align="center" prop="salesCount"/>
 | 
			
		||||
          <el-table-column label="排序" align="center" prop="sort"/>
 | 
			
		||||
          <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="状态" align="center" prop="status">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <dict-tag :type="DICT_TYPE.PRODUCT_SPU_STATUS" :value="scope.row.status"/>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                         v-hasPermi="['product:spu:update']">修改</el-button>
 | 
			
		||||
              <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                         v-hasPermi="['product:spu:delete']">删除</el-button>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table>
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
 | 
			
		||||
      <!-- 销售中 -->
 | 
			
		||||
      <el-tab-pane label="销售中" name="on">
 | 
			
		||||
        <!-- 列表 -->
 | 
			
		||||
        <el-table v-loading="loading" :data="list">
 | 
			
		||||
          <el-table-column label="商品信息" align="center" width="260">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <div class="product-info">
 | 
			
		||||
                <img v-if="scope.row.picUrls" :src="scope.row.picUrls[0]" alt="分类图片" class="img-height"/>
 | 
			
		||||
                <div class="message">{{ scope.row.name }}</div>
 | 
			
		||||
              </div>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="价格" align="center" prop="marketPrice" :formatter="formatPrice"/>
 | 
			
		||||
          <el-table-column label="库存" align="center" prop="totalStock"/>
 | 
			
		||||
          <el-table-column label="销量" align="center" prop="salesCount"/>
 | 
			
		||||
          <el-table-column label="排序" align="center" prop="sort"/>
 | 
			
		||||
          <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="状态" align="center" prop="status">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <dict-tag :type="DICT_TYPE.PRODUCT_SPU_STATUS" :value="scope.row.status"/>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                         v-hasPermi="['product:spu:update']">修改</el-button>
 | 
			
		||||
              <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                         v-hasPermi="['product:spu:delete']">删除</el-button>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table>
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
 | 
			
		||||
      <!-- 仓库中 -->
 | 
			
		||||
      <el-tab-pane label="仓库中" name="off">
 | 
			
		||||
        <!-- 列表 -->
 | 
			
		||||
        <el-table v-loading="loading" :data="list">
 | 
			
		||||
          <el-table-column label="商品信息" align="center" width="260">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <div class="product-info">
 | 
			
		||||
                <img v-if="scope.row.picUrls" :src="scope.row.picUrls[0]" alt="分类图片" class="img-height"/>
 | 
			
		||||
                <div class="message">{{ scope.row.name }}</div>
 | 
			
		||||
              </div>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="价格" align="center" prop="marketPrice" :formatter="formatPrice"/>
 | 
			
		||||
          <el-table-column label="库存" align="center" prop="totalStock"/>
 | 
			
		||||
          <el-table-column label="销量" align="center" prop="salesCount"/>
 | 
			
		||||
          <el-table-column label="排序" align="center" prop="sort"/>
 | 
			
		||||
          <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="状态" align="center" prop="status">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <dict-tag :type="DICT_TYPE.PRODUCT_SPU_STATUS" :value="scope.row.status"/>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                         v-hasPermi="['product:spu:update']">修改</el-button>
 | 
			
		||||
              <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                         v-hasPermi="['product:spu:delete']">删除</el-button>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table>
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
 | 
			
		||||
      <!-- 预警中 -->
 | 
			
		||||
      <el-tab-pane label="预警中" name="remind">
 | 
			
		||||
        <!-- 列表 -->
 | 
			
		||||
        <el-table v-loading="loading" :data="list">
 | 
			
		||||
          <el-table-column label="商品信息" align="center" width="260">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <div class="product-info">
 | 
			
		||||
                <img v-if="scope.row.picUrls" :src="scope.row.picUrls[0]" alt="分类图片" class="img-height"/>
 | 
			
		||||
                <div class="message">{{ scope.row.name }}</div>
 | 
			
		||||
              </div>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="价格" align="center" prop="marketPrice" :formatter="formatPrice"/>
 | 
			
		||||
          <el-table-column label="库存" align="center" prop="totalStock"/>
 | 
			
		||||
          <el-table-column label="销量" align="center" prop="salesCount"/>
 | 
			
		||||
          <el-table-column label="排序" align="center" prop="sort"/>
 | 
			
		||||
          <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="状态" align="center" prop="status">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <dict-tag :type="DICT_TYPE.PRODUCT_SPU_STATUS" :value="scope.row.status"/>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
            <template v-slot="scope">
 | 
			
		||||
              <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                         v-hasPermi="['product:spu:update']">修改</el-button>
 | 
			
		||||
              <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                         v-hasPermi="['product:spu:delete']">删除</el-button>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table>
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
    </el-tabs>
 | 
			
		||||
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {deleteSpu, getSpuPage,} from "@/api/mall/product/spu";
 | 
			
		||||
import {getProductCategoryList} from "@/api/mall/product/category";
 | 
			
		||||
import {getBrandList} from "@/api/mall/product/brand";
 | 
			
		||||
import {ProductSpuStatusEnum} from "@/utils/constants";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "ProductSpu",
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      activeTabs: "all",
 | 
			
		||||
      propName: {
 | 
			
		||||
        checkStrictly: true,
 | 
			
		||||
        label: "name",
 | 
			
		||||
        value: "id",
 | 
			
		||||
      },
 | 
			
		||||
      brandList: [],
 | 
			
		||||
      categoryList: [],
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 导出遮罩层
 | 
			
		||||
      exportLoading: false,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 商品spu列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      dateRangeCreateTime: [],
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        name: null,
 | 
			
		||||
        code: null,
 | 
			
		||||
        categoryIds: [],
 | 
			
		||||
        categoryId: null,
 | 
			
		||||
        brandId: null,
 | 
			
		||||
        status: null,
 | 
			
		||||
        salesCountMin: null,
 | 
			
		||||
        salesCountMax: null,
 | 
			
		||||
        marketPriceMin: null,
 | 
			
		||||
        marketPriceMax: null,
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
    this.getListCategory()
 | 
			
		||||
    this.getListBrand()
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询分类列表 */
 | 
			
		||||
    getListCategory() {
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getProductCategoryList().then((response) => {
 | 
			
		||||
        this.categoryList = this.handleTree(response.data, "id", "parentId");
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 查询品牌列表 */
 | 
			
		||||
    getListBrand() {
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getBrandList().then((response) => {
 | 
			
		||||
        this.brandList = response.data;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 处理查询参数
 | 
			
		||||
      let params = {...this.queryParams};
 | 
			
		||||
      params.marketPriceMin = this.queryParams.marketPriceMin === null ? null : params.marketPriceMin * 100;
 | 
			
		||||
      params.marketPriceMax = this.queryParams.marketPriceMax === null ? null : params.marketPriceMax * 100;
 | 
			
		||||
      params.categoryId = this.queryParams.categoryIds[this.queryParams.categoryIds.length - 1];
 | 
			
		||||
      this.addBeginAndEndTime(params, this.dateRangeCreateTime, "createTime");
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getSpuPage(params).then((response) => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.dateRangeCreateTime = [];
 | 
			
		||||
      this.$refs.category.$refs.panel.checkedValue = [];//也可以是指定的值,默认返回值是数组,也可以返回单个值
 | 
			
		||||
      this.$refs.category.$refs.panel.activePath = [];
 | 
			
		||||
      this.$refs.category.$refs.panel.syncActivePath();
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.$router.push({ name: 'ProductSpuCreate'})
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.$router.push({ name: 'ProductSpuUpdate', params: { spuId: row.id }})
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal
 | 
			
		||||
        .confirm('是否确认删除商品spu编号为"' + id + '"的数据项?')
 | 
			
		||||
        .then(function () {
 | 
			
		||||
          return deleteSpu(id);
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          this.getList();
 | 
			
		||||
          this.$modal.msgSuccess("删除成功");
 | 
			
		||||
        }).catch(() => {
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
    formatPrice(row, column, cellValue) {
 | 
			
		||||
      return '¥' + this.divide(cellValue, 100);
 | 
			
		||||
    },
 | 
			
		||||
    // 选中 tab
 | 
			
		||||
    handleClick(val) {
 | 
			
		||||
      if (val.name === "all") {
 | 
			
		||||
        this.queryParams.status = undefined;
 | 
			
		||||
        this.queryParams.alarmStock = undefined;
 | 
			
		||||
      } else if (val.name === "on") {
 | 
			
		||||
        this.queryParams.status = ProductSpuStatusEnum.ENABLE.status;
 | 
			
		||||
        this.queryParams.alarmStock = undefined;
 | 
			
		||||
      } else if (val.name === "off") {
 | 
			
		||||
        this.queryParams.status = ProductSpuStatusEnum.DISABLE.status;
 | 
			
		||||
        this.queryParams.alarmStock = undefined;
 | 
			
		||||
      } else if (val.name === "remind") {
 | 
			
		||||
        this.queryParams.status = undefined;
 | 
			
		||||
        this.queryParams.alarmStock = true;
 | 
			
		||||
      }
 | 
			
		||||
      this.getList();
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
.app-container {
 | 
			
		||||
  .el-tag + .el-tag {
 | 
			
		||||
    margin-left: 10px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .product-info {
 | 
			
		||||
    display: flex;
 | 
			
		||||
 | 
			
		||||
    .img-height {
 | 
			
		||||
      height: 50px;
 | 
			
		||||
      width: 50px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .message {
 | 
			
		||||
      margin-left: 10px;
 | 
			
		||||
      text-overflow: ellipsis;
 | 
			
		||||
      display: -webkit-box;
 | 
			
		||||
      -webkit-line-clamp: 2;
 | 
			
		||||
      word-break: break-all;
 | 
			
		||||
      -webkit-box-orient: vertical;
 | 
			
		||||
      white-space: normal;
 | 
			
		||||
      overflow: hidden;
 | 
			
		||||
      height: 50px;
 | 
			
		||||
      line-height: 25px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,580 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="container">
 | 
			
		||||
    <!-- TODO 样式优化:表单宽度、表单项对齐、hr 粗细; -->
 | 
			
		||||
    <el-tabs v-model="activeName" class="tabs">
 | 
			
		||||
      <!-- 基础设置 -->
 | 
			
		||||
      <!-- TODO @luowenfeng:基础设置,分成基础信息、配送信息 -->
 | 
			
		||||
      <el-tab-pane label="基础设置" name="basic">
 | 
			
		||||
        <el-form ref="basic" :model="baseForm" :rules="rules" label-width="100px" style="width: 95%">
 | 
			
		||||
          <el-form-item label="商品名称" prop="name">
 | 
			
		||||
            <el-input v-model="baseForm.name" placeholder="请输入商品名称" />
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label="促销语">
 | 
			
		||||
            <el-input type="textarea" v-model="baseForm.sellPoint" placeholder="请输入促销语"/>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label="商品主图" prop="picUrls">
 | 
			
		||||
            <ImageUpload v-model="baseForm.picUrls" :value="baseForm.picUrls" :limit="10" class="mall-image"/>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label="商品视频" prop="videoUrl">
 | 
			
		||||
            <VideoUpload v-model="baseForm.videoUrl" :value="baseForm.videoUrl"/>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label="商品品牌" prop="brandId">
 | 
			
		||||
            <el-select v-model="baseForm.brandId" placeholder="请选择商品品牌">
 | 
			
		||||
              <el-option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id"/>
 | 
			
		||||
            </el-select>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label="商品分类" prop="categoryIds">
 | 
			
		||||
            <el-cascader v-model="baseForm.categoryIds" placeholder="商品分类" style="width: 100%"
 | 
			
		||||
                         :options="categoryList" :props="propName" clearable/>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label="是否上架" prop="status">
 | 
			
		||||
            <el-radio-group v-model="baseForm.status">
 | 
			
		||||
              <el-radio :label="1">立即上架</el-radio>
 | 
			
		||||
              <el-radio :label="0">放入仓库</el-radio>
 | 
			
		||||
            </el-radio-group>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </el-form>
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
 | 
			
		||||
      <!-- 价格库存 -->
 | 
			
		||||
      <!-- TODO @luowenfeng:rates=》priceStack 会更好哈 -->
 | 
			
		||||
      <el-tab-pane label="价格库存" name="rates" class="rates">
 | 
			
		||||
        <el-form ref="rates" :model="ratesForm" :rules="rules">
 | 
			
		||||
          <el-form-item label="启用多规格">
 | 
			
		||||
            <el-switch v-model="specSwitch" @change="changeSpecSwitch"/>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <!-- 动态添加规格属性 -->
 | 
			
		||||
          <div v-show="ratesForm.spec === 2">
 | 
			
		||||
            <div v-for="(specs, index) in dynamicSpec" :key="index" class="dynamic-spec">
 | 
			
		||||
              <!-- 删除按钮 -->
 | 
			
		||||
              <el-button type="danger" icon="el-icon-delete" circle class="spec-delete" @click="removeSpec(index)"/>
 | 
			
		||||
              <div class="spec-header">
 | 
			
		||||
                规格项:
 | 
			
		||||
                <el-select v-model="specs.specId" filterable placeholder="请选择" @change="changeSpec">
 | 
			
		||||
                  <el-option v-for="item in propertyPageList" :key="item.id" :label="item.name" :value="item.id"/>
 | 
			
		||||
                </el-select>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div class="spec-values">
 | 
			
		||||
                <template v-for="(v, i) in specs.specValue">
 | 
			
		||||
                  <el-input v-model="v.name" class="spec-value" :key="i" disabled/>
 | 
			
		||||
                </template>
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <el-button type="primary" @click="dynamicSpec.push({specValue: []}); ratesForm.rates = []">添加规格项目</el-button>
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
          <!-- 规格明细 -->
 | 
			
		||||
          <el-form-item label="规格明细">
 | 
			
		||||
            <el-table :data="ratesForm.rates" border style="width: 100%" ref="ratesTable">
 | 
			
		||||
              <template v-if="this.specSwitch">
 | 
			
		||||
                <el-table-column :key="index" v-for="(item, index) in dynamicSpec.filter(v => v.specName !== undefined)"
 | 
			
		||||
                                 :label="item.specName">
 | 
			
		||||
                  <template v-slot="scope">
 | 
			
		||||
                    <el-input v-if="scope.row.spec" v-model="scope.row.spec[index]" disabled/>
 | 
			
		||||
                  </template>
 | 
			
		||||
                </el-table-column>
 | 
			
		||||
              </template>
 | 
			
		||||
              <el-table-column label="规格图片" width="120px" :render-header="addRedStar" key="90">
 | 
			
		||||
                <template v-slot="scope">
 | 
			
		||||
                  <ImageUpload v-model="scope.row.picUrl" :limit="1" :isShowTip="false" style="width: 100px; height: 50px"/>
 | 
			
		||||
                </template>
 | 
			
		||||
              </el-table-column>
 | 
			
		||||
              <el-table-column label="市场价(元)" :render-header="addRedStar" key="92">
 | 
			
		||||
                <template v-slot="scope">
 | 
			
		||||
                  <el-form-item :prop="'rates.'+ scope.$index + '.marketPrice'" :rules="[{required: true, trigger: 'change'}]">
 | 
			
		||||
                    <el-input v-model="scope.row.marketPrice"
 | 
			
		||||
                              oninput="value= value.match(/\d+(\.\d{0,2})?/) ? value.match(/\d+(\.\d{0,2})?/)[0] : ''"/>
 | 
			
		||||
                  </el-form-item>
 | 
			
		||||
                </template>
 | 
			
		||||
              </el-table-column>
 | 
			
		||||
              <el-table-column label="销售价(元)" :render-header="addRedStar" key="93">
 | 
			
		||||
                <template v-slot="scope">
 | 
			
		||||
                  <el-form-item :prop="'rates.'+ scope.$index + '.price'"
 | 
			
		||||
                                :rules="[{required: true, trigger: 'change'}]">
 | 
			
		||||
                    <el-input v-model="scope.row.price"
 | 
			
		||||
                              oninput="value= value.match(/\d+(\.\d{0,2})?/) ? value.match(/\d+(\.\d{0,2})?/)[0] : ''" />
 | 
			
		||||
                  </el-form-item>
 | 
			
		||||
                </template>
 | 
			
		||||
              </el-table-column>
 | 
			
		||||
              <el-table-column label="成本价" :render-header="addRedStar" key="94">
 | 
			
		||||
                <template v-slot="scope">
 | 
			
		||||
                  <el-form-item :prop="'rates.'+ scope.$index + '.costPrice'"
 | 
			
		||||
                                :rules="[{required: true, trigger: 'change'}]">
 | 
			
		||||
                    <el-input v-model="scope.row.costPrice"
 | 
			
		||||
                              oninput="value= value.match(/\d+(\.\d{0,2})?/) ? value.match(/\d+(\.\d{0,2})?/)[0] : ''" />
 | 
			
		||||
                  </el-form-item>
 | 
			
		||||
                </template>
 | 
			
		||||
              </el-table-column>
 | 
			
		||||
              <el-table-column label="库存" :render-header="addRedStar" key="95">
 | 
			
		||||
                <template v-slot="scope">
 | 
			
		||||
                  <el-form-item :prop="'rates.'+ scope.$index + '.stock'" :rules="[{required: true, trigger: 'change'}]">
 | 
			
		||||
                    <el-input v-model="scope.row.stock" oninput="value=value.replace(/^(0+)|[^\d]+/g,'')"></el-input>
 | 
			
		||||
                  </el-form-item>
 | 
			
		||||
                </template>
 | 
			
		||||
              </el-table-column>
 | 
			
		||||
              <el-table-column label="预警库存" key="96">
 | 
			
		||||
                <template v-slot="scope">
 | 
			
		||||
                  <el-input v-model="scope.row.warnStock" oninput="value=value.replace(/^(0+)|[^\d]+/g,'')"></el-input>
 | 
			
		||||
                </template>
 | 
			
		||||
              </el-table-column>
 | 
			
		||||
              <el-table-column label="体积" key="97">
 | 
			
		||||
                <template v-slot="scope">
 | 
			
		||||
                  <el-input v-model="scope.row.volume" />
 | 
			
		||||
                </template>
 | 
			
		||||
              </el-table-column>
 | 
			
		||||
              <el-table-column label="重量" key="98">
 | 
			
		||||
                <template v-slot="scope">
 | 
			
		||||
                  <el-input v-model="scope.row.weight" />
 | 
			
		||||
                </template>
 | 
			
		||||
              </el-table-column>
 | 
			
		||||
              <el-table-column label="条码" key="99">
 | 
			
		||||
                <template v-slot="scope">
 | 
			
		||||
                  <el-input v-model="scope.row.barCode" />
 | 
			
		||||
                </template>
 | 
			
		||||
              </el-table-column>
 | 
			
		||||
              <template v-if="this.specSwitch">
 | 
			
		||||
                <el-table-column fixed="right" label="操作" width="50" key="100">
 | 
			
		||||
                  <template v-slot="scope">
 | 
			
		||||
                    <el-button @click="scope.row.status = 1" type="text" size="small"
 | 
			
		||||
                               v-show="scope.row.status === undefined || scope.row.status === 0 ">禁用
 | 
			
		||||
                    </el-button>
 | 
			
		||||
                    <el-button @click="scope.row.status = 0" type="text" size="small" v-show="scope.row.status === 1">
 | 
			
		||||
                      启用
 | 
			
		||||
                    </el-button>
 | 
			
		||||
                  </template>
 | 
			
		||||
                </el-table-column>
 | 
			
		||||
              </template>
 | 
			
		||||
            </el-table>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label="虚拟销量" prop="virtualSalesCount">
 | 
			
		||||
            <el-input v-model="baseForm.virtualSalesCount" placeholder="请输入虚拟销量"
 | 
			
		||||
                      oninput="value=value.replace(/^(0+)|[^\d]+/g,'')"/>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </el-form>
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
 | 
			
		||||
      <!-- 商品详情 -->
 | 
			
		||||
      <el-tab-pane label="商品详情" name="detail">
 | 
			
		||||
        <el-form ref="detail" :model="baseForm" :rules="rules">
 | 
			
		||||
          <el-form-item prop="description">
 | 
			
		||||
            <editor v-model="baseForm.description" :min-height="380"/>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </el-form>
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
 | 
			
		||||
      <!-- 销售设置 -->
 | 
			
		||||
      <el-tab-pane label="高级设置" name="senior">
 | 
			
		||||
        <el-form ref="senior" :model="baseForm" :rules="rules" label-width="100px" style="width: 95%">
 | 
			
		||||
          <el-form-item label="排序字段">
 | 
			
		||||
            <el-input v-model="baseForm.sort" placeholder="请输入排序字段" oninput="value=value.replace(/^(0+)|[^\d]+/g,'')"/>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label="是否展示库存" prop="showStock">
 | 
			
		||||
            <el-radio-group v-model="baseForm.showStock">
 | 
			
		||||
              <el-radio :label="true">是</el-radio>
 | 
			
		||||
              <el-radio :label="false">否</el-radio>
 | 
			
		||||
            </el-radio-group>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </el-form>
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
    </el-tabs>
 | 
			
		||||
 | 
			
		||||
    <div class="buttons">
 | 
			
		||||
      <el-button type="info" round @click="cancel">取消</el-button>
 | 
			
		||||
      <el-button type="success" round @click="submit">确认</el-button>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {getBrandList} from "@/api/mall/product/brand";
 | 
			
		||||
import {getProductCategoryList} from "@/api/mall/product/category";
 | 
			
		||||
import {createSpu, getSpuDetail, updateSpu} from "@/api/mall/product/spu";
 | 
			
		||||
import {getPropertyListAndValue,} from "@/api/mall/product/property";
 | 
			
		||||
import Editor from "@/components/Editor";
 | 
			
		||||
import ImageUpload from "@/components/ImageUpload";
 | 
			
		||||
import VideoUpload from "@/components/VideoUpload";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "ProductSave",
 | 
			
		||||
  components: {
 | 
			
		||||
    Editor,
 | 
			
		||||
    ImageUpload,
 | 
			
		||||
    VideoUpload
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      specSwitch: false,
 | 
			
		||||
      activeName: "basic",
 | 
			
		||||
      propName: {
 | 
			
		||||
        checkStrictly: true,
 | 
			
		||||
        label: "name",
 | 
			
		||||
        value: "id",
 | 
			
		||||
      },
 | 
			
		||||
      // 基础设置
 | 
			
		||||
      baseForm: {
 | 
			
		||||
        id: null,
 | 
			
		||||
        name: null,
 | 
			
		||||
        sellPoint: null,
 | 
			
		||||
        categoryIds: null,
 | 
			
		||||
        sort: null,
 | 
			
		||||
        description: null,
 | 
			
		||||
        picUrls: null,
 | 
			
		||||
        videoUrl: null,
 | 
			
		||||
        status: 0,
 | 
			
		||||
        virtualSalesCount: 0,
 | 
			
		||||
        showStock: true,
 | 
			
		||||
        brandId: null,
 | 
			
		||||
      },
 | 
			
		||||
 | 
			
		||||
      categoryList: [],
 | 
			
		||||
      // 价格库存
 | 
			
		||||
      ratesForm: {
 | 
			
		||||
        spec: 1,
 | 
			
		||||
        // 规格明细
 | 
			
		||||
        rates: [{}]
 | 
			
		||||
      },
 | 
			
		||||
      dynamicSpec: [
 | 
			
		||||
        // {
 | 
			
		||||
        //   specId: 86,
 | 
			
		||||
        //   specName: "颜色",
 | 
			
		||||
        //   specValue:[{
 | 
			
		||||
        //      name: "红色",
 | 
			
		||||
        //      id: 225,
 | 
			
		||||
        //   }]
 | 
			
		||||
        // },
 | 
			
		||||
      ],
 | 
			
		||||
      propertyPageList: [],
 | 
			
		||||
      brandList: [],
 | 
			
		||||
      specValue: null,
 | 
			
		||||
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        name: [{required: true, message: "商品名称不能为空", trigger: "blur"},],
 | 
			
		||||
        description: [{required: true, message: "描述不能为空", trigger: "blur"},],
 | 
			
		||||
        categoryIds: [{required: true, message: "分类id不能为空", trigger: "blur"},],
 | 
			
		||||
        status: [{required: true, message: "商品状态不能为空", trigger: "blur"}],
 | 
			
		||||
        brandId: [{required: true, message: "商品品牌不能为空", trigger: "blur"}],
 | 
			
		||||
        picUrls: [{required: true, message: "商品轮播图地址不能为空", trigger: "blur"}],
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getListBrand();
 | 
			
		||||
    this.getListCategory();
 | 
			
		||||
    this.getPropertyPageList();
 | 
			
		||||
    const spuId = this.$route.params && this.$route.params.spuId;
 | 
			
		||||
    if (spuId != null) {
 | 
			
		||||
      this.updateType(spuId)
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    removeSpec(index) {
 | 
			
		||||
      this.dynamicSpec.splice(index, 1);
 | 
			
		||||
      this.changeSpecSwitch()
 | 
			
		||||
    },
 | 
			
		||||
    // 必选标识
 | 
			
		||||
    addRedStar(h, {column}) {
 | 
			
		||||
      return [
 | 
			
		||||
        h('span', {style: 'color: #F56C6C'}, '*'),
 | 
			
		||||
        h('span', ' ' + column.label)
 | 
			
		||||
      ];
 | 
			
		||||
    },
 | 
			
		||||
    changeSpecSwitch() {
 | 
			
		||||
      this.specSwitch ? this.ratesForm.spec = 2 : this.ratesForm.spec = 1;
 | 
			
		||||
      this.$refs.ratesTable.doLayout();
 | 
			
		||||
      if (this.ratesForm.spec === 1) {
 | 
			
		||||
        this.ratesForm.rates = [{}]
 | 
			
		||||
      } else {
 | 
			
		||||
        this.ratesForm.rates = []
 | 
			
		||||
        if (this.dynamicSpec.length > 0) {
 | 
			
		||||
          this.buildRatesFormRates()
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    // 构建规格明细笛卡尔积
 | 
			
		||||
    buildRatesFormRates() {
 | 
			
		||||
      let rates = [];
 | 
			
		||||
      this.dynamicSpec.map(v => v.specValue.map(m => m.name))
 | 
			
		||||
        .reduce((last, current) => {
 | 
			
		||||
          const array = [];
 | 
			
		||||
          last.forEach(par1 => {
 | 
			
		||||
            current.forEach(par2 => {
 | 
			
		||||
              let v
 | 
			
		||||
              // 当两个对象合并时,需使用[1,2]方式生成数组,而当数组和对象合并时,需使用concat
 | 
			
		||||
              if (par1 instanceof Array) {
 | 
			
		||||
                v = par1.concat(par2)
 | 
			
		||||
              } else {
 | 
			
		||||
                v = [par1, par2];
 | 
			
		||||
              }
 | 
			
		||||
              array.push(v)
 | 
			
		||||
            });
 | 
			
		||||
          });
 | 
			
		||||
          return array;
 | 
			
		||||
        })
 | 
			
		||||
        .forEach(v => {
 | 
			
		||||
          let spec = v;
 | 
			
		||||
          // 当v为单个规格项时,会变成字符串。造成表格只截取第一个字符串,而不是数组的第一个元素
 | 
			
		||||
          if (typeof v == 'string') {
 | 
			
		||||
            spec = Array.of(v)
 | 
			
		||||
          }
 | 
			
		||||
          rates.push({spec: spec, status: 0, name: Array.of(v).join()})
 | 
			
		||||
        });
 | 
			
		||||
      this.ratesForm.rates = rates
 | 
			
		||||
    },
 | 
			
		||||
    /** 查询分类 */
 | 
			
		||||
    getListCategory() {
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getProductCategoryList().then((response) => {
 | 
			
		||||
        this.categoryList = this.handleTree(response.data, "id", "parentId");
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 查询品牌列表 */
 | 
			
		||||
    getListBrand() {
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getBrandList().then((response) => {
 | 
			
		||||
        this.brandList = response.data;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    // 取消按钮
 | 
			
		||||
    cancel() {
 | 
			
		||||
      var currentView = this.$store.state.tagsView.visitedViews[0]
 | 
			
		||||
      for (currentView of this.$store.state.tagsView.visitedViews) {
 | 
			
		||||
        if (currentView.path === this.$route.path) {
 | 
			
		||||
          break
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      this.$store.dispatch('tagsView/delView', currentView)
 | 
			
		||||
        .then(() => {
 | 
			
		||||
          this.$router.push("/product/spu")
 | 
			
		||||
        })
 | 
			
		||||
    },
 | 
			
		||||
    submit() {
 | 
			
		||||
      this.$refs[this.activeName].validate((valid) => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        let rates = JSON.parse(JSON.stringify(this.ratesForm.rates));
 | 
			
		||||
 | 
			
		||||
        // 价格元转分
 | 
			
		||||
        rates.forEach(r => {
 | 
			
		||||
          r.marketPrice = r.marketPrice * 100;
 | 
			
		||||
          r.price = r.price * 100;
 | 
			
		||||
          r.costPrice = r.costPrice * 100;
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        // 动态规格调整字段
 | 
			
		||||
        if (this.specSwitch) {
 | 
			
		||||
          rates.forEach(r => {
 | 
			
		||||
            let properties = []
 | 
			
		||||
            Array.of(r.spec).forEach(s => {
 | 
			
		||||
              let obj;
 | 
			
		||||
              if (s instanceof Array) {
 | 
			
		||||
                obj = s;
 | 
			
		||||
              } else {
 | 
			
		||||
                obj = Array.of(s);
 | 
			
		||||
              }
 | 
			
		||||
              obj.forEach((v, i) => {
 | 
			
		||||
                let specValue = this.dynamicSpec[i].specValue.find(o => o.name === v);
 | 
			
		||||
                let propertie = {};
 | 
			
		||||
                propertie.propertyId = this.dynamicSpec[i].specId;
 | 
			
		||||
                propertie.valueId = specValue.id;
 | 
			
		||||
                properties.push(propertie);
 | 
			
		||||
              })
 | 
			
		||||
            })
 | 
			
		||||
            r.properties = properties;
 | 
			
		||||
          })
 | 
			
		||||
        } else {
 | 
			
		||||
          rates[0].name = this.baseForm.name;
 | 
			
		||||
          rates[0].status = this.baseForm.status;
 | 
			
		||||
        }
 | 
			
		||||
        let form = this.baseForm
 | 
			
		||||
        if (form.picUrls instanceof Array) {
 | 
			
		||||
          form.picUrls = form.picUrls.flatMap(m => m.split(','))
 | 
			
		||||
        } else if (form.picUrls.split(',') instanceof Array) {
 | 
			
		||||
          form.picUrls = form.picUrls.split(',').flatMap(m => m.split(','))
 | 
			
		||||
        } else {
 | 
			
		||||
          form.picUrls = Array.of(form.picUrls)
 | 
			
		||||
        }
 | 
			
		||||
        form.skus = rates;
 | 
			
		||||
        form.specType = this.ratesForm.spec;
 | 
			
		||||
 | 
			
		||||
        let category = form.categoryIds instanceof Array ? form.categoryIds: Array.of(form.categoryIds)
 | 
			
		||||
        console.log(category)
 | 
			
		||||
        form.categoryId = category[category.length - 1];
 | 
			
		||||
 | 
			
		||||
        if (form.id == null) {
 | 
			
		||||
          createSpu(form).then(() => {
 | 
			
		||||
            this.$modal.msgSuccess("新增成功");
 | 
			
		||||
          }).then(()=>{
 | 
			
		||||
            this.cancel();
 | 
			
		||||
          })
 | 
			
		||||
        } else {
 | 
			
		||||
          updateSpu(form).then(() => {
 | 
			
		||||
            this.$modal.msgSuccess("修改成功");
 | 
			
		||||
          }).then(()=>{
 | 
			
		||||
            this.cancel();
 | 
			
		||||
          })
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
    /** 查询规格 */
 | 
			
		||||
    getPropertyPageList() {
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getPropertyListAndValue().then((response) => {
 | 
			
		||||
        this.propertyPageList = response.data;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    // 添加规格项目
 | 
			
		||||
    changeSpec(val) {
 | 
			
		||||
      let obj = this.propertyPageList.find(o => o.id === val);
 | 
			
		||||
      let spec = this.dynamicSpec.find(o => o.specId === val)
 | 
			
		||||
      spec.specId = obj.id;
 | 
			
		||||
      spec.specName = obj.name;
 | 
			
		||||
      spec.specValue = obj.values;
 | 
			
		||||
      this.buildRatesFormRates();
 | 
			
		||||
    },
 | 
			
		||||
    updateType(id) {
 | 
			
		||||
      getSpuDetail(id).then((response) => {
 | 
			
		||||
        let data = response.data;
 | 
			
		||||
        this.baseForm.id = data.id;
 | 
			
		||||
        this.baseForm.name = data.name;
 | 
			
		||||
        this.baseForm.sellPoint = data.sellPoint;
 | 
			
		||||
        this.baseForm.categoryIds = data.categoryId;
 | 
			
		||||
        this.baseForm.videoUrl = data.videoUrl;
 | 
			
		||||
        this.baseForm.sort = data.sort;
 | 
			
		||||
        this.baseForm.description = data.description;
 | 
			
		||||
        this.baseForm.picUrls = data.picUrls;
 | 
			
		||||
        this.baseForm.status = data.status;
 | 
			
		||||
        this.baseForm.virtualSalesCount = data.virtualSalesCount;
 | 
			
		||||
        this.baseForm.showStock = data.showStock;
 | 
			
		||||
        this.baseForm.brandId = data.brandId;
 | 
			
		||||
        this.ratesForm.spec = data.specType;
 | 
			
		||||
        data.skus.forEach(r => {
 | 
			
		||||
          r.marketPrice = this.divide(r.marketPrice, 100)
 | 
			
		||||
          r.price = this.divide(r.price, 100)
 | 
			
		||||
          r.costPrice = this.divide(r.costPrice, 100)
 | 
			
		||||
        })
 | 
			
		||||
        if (this.ratesForm.spec === 2) {
 | 
			
		||||
          this.specSwitch = true;
 | 
			
		||||
          data.productPropertyViews.forEach(p => {
 | 
			
		||||
            let obj = {};
 | 
			
		||||
            obj.specId = p.propertyId;
 | 
			
		||||
            obj.specName = p.name;
 | 
			
		||||
            obj.specValue = p.propertyValues;
 | 
			
		||||
            this.dynamicSpec.push(obj);
 | 
			
		||||
          })
 | 
			
		||||
          data.skus.forEach(s => {
 | 
			
		||||
            s.spec = [];
 | 
			
		||||
            s.properties.forEach(sp => {
 | 
			
		||||
              let spec = data.productPropertyViews.find(o => o.propertyId === sp.propertyId).propertyValues.find(v => v.id === sp.valueId).name;
 | 
			
		||||
              s.spec.push(spec)
 | 
			
		||||
            })
 | 
			
		||||
          })
 | 
			
		||||
        }
 | 
			
		||||
        this.ratesForm.rates = data.skus
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss">
 | 
			
		||||
.container{
 | 
			
		||||
  padding: 20px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dynamic-spec {
 | 
			
		||||
  background-color: #f2f2f2;
 | 
			
		||||
  width: 85%;
 | 
			
		||||
  margin: auto;
 | 
			
		||||
  margin-bottom: 10px;
 | 
			
		||||
 | 
			
		||||
  .spec-header {
 | 
			
		||||
    padding: 30px;
 | 
			
		||||
    padding-bottom: 20px;
 | 
			
		||||
 | 
			
		||||
    .spec-name {
 | 
			
		||||
      display: inline;
 | 
			
		||||
 | 
			
		||||
      input {
 | 
			
		||||
        width: 30%;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .spec-values {
 | 
			
		||||
    width: 84%;
 | 
			
		||||
    padding: 25px;
 | 
			
		||||
    margin: auto;
 | 
			
		||||
    padding-top: 5px;
 | 
			
		||||
 | 
			
		||||
    .spec-value {
 | 
			
		||||
      display: inline-block;
 | 
			
		||||
      margin-right: 10px;
 | 
			
		||||
      margin-bottom: 10px;
 | 
			
		||||
      width: 13%;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .spec-delete {
 | 
			
		||||
    float: right;
 | 
			
		||||
    margin-top: 10px;
 | 
			
		||||
    margin-right: 10px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.tabs {
 | 
			
		||||
  border-bottom: 2px solid #f2f2f2;
 | 
			
		||||
 | 
			
		||||
  .el-tab-pane {
 | 
			
		||||
    overflow-y: auto;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 库存价格图片样式修改
 | 
			
		||||
.rates {
 | 
			
		||||
  .component-upload-image {
 | 
			
		||||
    margin: auto;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .el-upload--picture-card {
 | 
			
		||||
    width: 100px;
 | 
			
		||||
    height: 50px;
 | 
			
		||||
    line-height: 60px;
 | 
			
		||||
    margin: auto;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .el-upload-list__item {
 | 
			
		||||
    width: 100px !important;
 | 
			
		||||
    height: 50px !important;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.buttons {
 | 
			
		||||
  margin-top: 20px;
 | 
			
		||||
  height: 36px;
 | 
			
		||||
 | 
			
		||||
  button {
 | 
			
		||||
    float: right;
 | 
			
		||||
    margin-left: 15px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.mall-image {
 | 
			
		||||
  .el-upload--picture-card {
 | 
			
		||||
    width: 80px;
 | 
			
		||||
    height: 80px;
 | 
			
		||||
    line-height: 90px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .el-upload-list__item {
 | 
			
		||||
    width: 80px;
 | 
			
		||||
    height: 80px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,164 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="会员昵称" prop="nickname">
 | 
			
		||||
        <el-input v-model="queryParams.nickname" placeholder="请输入会员昵称" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- Tab 选项:真正的内容在 Lab -->
 | 
			
		||||
    <el-tabs v-model="activeTab" type="card" @tab-click="tabClick" style="margin-top: -40px;">
 | 
			
		||||
      <el-tab-pane v-for="tab in statusTabs" :key="tab.value" :label="tab.label" :name="tab.value" />
 | 
			
		||||
    </el-tabs>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="会员信息" align="center" prop="nickname" /> <!-- TODO 芋艿:以后支持头像,支持跳转 -->
 | 
			
		||||
      <el-table-column label="优惠劵" align="center" prop="name" />
 | 
			
		||||
      <el-table-column label="优惠券类型" align="center" prop="discountType">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.PROMOTION_DISCOUNT_TYPE" :value="scope.row.discountType" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="领取方式" align="center" prop="takeType">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.PROMOTION_COUPON_TAKE_TYPE" :value="scope.row.takeType" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="状态" align="center" prop="status">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.PROMOTION_COUPON_STATUS" :value="scope.row.status" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="领取时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="使用时间" align="center" prop="useTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.useTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-hasPermi="['promotion:coupon:delete']">回收</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { deleteCoupon, getCouponPage } from "@/api/mall/promotion/coupon";
 | 
			
		||||
import { DICT_TYPE, getDictDatas} from "@/utils/dict";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "PromotionCoupon",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 导出遮罩层
 | 
			
		||||
      exportLoading: false,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 优惠劵列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        createTime: [],
 | 
			
		||||
        status: undefined,
 | 
			
		||||
      },
 | 
			
		||||
      // Tab 筛选
 | 
			
		||||
      activeTab: 'all',
 | 
			
		||||
      statusTabs: [{
 | 
			
		||||
        label: '全部',
 | 
			
		||||
        value: 'all'
 | 
			
		||||
      }],
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
    // 设置 statuses 过滤
 | 
			
		||||
    for (const dict of getDictDatas(DICT_TYPE.PROMOTION_COUPON_STATUS)) {
 | 
			
		||||
      this.statusTabs.push({
 | 
			
		||||
        label: dict.label,
 | 
			
		||||
        value: dict.value
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getCouponPage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('回收将会收回会员领取的待使用的优惠券,已使用的将无法回收,确定要回收所选优惠券吗?').then(function() {
 | 
			
		||||
          return deleteCoupon(id);
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          this.getList();
 | 
			
		||||
          this.$modal.msgSuccess("回收成功");
 | 
			
		||||
        }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    /** tab 切换 */
 | 
			
		||||
    tabClick(tab) {
 | 
			
		||||
      this.queryParams.status = tab.name === 'all' ? undefined : tab.name;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,404 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="82px">
 | 
			
		||||
      <el-form-item label="优惠券名称" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入优惠劵名" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="优惠券类型" prop="discountType">
 | 
			
		||||
        <el-select v-model="queryParams.discountType" placeholder="请选择优惠券类型" clearable size="small">
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_DISCOUNT_TYPE)"
 | 
			
		||||
                     :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="优惠券状态" prop="status">
 | 
			
		||||
        <el-select v-model="queryParams.status" placeholder="请选择优惠券状态" clearable size="small">
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
 | 
			
		||||
                       :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['promotion:coupon-template:create']">新增</el-button>
 | 
			
		||||
        <el-button type="info" plain icon="el-icon-s-operation" size="mini"
 | 
			
		||||
                   @click="() => this.$router.push('/promotion/coupon')"
 | 
			
		||||
                   v-hasPermi="['promotion:coupon:query']">会员优惠劵</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="优惠券名称" align="center" prop="name" />
 | 
			
		||||
      <el-table-column label="优惠券类型" align="center" prop="discountType">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.PROMOTION_DISCOUNT_TYPE" :value="scope.row.discountType" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="优惠金额 / 折扣" align="center" prop="discount" :formatter="discountFormat" />
 | 
			
		||||
      <el-table-column label="发放数量" align="center" prop="totalCount" />
 | 
			
		||||
      <el-table-column label="剩余数量" align="center" prop="totalCount" :formatter="row => (row.totalCount - row.takeCount)" />
 | 
			
		||||
      <el-table-column label="领取上限" align="center" prop="takeLimitCount" :formatter="takeLimitCountFormat" />
 | 
			
		||||
      <el-table-column label="有效期限" align="center" prop="validityType" width="180" :formatter="validityTypeFormat" />
 | 
			
		||||
      <el-table-column label="状态" align="center" prop="status">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-switch v-model="scope.row.status" :active-value="0" :inactive-value="1" @change="handleStatusChange(scope.row)"/>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                     v-hasPermi="['promotion:coupon-template:update']">修改</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-hasPermi="['promotion:coupon-template:delete']">删除</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="600px" v-dialogDrag append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="140px">
 | 
			
		||||
        <el-form-item label="优惠券名称" prop="name">
 | 
			
		||||
          <el-input v-model="form.name" placeholder="请输入优惠券名称" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="优惠券类型" prop="discountType">
 | 
			
		||||
          <el-radio-group v-model="form.discountType">
 | 
			
		||||
            <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_DISCOUNT_TYPE)"
 | 
			
		||||
                      :key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.discountType === PromotionDiscountTypeEnum.PRICE.type" label="优惠券面额" prop="discountPrice">
 | 
			
		||||
          <el-input-number v-model="form.discountPrice" placeholder="请输入优惠金额,单位:元"
 | 
			
		||||
                           style="width: 400px" :precision="2" :min="0" /> 元
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.discountType === PromotionDiscountTypeEnum.PERCENT.type" label="优惠券折扣" prop="discountPercent">
 | 
			
		||||
          <el-input-number v-model="form.discountPercent" placeholder="优惠券折扣不能小于 1 折,且不可大于 9.9 折"
 | 
			
		||||
                           style="width: 400px" :precision="1" :min="1" :max="9.9" /> 折
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.discountType === PromotionDiscountTypeEnum.PERCENT.type" label="最多优惠" prop="discountLimitPrice">
 | 
			
		||||
          <el-input-number v-model="form.discountLimitPrice" placeholder="请输入最多优惠"
 | 
			
		||||
                           style="width: 400px" :precision="2" :min="0" /> 元
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="满多少元可以使用" prop="usePrice">
 | 
			
		||||
          <el-input-number v-model="form.usePrice" placeholder="无门槛请设为 0"
 | 
			
		||||
                    style="width: 400px" :precision="2" :min="0" /> 元
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="领取方式" prop="takeType">
 | 
			
		||||
          <el-radio-group v-model="form.takeType">
 | 
			
		||||
            <el-radio :key="1" :label="1">直接领取</el-radio>
 | 
			
		||||
            <el-radio :key="2" :label="2">指定发放</el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.takeType === 1" label="发放数量" prop="totalCount">
 | 
			
		||||
          <el-input-number v-model="form.totalCount" placeholder="发放数量,没有之后不能领取或发放,-1 为不限制"
 | 
			
		||||
                           style="width: 400px" :precision="0" :min="-1" /> 张
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.takeType === 1" label="每人限领个数" prop="takeLimitCount">
 | 
			
		||||
          <el-input-number v-model="form.takeLimitCount" placeholder="设置为 -1 时,可无限领取"
 | 
			
		||||
                    style="width: 400px" :precision="0" :min="-1" /> 张
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="有效期类型" prop="validityType">
 | 
			
		||||
          <el-radio-group v-model="form.validityType">
 | 
			
		||||
            <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_COUPON_TEMPLATE_VALIDITY_TYPE)"
 | 
			
		||||
                      :key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.validityType === CouponTemplateValidityTypeEnum.DATE.type" label="固定日期" prop="validTimes">
 | 
			
		||||
          <el-date-picker v-model="form.validTimes" style="width: 240px"  value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange"
 | 
			
		||||
                          :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.validityType === CouponTemplateValidityTypeEnum.TERM.type" label="领取日期" prop="fixedStartTerm">
 | 
			
		||||
          第 <el-input-number v-model="form.fixedStartTerm" placeholder="0 为今天生效"
 | 
			
		||||
                              style="width: 165px" :precision="0" :min="0"/> 至
 | 
			
		||||
          <el-input-number v-model="form.fixedEndTerm" placeholder="请输入结束天数"
 | 
			
		||||
                           style="width: 165px" :precision="0" :min="0"/> 天有效
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="活动商品" prop="productScope">
 | 
			
		||||
          <el-radio-group v-model="form.productScope">
 | 
			
		||||
            <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_PRODUCT_SCOPE)"
 | 
			
		||||
                      :key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.productScope === PromotionProductScopeEnum.SPU.scope" prop="productSpuIds">
 | 
			
		||||
          <el-select v-model="form.productSpuIds" placeholder="请选择活动商品" clearable size="small"
 | 
			
		||||
                     multiple filterable style="width: 400px">
 | 
			
		||||
            <el-option v-for="item in productSpus" :key="item.id" :label="item.name" :value="item.id">
 | 
			
		||||
              <span style="float: left">{{ item.name }}</span>
 | 
			
		||||
              <span style="float: right; color: #8492a6; font-size: 13px">¥{{ (item.minPrice / 100.0).toFixed(2) }}</span>
 | 
			
		||||
            </el-option>
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {
 | 
			
		||||
  createCouponTemplate,
 | 
			
		||||
  updateCouponTemplate,
 | 
			
		||||
  deleteCouponTemplate,
 | 
			
		||||
  getCouponTemplate,
 | 
			
		||||
  getCouponTemplatePage,
 | 
			
		||||
  updateCouponTemplateStatus
 | 
			
		||||
} from "@/api/mall/promotion/couponTemplate";
 | 
			
		||||
import {
 | 
			
		||||
  CommonStatusEnum,
 | 
			
		||||
  CouponTemplateValidityTypeEnum,
 | 
			
		||||
  PromotionDiscountTypeEnum,
 | 
			
		||||
  PromotionProductScopeEnum
 | 
			
		||||
} from "@/utils/constants";
 | 
			
		||||
import { getSpuSimpleList } from "@/api/mall/product/spu";
 | 
			
		||||
import { parseTime } from "@/utils/ruoyi";
 | 
			
		||||
import {changeRoleStatus} from "@/api/system/role";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "PromotionCouponTemplate",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 导出遮罩层
 | 
			
		||||
      exportLoading: false,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 优惠劵列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        name: null,
 | 
			
		||||
        status: null,
 | 
			
		||||
        type: null,
 | 
			
		||||
        createTime: [],
 | 
			
		||||
      },
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {},
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        name: [{ required: true, message: "优惠券名称不能为空", trigger: "blur" }],
 | 
			
		||||
        discountType: [{ required: true, message: "优惠券类型不能为空", trigger: "change" }],
 | 
			
		||||
        discountPrice: [{ required: true, message: "优惠券面额不能为空", trigger: "blur" }],
 | 
			
		||||
        discountPercent: [{ required: true, message: "优惠券折扣不能为空", trigger: "blur" }],
 | 
			
		||||
        discountLimitPrice: [{ required: true, message: "最多优惠不能为空", trigger: "blur" }],
 | 
			
		||||
        usePrice: [{ required: true, message: "满多少元可以使用不能为空", trigger: "blur" }],
 | 
			
		||||
        takeType: [{ required: true, message: "领取方式不能为空", trigger: "change" }],
 | 
			
		||||
        totalCount: [{ required: true, message: "发放数量不能为空", trigger: "blur" }],
 | 
			
		||||
        takeLimitCount: [{ required: true, message: "每人限领个数不能为空", trigger: "blur" }],
 | 
			
		||||
        validityType: [{ required: true, message: "有效期类型不能为空", trigger: "change" }],
 | 
			
		||||
        validTimes: [{ required: true, message: "固定日期不能为空", trigger: "change" }],
 | 
			
		||||
        fixedStartTerm: [{ required: true, message: "开始领取天数不能为空", trigger: "blur" }],
 | 
			
		||||
        fixedEndTerm: [{ required: true, message: "开始领取天数不能为空", trigger: "blur" }],
 | 
			
		||||
        productScope: [{ required: true, message: "商品范围不能为空", trigger: "blur" }],
 | 
			
		||||
        productSpuIds: [{ required: true, message: "商品范围不能为空", trigger: "blur" }],
 | 
			
		||||
      },
 | 
			
		||||
      // 商品列表
 | 
			
		||||
      productSpus: [],
 | 
			
		||||
      // 如下的变量,主要为了 v-if 判断可以使用到
 | 
			
		||||
      PromotionProductScopeEnum: PromotionProductScopeEnum,
 | 
			
		||||
      CouponTemplateValidityTypeEnum: CouponTemplateValidityTypeEnum,
 | 
			
		||||
      PromotionDiscountTypeEnum: PromotionDiscountTypeEnum,
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getCouponTemplatePage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
      // 查询商品列表
 | 
			
		||||
      getSpuSimpleList().then(response => {
 | 
			
		||||
        this.productSpus = response.data
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        discountType: PromotionDiscountTypeEnum.PRICE.type,
 | 
			
		||||
        discountPrice: undefined,
 | 
			
		||||
        discountPercent: undefined,
 | 
			
		||||
        discountLimitPrice: undefined,
 | 
			
		||||
        usePrice: undefined,
 | 
			
		||||
        takeType: 1,
 | 
			
		||||
        totalCount: undefined,
 | 
			
		||||
        takeLimitCount: undefined,
 | 
			
		||||
        validityType: CouponTemplateValidityTypeEnum.DATE.type,
 | 
			
		||||
        validTimes: [],
 | 
			
		||||
        validStartTime: undefined,
 | 
			
		||||
        validEndTime: undefined,
 | 
			
		||||
        fixedStartTerm: undefined,
 | 
			
		||||
        fixedEndTerm: undefined,
 | 
			
		||||
        productScope: PromotionProductScopeEnum.ALL.scope,
 | 
			
		||||
        productSpuIds: [],
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.title = "添加优惠劵";
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      getCouponTemplate(id).then(response => {
 | 
			
		||||
        this.form = {
 | 
			
		||||
          ...response.data,
 | 
			
		||||
          discountPrice: response.data.discountPrice !== undefined ? response.data.discountPrice / 100.0 : undefined,
 | 
			
		||||
          discountPercent: response.data.discountPercent !== undefined ? response.data.discountPercent / 10.0 : undefined,
 | 
			
		||||
          discountLimitPrice: response.data.discountLimitPrice !== undefined ? response.data.discountLimitPrice / 100.0 : undefined,
 | 
			
		||||
          usePrice: response.data.usePrice !== undefined ? response.data.usePrice / 100.0 : undefined,
 | 
			
		||||
          validTimes: [response.data.validStartTime, response.data.validEndTime]
 | 
			
		||||
        }
 | 
			
		||||
        this.open = true;
 | 
			
		||||
        this.title = "修改优惠劵";
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 金额相关字段的缩放
 | 
			
		||||
        let data = {
 | 
			
		||||
          ...this.form,
 | 
			
		||||
          discountPrice: this.form.discountPrice !== undefined ? this.form.discountPrice * 100 : undefined,
 | 
			
		||||
          discountPercent: this.form.discountPercent !== undefined ? this.form.discountPercent * 10 : undefined,
 | 
			
		||||
          discountLimitPrice: this.form.discountLimitPrice !== undefined ? this.form.discountLimitPrice * 100 : undefined,
 | 
			
		||||
          usePrice: this.form.usePrice !== undefined ? this.form.usePrice * 100 : undefined,
 | 
			
		||||
          validStartTime: this.form.validTimes && this.form.validTimes.length === 2 ? this.form.validTimes[0] : undefined,
 | 
			
		||||
          validEndTime: this.form.validTimes && this.form.validTimes.length === 2 ? this.form.validTimes[1] : undefined,
 | 
			
		||||
        }
 | 
			
		||||
        // 修改的提交
 | 
			
		||||
        if (this.form.id != null) {
 | 
			
		||||
          updateCouponTemplate(data).then(response => {
 | 
			
		||||
            this.$modal.msgSuccess("修改成功");
 | 
			
		||||
            this.open = false;
 | 
			
		||||
            this.getList();
 | 
			
		||||
          });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 添加的提交
 | 
			
		||||
        createCouponTemplate(data).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("新增成功");
 | 
			
		||||
          this.open = false;
 | 
			
		||||
          this.getList();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 优惠劵模板状态修改 */
 | 
			
		||||
    handleStatusChange(row) {
 | 
			
		||||
      // 此时,row 已经变成目标状态了,所以可以直接提交请求和提示
 | 
			
		||||
      let text = row.status === CommonStatusEnum.ENABLE ? "启用" : "停用";
 | 
			
		||||
      this.$modal.confirm('确认要"' + text + '""' + row.name + '"优惠劵吗?').then(function() {
 | 
			
		||||
        return updateCouponTemplateStatus(row.id, row.status);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.$modal.msgSuccess(text + "成功");
 | 
			
		||||
      }).catch(function() {
 | 
			
		||||
        // 异常时,需要将 row.status 状态重置回之前的
 | 
			
		||||
        row.status = row.status === CommonStatusEnum.ENABLE ? CommonStatusEnum.DISABLE
 | 
			
		||||
            : CommonStatusEnum.ENABLE;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认删除优惠劵编号为"' + id + '"的数据项?').then(function() {
 | 
			
		||||
          return deleteCouponTemplate(id);
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          this.getList();
 | 
			
		||||
          this.$modal.msgSuccess("删除成功");
 | 
			
		||||
        }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    // 格式化【优惠金额/折扣】
 | 
			
		||||
    discountFormat(row, column) {
 | 
			
		||||
      if (row.discountType === PromotionDiscountTypeEnum.PRICE.type) {
 | 
			
		||||
        return `¥${(row.discountPrice / 100.0).toFixed(2)}`;
 | 
			
		||||
      }
 | 
			
		||||
      if (row.discountType === PromotionDiscountTypeEnum.PERCENT.type) {
 | 
			
		||||
        return `¥${(row.discountPrice / 100.0).toFixed(2)}`;
 | 
			
		||||
      }
 | 
			
		||||
      return '未知【' + row.discountType + '】';
 | 
			
		||||
    },
 | 
			
		||||
    // 格式化【领取上限】
 | 
			
		||||
    takeLimitCountFormat(row, column) {
 | 
			
		||||
      if (row.takeLimitCount === -1) {
 | 
			
		||||
        return '无领取限制';
 | 
			
		||||
      }
 | 
			
		||||
      return `${row.takeLimitCount} 张/人`
 | 
			
		||||
    },
 | 
			
		||||
    // 格式化【有效期限】
 | 
			
		||||
    validityTypeFormat(row, column) {
 | 
			
		||||
      if (row.validityType === CouponTemplateValidityTypeEnum.DATE.type) {
 | 
			
		||||
        return `${parseTime(row.validStartTime)} 至 ${parseTime(row.validEndTime)}`
 | 
			
		||||
      }
 | 
			
		||||
      if (row.validityType === CouponTemplateValidityTypeEnum.TERM.type) {
 | 
			
		||||
        return `领取后第 ${row.fixedStartTerm} - ${row.fixedEndTerm} 天内可用`
 | 
			
		||||
      }
 | 
			
		||||
      return '未知【' + row.validityType + '】';
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,383 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="活动名称" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入活动名称" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="活动状态" prop="status">
 | 
			
		||||
        <el-select v-model="queryParams.status" placeholder="请选择活动状态" clearable size="small">
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_ACTIVITY_STATUS)"
 | 
			
		||||
                       :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['promotion:discount-activity:create']">新增</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="活动名称" align="center" prop="name" />
 | 
			
		||||
      <el-table-column label="活动时间" align="center" prop="startTime" width="240">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <div>开始:{{ parseTime(scope.row.startTime) }}</div>
 | 
			
		||||
          <div>结束:{{ parseTime(scope.row.endTime) }}</div>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="状态" align="center" prop="status">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.PROMOTION_ACTIVITY_STATUS" :value="scope.row.status" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                     v-if="scope.row.status !== PromotionActivityStatusEnum.CLOSE.type"
 | 
			
		||||
                     v-hasPermi="['promotion:discount-activity:update']">修改</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleClose(scope.row)"
 | 
			
		||||
                     v-if="scope.row.status !== PromotionActivityStatusEnum.CLOSE.type &&
 | 
			
		||||
                            scope.row.status !== PromotionActivityStatusEnum.END.type"
 | 
			
		||||
                     v-hasPermi="['promotion:discount-activity:close']">关闭</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-if="scope.row.status === PromotionActivityStatusEnum.CLOSE.type"
 | 
			
		||||
                     v-hasPermi="['promotion:discount-activity:delete']">删除</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="1000px" v-dialogDrag append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
 | 
			
		||||
        <el-form-item label="活动名称" prop="name">
 | 
			
		||||
          <el-input v-model="form.name" placeholder="请输入活动名称" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="备注" prop="remark">
 | 
			
		||||
          <el-input type="textarea" v-model="form.remark" placeholder="请输入备注" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="活动时间" prop="startAndEndTime">
 | 
			
		||||
          <el-date-picker clearable v-model="form.startAndEndTime" type="datetimerange" :default-time="['00:00:00', '23:59:59']"
 | 
			
		||||
                          value-format="timestamp" placeholder="选择开始时间" style="width: 880px" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="商品选择">
 | 
			
		||||
          <el-select v-model="form.skuIds" placeholder="请选择活动商品" clearable size="small"
 | 
			
		||||
                     multiple filterable style="width: 880px" @change="changeFormSku">
 | 
			
		||||
            <el-option v-for="item in productSkus" :key="item.id" :label="item.spuName + ' ' + item.name" :value="item.id">
 | 
			
		||||
              <span style="float: left">{{ item.spuName }}   {{ item.name}}</span>
 | 
			
		||||
              <span style="float: right; color: #8492a6; font-size: 13px">¥{{ (item.price / 100.0).toFixed(2) }}</span>
 | 
			
		||||
            </el-option>
 | 
			
		||||
          </el-select>
 | 
			
		||||
          <el-table v-loading="loading" :data="form.products">
 | 
			
		||||
            <el-table-column label="商品名称" align="center" width="200">
 | 
			
		||||
              <template v-slot="scope">
 | 
			
		||||
                {{ scope.row.spuName }}   {{ scope.row.name}}
 | 
			
		||||
              </template>
 | 
			
		||||
            </el-table-column>
 | 
			
		||||
            <el-table-column label="商品价格" align="center" prop="price">
 | 
			
		||||
              <template v-slot="scope">
 | 
			
		||||
                ¥{{ (scope.row.price / 100.0).toFixed(2) }}
 | 
			
		||||
              </template>
 | 
			
		||||
            </el-table-column>
 | 
			
		||||
            <el-table-column label="库存" align="center" prop="stock" />
 | 
			
		||||
            <el-table-column label="优惠类型" align="center" property="discountType">
 | 
			
		||||
              <template v-slot="scope">
 | 
			
		||||
                <el-select v-model="scope.row.discountType" placeholder="请选择优惠类型">
 | 
			
		||||
                  <el-option v-for="dict in getDictDatas(DICT_TYPE.PROMOTION_DISCOUNT_TYPE)"
 | 
			
		||||
                             :key="dict.value" :label="dict.label" :value="parseInt(dict.value)"/>
 | 
			
		||||
                </el-select>
 | 
			
		||||
              </template>
 | 
			
		||||
            </el-table-column>
 | 
			
		||||
            <el-table-column label="优惠" align="center" prop="startTime" width="250">
 | 
			
		||||
              <template v-slot="scope">
 | 
			
		||||
                <el-form-item v-if="scope.row.discountType === PromotionDiscountTypeEnum.PRICE.type" prop="discountPrice">
 | 
			
		||||
                  减 <el-input-number v-model="scope.row.discountPrice" placeholder="请输入优惠金额"
 | 
			
		||||
                                      style="width: 190px" :precision="2" :min="0" :max="scope.row.price / 100.0 - 0.01" /> 元
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item v-if="scope.row.discountType === PromotionDiscountTypeEnum.PERCENT.type" prop="discountPercent">
 | 
			
		||||
                  打 <el-input-number v-model="scope.row.discountPercent" placeholder="请输入优惠折扣"
 | 
			
		||||
                                      style="width: 190px" :precision="1" :min="1" :max="9.9" /> 折
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
              </template>
 | 
			
		||||
            </el-table-column>
 | 
			
		||||
            <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
              <template v-slot="scope">
 | 
			
		||||
                <el-button size="mini" type="text" icon="el-icon-delete" @click="removeFormSku(scope.row.skuId)">删除</el-button>
 | 
			
		||||
              </template>
 | 
			
		||||
            </el-table-column>
 | 
			
		||||
          </el-table>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {
 | 
			
		||||
  createDiscountActivity,
 | 
			
		||||
  updateDiscountActivity,
 | 
			
		||||
  deleteDiscountActivity,
 | 
			
		||||
  getDiscountActivity,
 | 
			
		||||
  getDiscountActivityPage,
 | 
			
		||||
  closeDiscountActivity
 | 
			
		||||
} from "@/api/mall/promotion/discountActivity";
 | 
			
		||||
import {
 | 
			
		||||
  PromotionActivityStatusEnum, PromotionDiscountTypeEnum,
 | 
			
		||||
  PromotionProductScopeEnum
 | 
			
		||||
} from "@/utils/constants";
 | 
			
		||||
import { getSkuOptionList } from "@/api/mall/product/sku";
 | 
			
		||||
import { deepClone } from "@/utils";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "PromotionDiscountActivity",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 导出遮罩层
 | 
			
		||||
      exportLoading: false,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 限时折扣活动列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层名称
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        name: null,
 | 
			
		||||
        status: null,
 | 
			
		||||
        createTime: [],
 | 
			
		||||
      },
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {
 | 
			
		||||
        skuIds: [], // 选中的 SKU
 | 
			
		||||
        products: [], // 商品信息
 | 
			
		||||
      },
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        name: [{ required: true, message: "活动名称不能为空", trigger: "blur" }],
 | 
			
		||||
        startAndEndTime: [{ required: true, message: "活动时间不能为空", trigger: "blur" }],
 | 
			
		||||
        skuIds: [{ required: true, message: "选择商品不能为空", trigger: "blur" }],
 | 
			
		||||
      },
 | 
			
		||||
      // 商品 SKU 列表
 | 
			
		||||
      productSkus: [],
 | 
			
		||||
      // 如下的变量,主要为了 v-if 判断可以使用到
 | 
			
		||||
      PromotionProductScopeEnum: PromotionProductScopeEnum,
 | 
			
		||||
      PromotionActivityStatusEnum: PromotionActivityStatusEnum,
 | 
			
		||||
      PromotionDiscountTypeEnum: PromotionDiscountTypeEnum,
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getDiscountActivityPage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
      // 获得 SKU 商品列表
 | 
			
		||||
      getSkuOptionList().then(response => {
 | 
			
		||||
        this.productSkus = response.data;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        startAndEndTime: undefined,
 | 
			
		||||
        startTime: undefined,
 | 
			
		||||
        endTime: undefined,
 | 
			
		||||
        remark: undefined,
 | 
			
		||||
        skuIds: [],
 | 
			
		||||
        products: [],
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.title = "添加限时折扣活动";
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      getDiscountActivity(id).then(response => {
 | 
			
		||||
        this.form = response.data;
 | 
			
		||||
        // 修改数据
 | 
			
		||||
        this.form.startAndEndTime = [response.data.startTime, response.data.endTime];
 | 
			
		||||
        this.form.skuIds = response.data.products.map(item => item.skuId);
 | 
			
		||||
        this.form.products.forEach(product => {
 | 
			
		||||
          // 获得对应的 SKU 信息
 | 
			
		||||
          const sku = this.productSkus.find(item => item.id === product.skuId);
 | 
			
		||||
          if (!sku) {
 | 
			
		||||
            return;
 | 
			
		||||
          }
 | 
			
		||||
          // 设置商品信息
 | 
			
		||||
          product.name = sku.name;
 | 
			
		||||
          product.spuName = sku.spuName;
 | 
			
		||||
          product.price = sku.price;
 | 
			
		||||
          product.stock = sku.stock;
 | 
			
		||||
          product.discountPrice = product.discountPrice !== undefined ? product.discountPrice / 100.0 : undefined;
 | 
			
		||||
          product.discountPercent = product.discountPercent !== undefined ? product.discountPercent / 10.0 : undefined;
 | 
			
		||||
        });
 | 
			
		||||
        // 打开弹窗
 | 
			
		||||
        this.open = true;
 | 
			
		||||
        this.title = "修改限时折扣活动";
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 处理数据
 | 
			
		||||
        const data = deepClone(this.form); // 必须深拷贝,不然后面的 products 操作会有影响
 | 
			
		||||
        data.startTime = this.form.startAndEndTime[0];
 | 
			
		||||
        data.endTime = this.form.startAndEndTime[1];
 | 
			
		||||
        data.products.forEach(product => {
 | 
			
		||||
          product.discountPrice = product.discountPrice !== undefined ? product.discountPrice * 100 : undefined;
 | 
			
		||||
          product.discountPercent = product.discountPercent !== undefined ? product.discountPercent * 10 : undefined;
 | 
			
		||||
        });
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 修改的提交
 | 
			
		||||
        if (this.form.id != null) {
 | 
			
		||||
          updateDiscountActivity(data).then(response => {
 | 
			
		||||
            this.$modal.msgSuccess("修改成功");
 | 
			
		||||
            this.open = false;
 | 
			
		||||
            this.getList();
 | 
			
		||||
          });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 添加的提交
 | 
			
		||||
        createDiscountActivity(data).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("新增成功");
 | 
			
		||||
          this.open = false;
 | 
			
		||||
          this.getList();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认删除限时折扣活动编号为"' + id + '"的数据项?').then(function() {
 | 
			
		||||
          return deleteDiscountActivity(id);
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          this.getList();
 | 
			
		||||
          this.$modal.msgSuccess("删除成功");
 | 
			
		||||
        }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    /** 关闭按钮操作 */
 | 
			
		||||
    handleClose(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认关闭限时折扣活动编号为"' + id + '"的数据项?').then(function() {
 | 
			
		||||
        return closeDiscountActivity(id);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("关闭成功");
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    /** 当 Form 的 SKU 发生变化时 */
 | 
			
		||||
    changeFormSku(skuIds) {
 | 
			
		||||
      // 处理【新增】
 | 
			
		||||
      skuIds.forEach(skuId => {
 | 
			
		||||
        // 获得对应的 SKU 信息
 | 
			
		||||
        const sku = this.productSkus.find(item => item.id === skuId);
 | 
			
		||||
        if (!sku) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 判断已存在,直接跳过
 | 
			
		||||
        const product = this.form.products.find(item => item.skuId === skuId);
 | 
			
		||||
        if (product) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        this.form.products.push({
 | 
			
		||||
          skuId: sku.id,
 | 
			
		||||
          name: sku.name,
 | 
			
		||||
          price: sku.price,
 | 
			
		||||
          stock: sku.stock,
 | 
			
		||||
          spuId: sku.spuId,
 | 
			
		||||
          spuName: sku.spuName,
 | 
			
		||||
          discountType: PromotionDiscountTypeEnum.PRICE.type,
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
      // 处理【移除】
 | 
			
		||||
      this.form.products.map((product, index) => {
 | 
			
		||||
        if (!skuIds.includes(product.skuId)) {
 | 
			
		||||
          this.form.products.splice(index, 1);
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 移除 Form 的 SKU */
 | 
			
		||||
    removeFormSku(skuId) {
 | 
			
		||||
      this.form.skuIds.map((id, index) => {
 | 
			
		||||
        if (skuId === id) {
 | 
			
		||||
          this.form.skuIds.splice(index, 1);
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
      this.changeFormSku(this.form.skuIds);
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,306 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="活动名称" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入活动名称" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="活动状态" prop="status">
 | 
			
		||||
        <el-select v-model="queryParams.status" placeholder="请选择活动状态" clearable size="small">
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_ACTIVITY_STATUS)"
 | 
			
		||||
                       :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['promotion:reward-activity:create']">新增</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="活动名称" align="center" prop="name" />
 | 
			
		||||
      <el-table-column label="活动时间" align="center" prop="startTime" width="240">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <div>开始:{{ parseTime(scope.row.startTime) }}</div>
 | 
			
		||||
          <div>结束:{{ parseTime(scope.row.endTime) }}</div>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="状态" align="center" prop="status">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.PROMOTION_ACTIVITY_STATUS" :value="scope.row.status" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                     v-if="scope.row.status !== PromotionActivityStatusEnum.CLOSE.type"
 | 
			
		||||
                     v-hasPermi="['promotion:reward-activity:update']">修改</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleClose(scope.row)"
 | 
			
		||||
                     v-if="scope.row.status !== PromotionActivityStatusEnum.CLOSE.type &&
 | 
			
		||||
                            scope.row.status !== PromotionActivityStatusEnum.END.type"
 | 
			
		||||
                     v-hasPermi="['promotion:reward-activity:close']">关闭</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-if="scope.row.status === PromotionActivityStatusEnum.CLOSE.type"
 | 
			
		||||
                     v-hasPermi="['promotion:reward-activity:delete']">删除</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="600px" v-dialogDrag append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
 | 
			
		||||
        <el-form-item label="活动名称" prop="name">
 | 
			
		||||
          <el-input v-model="form.name" placeholder="请输入活动名称" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="活动时间" prop="startAndEndTime">
 | 
			
		||||
          <el-date-picker clearable v-model="form.startAndEndTime" type="datetimerange" :default-time="['00:00:00', '23:59:59']"
 | 
			
		||||
                          value-format="timestamp" placeholder="选择开始时间" style="width: 480px" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="条件类型" prop="conditionType">
 | 
			
		||||
          <el-radio-group v-model="form.conditionType">
 | 
			
		||||
            <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_CONDITION_TYPE)"
 | 
			
		||||
                      :key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="优惠设置" prop="conditionType">
 | 
			
		||||
          <!-- TODO 芋艿:待实现! -->
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="活动商品" prop="productScope">
 | 
			
		||||
          <el-radio-group v-model="form.productScope">
 | 
			
		||||
            <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_PRODUCT_SCOPE)"
 | 
			
		||||
                      :key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item v-if="form.productScope === PromotionProductScopeEnum.SPU.scope" prop="productSpuIds">
 | 
			
		||||
          <el-select v-model="form.productSpuIds" placeholder="请选择活动商品" clearable size="small"
 | 
			
		||||
                     multiple filterable style="width: 400px">
 | 
			
		||||
            <el-option v-for="item in productSpus" :key="item.id" :label="item.name" :value="item.id">
 | 
			
		||||
              <span style="float: left">{{ item.name }}</span>
 | 
			
		||||
              <span style="float: right; color: #8492a6; font-size: 13px">¥{{ (item.minPrice / 100.0).toFixed(2) }}</span>
 | 
			
		||||
            </el-option>
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="备注" prop="remark">
 | 
			
		||||
          <el-input v-model="form.remark" placeholder="请输入备注" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {
 | 
			
		||||
  createRewardActivity,
 | 
			
		||||
  updateRewardActivity,
 | 
			
		||||
  deleteRewardActivity,
 | 
			
		||||
  getRewardActivity,
 | 
			
		||||
  getRewardActivityPage,
 | 
			
		||||
  closeRewardActivity
 | 
			
		||||
} from "@/api/mall/promotion/rewardActivity";
 | 
			
		||||
import {
 | 
			
		||||
  PromotionConditionTypeEnum,
 | 
			
		||||
  PromotionProductScopeEnum,
 | 
			
		||||
  PromotionActivityStatusEnum
 | 
			
		||||
} from "@/utils/constants";
 | 
			
		||||
import {getSpuSimpleList} from "@/api/mall/product/spu";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "PromotionRewardActivity",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 导出遮罩层
 | 
			
		||||
      exportLoading: false,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 满减送活动列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        name: null,
 | 
			
		||||
        status: null,
 | 
			
		||||
      },
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {},
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        name: [{ required: true, message: "活动名称不能为空", trigger: "blur" }],
 | 
			
		||||
        startAndEndTime: [{ required: true, message: "活动时间不能为空", trigger: "blur" }],
 | 
			
		||||
        conditionType: [{ required: true, message: "条件类型不能为空", trigger: "change" }],
 | 
			
		||||
        productScope: [{ required: true, message: "商品范围不能为空", trigger: "blur" }],
 | 
			
		||||
        productSpuIds: [{ required: true, message: "商品范围不能为空", trigger: "blur" }],
 | 
			
		||||
      },
 | 
			
		||||
      // 商品列表
 | 
			
		||||
      productSpus: [],
 | 
			
		||||
      // 如下的变量,主要为了 v-if 判断可以使用到
 | 
			
		||||
      PromotionProductScopeEnum: PromotionProductScopeEnum,
 | 
			
		||||
      PromotionActivityStatusEnum: PromotionActivityStatusEnum,
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
    // 查询商品列表
 | 
			
		||||
    getSpuSimpleList().then(response => {
 | 
			
		||||
      this.productSpus = response.data
 | 
			
		||||
    })
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getRewardActivityPage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        startAndEndTime: undefined,
 | 
			
		||||
        startTime: undefined,
 | 
			
		||||
        endTime: undefined,
 | 
			
		||||
        conditionType: PromotionConditionTypeEnum.PRICE.type,
 | 
			
		||||
        remark: undefined,
 | 
			
		||||
        productScope: PromotionProductScopeEnum.ALL.scope,
 | 
			
		||||
        productSpuIds: undefined,
 | 
			
		||||
        rules: undefined,
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.title = "添加满减送活动";
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      getRewardActivity(id).then(response => {
 | 
			
		||||
        this.form = response.data;
 | 
			
		||||
        this.form.startAndEndTime = [response.data.startTime, response.data.endTime];
 | 
			
		||||
        this.open = true;
 | 
			
		||||
        this.title = "修改满减送活动";
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        this.form.startTime = this.form.startAndEndTime[0];
 | 
			
		||||
        this.form.endTime = this.form.startAndEndTime[1];
 | 
			
		||||
        // TODO 芋艿:临时实现
 | 
			
		||||
        this.form.rules = [
 | 
			
		||||
          {
 | 
			
		||||
            limit: 1,
 | 
			
		||||
            discountPrice: 10,
 | 
			
		||||
            freeDelivery: true,
 | 
			
		||||
            point: 10,
 | 
			
		||||
            couponIds: [10, 20],
 | 
			
		||||
            couponCounts: [1, 2]
 | 
			
		||||
          }, {
 | 
			
		||||
            limit: 2,
 | 
			
		||||
            discountPrice: 20,
 | 
			
		||||
            freeDelivery: false,
 | 
			
		||||
            point: 20,
 | 
			
		||||
            couponIds: [30, 40],
 | 
			
		||||
            couponCounts: [3, 4]
 | 
			
		||||
          }
 | 
			
		||||
        ];
 | 
			
		||||
        // 修改的提交
 | 
			
		||||
        if (this.form.id != null) {
 | 
			
		||||
          updateRewardActivity(this.form).then(response => {
 | 
			
		||||
            this.$modal.msgSuccess("修改成功");
 | 
			
		||||
            this.open = false;
 | 
			
		||||
            this.getList();
 | 
			
		||||
          });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 添加的提交
 | 
			
		||||
        createRewardActivity(this.form).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("新增成功");
 | 
			
		||||
          this.open = false;
 | 
			
		||||
          this.getList();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认删除满减送活动编号为"' + id + '"的数据项?').then(function() {
 | 
			
		||||
          return deleteRewardActivity(id);
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          this.getList();
 | 
			
		||||
          this.$modal.msgSuccess("删除成功");
 | 
			
		||||
        }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    /** 关闭按钮操作 */
 | 
			
		||||
    handleClose(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认关闭满减送活动编号为"' + id + '"的数据项?').then(function() {
 | 
			
		||||
        return closeRewardActivity(id);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("关闭成功");
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,491 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
    <div class="app-container">
 | 
			
		||||
      <doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
 | 
			
		||||
 | 
			
		||||
        <!-- 搜索工作栏 -->
 | 
			
		||||
        <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"
 | 
			
		||||
            label-width="68px">
 | 
			
		||||
            <el-form-item label="活动名称" prop="name">
 | 
			
		||||
                <el-input v-model="queryParams.name" placeholder="请输入秒杀活动名称" clearable
 | 
			
		||||
                    @keyup.enter.native="handleQuery" />
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="活动状态" prop="status">
 | 
			
		||||
                <el-select v-model="queryParams.status" placeholder="请选择活动状态" clearable size="small">
 | 
			
		||||
                    <el-option v-for="dict in this.getDictDatas(DICT_TYPE.PROMOTION_ACTIVITY_STATUS)" :key="dict.value"
 | 
			
		||||
                        :label="dict.label" :value="dict.value" />
 | 
			
		||||
                </el-select>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="参与场次" prop="timeId">
 | 
			
		||||
                <el-select v-model="queryParams.timeId" placeholder="请选择参与场次" clearable size="small">
 | 
			
		||||
                    <el-option v-for="item in seckillTimeList" :key="item.id" :label="item.name" :value="item.id" />
 | 
			
		||||
                </el-select>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
                <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss"
 | 
			
		||||
                    type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
 | 
			
		||||
                    :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
            <el-form-item>
 | 
			
		||||
                <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
                <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
        </el-form>
 | 
			
		||||
 | 
			
		||||
        <!-- 操作工具栏 -->
 | 
			
		||||
        <el-row :gutter="10" class="mb8">
 | 
			
		||||
            <el-col :span="1.5">
 | 
			
		||||
                <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                    v-hasPermi="['promotion:seckill-activity:create']">新增秒杀活动</el-button>
 | 
			
		||||
            </el-col>
 | 
			
		||||
            <el-col :span="1.5">
 | 
			
		||||
                <el-button type="primary" plain icon="el-icon-menu" size="mini" @click="openSeckillTime"
 | 
			
		||||
                    v-hasPermi="['promotion:seckill-activity:create']">管理参与场次</el-button>
 | 
			
		||||
            </el-col>
 | 
			
		||||
            <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
        </el-row>
 | 
			
		||||
 | 
			
		||||
        <!-- 列表 -->
 | 
			
		||||
        <el-table v-loading="loading" :data="list">
 | 
			
		||||
            <el-table-column label="活动名称" align="center" prop="name" />
 | 
			
		||||
            <el-table-column label="活动状态" align="center" prop="status">
 | 
			
		||||
                <template v-slot="scope">
 | 
			
		||||
                    <dict-tag :type="DICT_TYPE.PROMOTION_ACTIVITY_STATUS" :value="scope.row.status" />
 | 
			
		||||
                </template>
 | 
			
		||||
            </el-table-column>
 | 
			
		||||
            <el-table-column label="参与场次" prop="timeIds" width="250">
 | 
			
		||||
                <template v-slot="scope">
 | 
			
		||||
                    <span v-for="item in seckillTimeList" :key="item.id"
 | 
			
		||||
                        v-if="scope.row.timeIds.includes(item.id)">
 | 
			
		||||
                        <el-tag style="margin:4px;" size="small">{{ item.name }}</el-tag>
 | 
			
		||||
                    </span>
 | 
			
		||||
                </template>
 | 
			
		||||
            </el-table-column>
 | 
			
		||||
            <el-table-column label="活动开始时间" align="center" prop="startTime" width="190">
 | 
			
		||||
                <template v-slot="scope">
 | 
			
		||||
                    <span>{{ "开始: " + parseTime(scope.row.startTime) }}</span>
 | 
			
		||||
                    <span>{{ "结束: " + parseTime(scope.row.endTime) }}</span>
 | 
			
		||||
                </template>
 | 
			
		||||
            </el-table-column>
 | 
			
		||||
 | 
			
		||||
            <el-table-column label="付款订单数" align="center" prop="orderCount" />
 | 
			
		||||
            <el-table-column label="付款人数" align="center" prop="userCount" />
 | 
			
		||||
            <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
                <template v-slot="scope">
 | 
			
		||||
                    <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
                </template>
 | 
			
		||||
            </el-table-column>
 | 
			
		||||
            <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
                <template v-slot="scope">
 | 
			
		||||
                    <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                        v-hasPermi="['promotion:seckill-activity:update']">修改</el-button>
 | 
			
		||||
                    <el-button size="mini" type="text" icon="el-icon-close" @click="handleClose(scope.row)"
 | 
			
		||||
                        v-hasPermi="['promotion:seckill-activity:delete']">关闭</el-button>
 | 
			
		||||
                    <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                        v-hasPermi="['promotion:seckill-activity:delete']">删除</el-button>
 | 
			
		||||
                </template>
 | 
			
		||||
            </el-table-column>
 | 
			
		||||
        </el-table>
 | 
			
		||||
        <!-- 分页组件 -->
 | 
			
		||||
        <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
            @pagination="getList" />
 | 
			
		||||
 | 
			
		||||
        <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
        <el-dialog :title="title" :visible.sync="open" width="1200px" v-dialogDrag append-to-body>
 | 
			
		||||
            <el-form ref="form" :model="form" :rules="rules" label-width="80px">
 | 
			
		||||
                <el-form-item label="活动名称" prop="name">
 | 
			
		||||
                    <el-input v-model="form.name" placeholder="请输入秒杀活动名称" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item label="活动时间" prop="startAndEndTime">
 | 
			
		||||
                    <el-date-picker clearable v-model="form.startAndEndTime" type="datetimerange"
 | 
			
		||||
                        value-format="timestamp" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"
 | 
			
		||||
                        style="width: 1080px" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item label="排序" prop="sort">
 | 
			
		||||
                    <el-input-number v-model="form.sort" controls-position="right" :min="0" :max="10000">
 | 
			
		||||
                    </el-input-number>
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item label="备注" prop="remark">
 | 
			
		||||
                    <el-input type="textarea" v-model="form.remark" placeholder="请输入备注" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item label="场次选择">
 | 
			
		||||
                    <el-select v-model="form.timeIds" placeholder="请选择参与场次" clearable size="small" multiple filterable
 | 
			
		||||
                        style="width: 880px">
 | 
			
		||||
                        <el-option v-for="item in seckillTimeList" :key="item.id" :label="item.name" :value="item.id">
 | 
			
		||||
                            <span style="float: left">{{ item.name + ': { ' }} {{ item.startTime }} -- {{ item.endTime +
 | 
			
		||||
                                    ' }'
 | 
			
		||||
                            }}</span>
 | 
			
		||||
                            <span style="float: right; color: #8492a6; font-size: 13px"></span>
 | 
			
		||||
                        </el-option>
 | 
			
		||||
                    </el-select>
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item label="商品选择">
 | 
			
		||||
                    <el-select v-model="form.skuIds" placeholder="请选择活动商品" clearable size="small" multiple filterable
 | 
			
		||||
                        style="width: 880px" @change="changeFormSku">
 | 
			
		||||
                        <el-option v-for="item in productSkus" :key="item.id" :label="item.spuName + ' ' + item.name"
 | 
			
		||||
                            :value="item.id">
 | 
			
		||||
                            <span style="float: left">{{ item.spuName }}   {{ item.name }}</span>
 | 
			
		||||
                            <span style="float: right; color: #8492a6; font-size: 13px">¥{{ (item.price /
 | 
			
		||||
                                    100.0).toFixed(2)
 | 
			
		||||
                            }}</span>
 | 
			
		||||
                        </el-option>
 | 
			
		||||
                    </el-select>
 | 
			
		||||
                    <el-row>
 | 
			
		||||
                        <el-button type="primary" size="mini" @click="batchEditProduct('limitBuyCount')">限购</el-button>
 | 
			
		||||
                        <el-button type="primary" size="mini" @click="batchEditProduct('seckillPrice')">秒杀价</el-button>
 | 
			
		||||
                        <el-button type="primary" size="mini" @click="batchEditProduct('seckillStock')">秒杀库存</el-button>
 | 
			
		||||
                    </el-row>
 | 
			
		||||
                    <el-table v-loading="loading" ref="productsTable" :data="form.products">
 | 
			
		||||
                        <el-table-column type="selection" width="55">
 | 
			
		||||
                        </el-table-column>
 | 
			
		||||
                        <el-table-column label="商品名称" align="center" width="200">
 | 
			
		||||
                            <template v-slot="scope">
 | 
			
		||||
                                {{ scope.row.spuName }}   {{ scope.row.name }}
 | 
			
		||||
                            </template>
 | 
			
		||||
                        </el-table-column>
 | 
			
		||||
                        <el-table-column label="商品价格" align="center" prop="price">
 | 
			
		||||
                            <template v-slot="scope">
 | 
			
		||||
                                ¥{{ (scope.row.price / 100.0).toFixed(2) }}
 | 
			
		||||
                            </template>
 | 
			
		||||
                        </el-table-column>
 | 
			
		||||
                        <el-table-column label="库存" align="center" prop="productStock" />
 | 
			
		||||
                        <el-table-column label="限购(0为不限购)" align="center" width="150">
 | 
			
		||||
                            <template v-slot="scope">
 | 
			
		||||
                                <el-input-number v-model="scope.row.limitBuyCount" size="mini" :min="0" :max="10000">
 | 
			
		||||
                                </el-input-number>
 | 
			
		||||
                            </template>
 | 
			
		||||
                        </el-table-column>
 | 
			
		||||
                        <el-table-column label="秒杀价(元)" align="center" width="150">
 | 
			
		||||
                            <template v-slot="scope">
 | 
			
		||||
                                <el-input-number v-model="scope.row.seckillPrice" size="mini" :precision="2" :min="0"
 | 
			
		||||
                                    :max="10000">
 | 
			
		||||
                                </el-input-number>
 | 
			
		||||
                            </template>
 | 
			
		||||
                        </el-table-column>
 | 
			
		||||
                        <el-table-column label="秒杀库存" align="center" width="150" prop="seckillStock">
 | 
			
		||||
                            <template v-slot="scope">
 | 
			
		||||
                                <el-input-number v-model="scope.row.seckillStock" size="mini" :min="0" :max="10000">
 | 
			
		||||
                                </el-input-number>
 | 
			
		||||
                            </template>
 | 
			
		||||
                        </el-table-column>
 | 
			
		||||
                        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
                            <template v-slot="scope">
 | 
			
		||||
                                <el-button size="mini" type="text" icon="el-icon-delete"
 | 
			
		||||
                                    @click="removeFormSku(scope.row.skuId)">删除
 | 
			
		||||
                                </el-button>
 | 
			
		||||
                            </template>
 | 
			
		||||
                        </el-table-column>
 | 
			
		||||
                    </el-table>
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
            </el-form>
 | 
			
		||||
            <div slot="footer" class="dialog-footer">
 | 
			
		||||
                <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
                <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
            </div>
 | 
			
		||||
        </el-dialog>
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { getSkuOptionList } from "@/api/mall/product/sku";
 | 
			
		||||
import { createSeckillActivity, updateSeckillActivity, closeSeckillActivity, deleteSeckillActivity, getSeckillActivity, getSeckillActivityPage, exportSeckillActivityExcel } from "@/api/mall/promotion/seckillActivity";
 | 
			
		||||
import { getSeckillTimeList } from "@/api/mall/promotion/seckillTime";
 | 
			
		||||
import { deepClone } from "@/utils";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    name: "PromotionSeckillActivity",
 | 
			
		||||
    components: {
 | 
			
		||||
    },
 | 
			
		||||
    data() {
 | 
			
		||||
        return {
 | 
			
		||||
            // 遮罩层
 | 
			
		||||
            loading: true,
 | 
			
		||||
            // 显示搜索条件
 | 
			
		||||
            showSearch: true,
 | 
			
		||||
            // 总条数
 | 
			
		||||
            total: 0,
 | 
			
		||||
            // 秒杀活动列表
 | 
			
		||||
            list: [],
 | 
			
		||||
            // 秒杀场次列表
 | 
			
		||||
            seckillTimeList: [],
 | 
			
		||||
            // 弹出层标题
 | 
			
		||||
            title: "",
 | 
			
		||||
            // 是否显示弹出层
 | 
			
		||||
            open: false,
 | 
			
		||||
            // 查询参数
 | 
			
		||||
            queryParams: {
 | 
			
		||||
                pageNo: 1,
 | 
			
		||||
                pageSize: 10,
 | 
			
		||||
                name: null,
 | 
			
		||||
                status: null,
 | 
			
		||||
                timeId: null,
 | 
			
		||||
                createTime: [],
 | 
			
		||||
            },
 | 
			
		||||
            // 表单参数
 | 
			
		||||
            form: {
 | 
			
		||||
                skuIds: [], // 选中的 SKU
 | 
			
		||||
                products: [], // 商品信息
 | 
			
		||||
                timeIds: [], //选中的秒杀场次id
 | 
			
		||||
            },
 | 
			
		||||
            // 商品 SKU 列表
 | 
			
		||||
            productSkus: [],
 | 
			
		||||
            // 表单校验
 | 
			
		||||
            rules: {
 | 
			
		||||
                name: [{ required: true, message: "秒杀活动名称不能为空", trigger: "blur" }],
 | 
			
		||||
                status: [{ required: true, message: "活动状态不能为空", trigger: "blur" }],
 | 
			
		||||
                startAndEndTime: [{ required: true, message: "活动时间不能为空", trigger: "blur" }],
 | 
			
		||||
                sort: [{ required: true, message: "排序不能为空", trigger: "blur" }],
 | 
			
		||||
                timeIds: [{ required: true, message: "秒杀场次不能为空", trigger: "blur" }],
 | 
			
		||||
                totalPrice: [{ required: true, message: "订单实付金额,单位:分不能为空", trigger: "blur" }],
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    },
 | 
			
		||||
    created() {
 | 
			
		||||
        this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    watch: {
 | 
			
		||||
        $route: 'getList'
 | 
			
		||||
    },
 | 
			
		||||
    methods: {
 | 
			
		||||
        /** 查询列表 */
 | 
			
		||||
        getList() {
 | 
			
		||||
            // 从秒杀时段跳转过来并鞋带timeId参数进行查询
 | 
			
		||||
            const timeId = this.$route.params && this.$route.params.timeId;
 | 
			
		||||
            if (timeId) {
 | 
			
		||||
                this.queryParams.timeId = timeId
 | 
			
		||||
            }
 | 
			
		||||
            this.loading = true;
 | 
			
		||||
            // 执行查询
 | 
			
		||||
            getSeckillActivityPage(this.queryParams).then(response => {
 | 
			
		||||
                console.log(response.data.list, "查询出的值");
 | 
			
		||||
                this.list = response.data.list;
 | 
			
		||||
                this.total = response.data.total;
 | 
			
		||||
                this.loading = false;
 | 
			
		||||
            });
 | 
			
		||||
            if (timeId) {
 | 
			
		||||
                //查询完成后设置为空
 | 
			
		||||
                this.$route.params.timeId = undefined
 | 
			
		||||
            }
 | 
			
		||||
            // 获得 SKU 商品列表
 | 
			
		||||
            getSkuOptionList().then(response => {
 | 
			
		||||
                this.productSkus = response.data;
 | 
			
		||||
            });
 | 
			
		||||
            // 获取参与场次列表
 | 
			
		||||
            getSeckillTimeList().then(response => {
 | 
			
		||||
                this.seckillTimeList = response.data;
 | 
			
		||||
            });
 | 
			
		||||
        },
 | 
			
		||||
        /** 取消按钮 */
 | 
			
		||||
        cancel() {
 | 
			
		||||
            this.open = false;
 | 
			
		||||
            this.reset();
 | 
			
		||||
        },
 | 
			
		||||
        /** 表单重置 */
 | 
			
		||||
        reset() {
 | 
			
		||||
            this.form = {
 | 
			
		||||
                id: undefined,
 | 
			
		||||
                name: undefined,
 | 
			
		||||
                status: undefined,
 | 
			
		||||
                remark: undefined,
 | 
			
		||||
                startTime: undefined,
 | 
			
		||||
                endTime: undefined,
 | 
			
		||||
                sort: undefined,
 | 
			
		||||
                timeIds: [],
 | 
			
		||||
                totalPrice: undefined,
 | 
			
		||||
                skuIds: [],
 | 
			
		||||
                products: [],
 | 
			
		||||
            };
 | 
			
		||||
            this.resetForm("form");
 | 
			
		||||
        },
 | 
			
		||||
        /** 搜索按钮操作 */
 | 
			
		||||
        handleQuery() {
 | 
			
		||||
            this.queryParams.pageNo = 1;
 | 
			
		||||
            this.getList();
 | 
			
		||||
        },
 | 
			
		||||
        /** 重置按钮操作 */
 | 
			
		||||
        resetQuery() {
 | 
			
		||||
            this.resetForm("queryForm");
 | 
			
		||||
            this.handleQuery();
 | 
			
		||||
        },
 | 
			
		||||
        /**打开秒杀场次管理页面 */
 | 
			
		||||
        openSeckillTime() {
 | 
			
		||||
            this.$tab.openPage("秒杀场次管理", "/promotion/seckill-time");
 | 
			
		||||
        },
 | 
			
		||||
        /** 新增按钮操作 */
 | 
			
		||||
        handleAdd() {
 | 
			
		||||
            this.reset();
 | 
			
		||||
            this.open = true;
 | 
			
		||||
            this.title = "添加秒杀活动";
 | 
			
		||||
        },
 | 
			
		||||
        /** 修改按钮操作 */
 | 
			
		||||
        handleUpdate(row) {
 | 
			
		||||
            this.reset();
 | 
			
		||||
            const id = row.id;
 | 
			
		||||
            getSeckillActivity(id).then(response => {
 | 
			
		||||
                this.form = response.data;
 | 
			
		||||
                // 修改数据
 | 
			
		||||
                this.form.startAndEndTime = [response.data.startTime, response.data.endTime];
 | 
			
		||||
                this.form.skuIds = response.data.products.map(item => item.skuId);
 | 
			
		||||
                this.form.products.forEach(product => {
 | 
			
		||||
                    // 获得对应的 SKU 信息
 | 
			
		||||
                    const sku = this.productSkus.find(item => item.id === product.skuId);
 | 
			
		||||
                    if (!sku) {
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                    // 设置商品信息
 | 
			
		||||
                    product.name = sku.name;
 | 
			
		||||
                    product.spuName = sku.spuName;
 | 
			
		||||
                    product.price = sku.price;
 | 
			
		||||
                    product.productStock = sku.stock;
 | 
			
		||||
                    this.$set(product, 'seckillStock', product.stock);
 | 
			
		||||
                    product.seckillPrice = product.seckillPrice !== undefined ? product.seckillPrice / 100 : undefined;
 | 
			
		||||
 | 
			
		||||
                });
 | 
			
		||||
                // 打开弹窗
 | 
			
		||||
                this.open = true;
 | 
			
		||||
                this.title = "修改限时折扣活动";
 | 
			
		||||
            })
 | 
			
		||||
        },
 | 
			
		||||
        /** 提交按钮 */
 | 
			
		||||
        submitForm() {
 | 
			
		||||
            this.$refs["form"].validate(valid => {
 | 
			
		||||
                if (!valid) {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                // 处理数据
 | 
			
		||||
                const data = deepClone(this.form);
 | 
			
		||||
                data.startTime = this.form.startAndEndTime[0];
 | 
			
		||||
                data.endTime = this.form.startAndEndTime[1];
 | 
			
		||||
                data.products.forEach(product => {
 | 
			
		||||
                    product.stock = product.seckillStock;
 | 
			
		||||
                    product.seckillPrice = product.seckillPrice !== undefined ? product.seckillPrice * 100 : undefined;
 | 
			
		||||
                });
 | 
			
		||||
                // 修改的提交
 | 
			
		||||
                if (this.form.id != null) {
 | 
			
		||||
                    updateSeckillActivity(data).then(response => {
 | 
			
		||||
                        this.$modal.msgSuccess("修改成功");
 | 
			
		||||
                        this.open = false;
 | 
			
		||||
                        this.getList();
 | 
			
		||||
                    });
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                // 添加的提交
 | 
			
		||||
                createSeckillActivity(data).then(response => {
 | 
			
		||||
                    this.$modal.msgSuccess("新增成功");
 | 
			
		||||
                    this.open = false;
 | 
			
		||||
                    this.getList();
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
        },
 | 
			
		||||
        /** 关闭按钮操作 */
 | 
			
		||||
        handleClose(row) {
 | 
			
		||||
            const id = row.id;
 | 
			
		||||
            this.$modal.confirm('是否确认关闭秒杀活动编号为"' + id + '"的数据项?').then(function () {
 | 
			
		||||
                return closeSeckillActivity(id);
 | 
			
		||||
            }).then(() => {
 | 
			
		||||
                this.getList();
 | 
			
		||||
                this.$modal.msgSuccess("关闭成功");
 | 
			
		||||
            }).catch(() => { });
 | 
			
		||||
        },
 | 
			
		||||
        /** 删除按钮操作 */
 | 
			
		||||
        handleDelete(row) {
 | 
			
		||||
            const id = row.id;
 | 
			
		||||
            this.$modal.confirm('是否确认删除秒杀活动编号为"' + id + '"的数据项?').then(function () {
 | 
			
		||||
                return deleteSeckillActivity(id);
 | 
			
		||||
            }).then(() => {
 | 
			
		||||
                this.getList();
 | 
			
		||||
                this.$modal.msgSuccess("删除成功");
 | 
			
		||||
            }).catch(() => { });
 | 
			
		||||
        },
 | 
			
		||||
        /** 批量修改商品秒杀价,秒杀库存,每人限购数量 */
 | 
			
		||||
        batchEditProduct(editType) {
 | 
			
		||||
            const selectProducts = this.$refs.productsTable.selection;
 | 
			
		||||
            if (selectProducts.length === 0) {
 | 
			
		||||
                this.$modal.msgError("请选择需要修改的商品");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            let promptTitle = '请输入';
 | 
			
		||||
            let regularPattern = /^[\s\S]*.*[^\s][\s\S]*$/; // 判断非空,且非空格
 | 
			
		||||
            //限购数
 | 
			
		||||
            if (editType === 'limitBuyCount') {
 | 
			
		||||
                promptTitle = '限购数';
 | 
			
		||||
                regularPattern = /^[0-9]*$/; //数字
 | 
			
		||||
            }
 | 
			
		||||
            //秒杀价
 | 
			
		||||
            if (editType === 'seckillPrice') {
 | 
			
		||||
                promptTitle = '秒杀价(元)';
 | 
			
		||||
                regularPattern = /^[0-9]+(\.[0-9]{1,2})?$/; // 有一位或两位小数的正数
 | 
			
		||||
            }
 | 
			
		||||
            //秒杀库存
 | 
			
		||||
            if (editType === 'seckillStock') {
 | 
			
		||||
                promptTitle = '秒杀库存';
 | 
			
		||||
                regularPattern = /^[0-9]*$/; //数字
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.$prompt(promptTitle, '提示', {
 | 
			
		||||
                confirmButtonText: '保存',
 | 
			
		||||
                cancelButtonText: '取消',
 | 
			
		||||
                inputPattern: regularPattern,
 | 
			
		||||
                inputErrorMessage: promptTitle + '格式不正确'
 | 
			
		||||
            }).then(({ value }) => {
 | 
			
		||||
                if (editType === 'limitBuyCount') {
 | 
			
		||||
                    selectProducts.forEach((item) => {
 | 
			
		||||
                        item.limitBuyCount = value;
 | 
			
		||||
                    })
 | 
			
		||||
                }
 | 
			
		||||
                if (editType === 'seckillPrice') {
 | 
			
		||||
                    selectProducts.forEach((item) => {
 | 
			
		||||
                        item.seckillPrice = value;
 | 
			
		||||
                    })
 | 
			
		||||
                }
 | 
			
		||||
                if (editType === 'seckillStock') {
 | 
			
		||||
                    selectProducts.forEach((item) => {
 | 
			
		||||
                        item.seckillStock = value;
 | 
			
		||||
                    })
 | 
			
		||||
                }
 | 
			
		||||
            }).catch();
 | 
			
		||||
        },
 | 
			
		||||
        /** 当 Form 的 SKU 发生变化时 */
 | 
			
		||||
        changeFormSku(skuIds) {
 | 
			
		||||
            // 处理【新增】
 | 
			
		||||
            skuIds.forEach(skuId => {
 | 
			
		||||
                // 获得对应的 SKU 信息
 | 
			
		||||
                const sku = this.productSkus.find(item => item.id === skuId);
 | 
			
		||||
                if (!sku) {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                // 判断已存在,直接跳过
 | 
			
		||||
                const product = this.form.products.find(item => item.skuId === skuId);
 | 
			
		||||
                if (product) {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                this.form.products.push({
 | 
			
		||||
                    skuId: sku.id,
 | 
			
		||||
                    name: sku.name,
 | 
			
		||||
                    price: sku.price,
 | 
			
		||||
                    productStock: sku.stock,
 | 
			
		||||
                    spuId: sku.spuId,
 | 
			
		||||
                    spuName: sku.spuName,
 | 
			
		||||
                    limitBuyCount: 1,
 | 
			
		||||
                    seckillStock: sku.stock,
 | 
			
		||||
                    seckillPrice: sku.price,
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
            // 处理【移除】
 | 
			
		||||
            this.form.products.map((product, index) => {
 | 
			
		||||
                if (!skuIds.includes(product.skuId)) {
 | 
			
		||||
                    this.form.products.splice(index, 1);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        },
 | 
			
		||||
        /** 移除 Form 的 SKU */
 | 
			
		||||
        removeFormSku(skuId) {
 | 
			
		||||
            this.form.skuIds.map((id, index) => {
 | 
			
		||||
                if (skuId === id) {
 | 
			
		||||
                    this.form.skuIds.splice(index, 1);
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            this.changeFormSku(this.form.skuIds);
 | 
			
		||||
        },
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,198 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
          v-hasPermi="['promotion:seckill-time:create']">新增秒杀时段</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="秒杀时段名称" align="center" prop="name" />
 | 
			
		||||
      <el-table-column label="开始时间点" align="center" prop="startTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ scope.row.startTime }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="结束时间点" align="center" prop="endTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ scope.row.endTime }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="秒杀活动数量" align="center" prop="seckillActivityCount" />
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-view" @click="handleOpenSeckillActivity(scope.row)">
 | 
			
		||||
            查看秒杀活动</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
            v-hasPermi="['promotion:seckill-time:update']">修改</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
            v-hasPermi="['promotion:seckill-time:delete']">删除</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="600px" v-dialogDrag append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="140px">
 | 
			
		||||
        <el-form-item label="秒杀场次名称" prop="name">
 | 
			
		||||
          <el-input v-model="form.name" placeholder="请输入秒杀时段名称" clearable />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="秒杀时间段" prop="startAndEndTime">
 | 
			
		||||
          <el-time-picker is-range v-model="form.startAndEndTime" range-separator="至" start-placeholder="开始时间"
 | 
			
		||||
            end-placeholder="结束时间" placeholder="选择时间范围" value-format="HH:mm:ss">
 | 
			
		||||
          </el-time-picker>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { createSeckillTime, updateSeckillTime, deleteSeckillTime, getSeckillTime, getSeckillTimePage, exportSeckillTimeExcel, getSeckillTimeList } from "@/api/mall/promotion/seckillTime";
 | 
			
		||||
import router from "@/router";
 | 
			
		||||
import { deepClone } from "@/utils";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "PromotionSeckillTime",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 导出遮罩层
 | 
			
		||||
      exportLoading: false,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      // total: 0,
 | 
			
		||||
      // 秒杀时段列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {},
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        name: [{ required: true, message: "秒杀时段名称不能为空", trigger: "blur" }],
 | 
			
		||||
        startAndEndTime: [{ required: true, message: "秒杀时间段不能为空", trigger: "blur" }],
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getSeckillTimeList().then(response => {
 | 
			
		||||
        this.list = response.data;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        startAndEndTime: undefined,
 | 
			
		||||
        startTime: undefined,
 | 
			
		||||
        endTime: undefined,
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /**查看当前秒杀时段的秒杀活动 */
 | 
			
		||||
    handleOpenSeckillActivity(row) {
 | 
			
		||||
      router.push({ name: 'SeckillActivity', params: { timeId: row.id } })
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.title = "添加秒杀时段";
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      getSeckillTime(id).then(response => {
 | 
			
		||||
        response.data.startAndEndTime = [response.data.startTime, response.data.endTime]
 | 
			
		||||
        this.form = response.data;
 | 
			
		||||
        this.open = true;
 | 
			
		||||
        this.title = "修改秒杀时段";
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        console.log(valid, "是否通过");
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 处理数据
 | 
			
		||||
        const data = deepClone(this.form);
 | 
			
		||||
        data.startTime = this.form.startAndEndTime[0];
 | 
			
		||||
        data.endTime = this.form.startAndEndTime[1];
 | 
			
		||||
        // 修改的提交
 | 
			
		||||
        if (this.form.id != null) {
 | 
			
		||||
          updateSeckillTime(data).then(response => {
 | 
			
		||||
            this.$modal.msgSuccess("修改成功");
 | 
			
		||||
            this.open = false;
 | 
			
		||||
            this.getList();
 | 
			
		||||
          });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 添加的提交
 | 
			
		||||
        createSeckillTime(data).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("新增成功");
 | 
			
		||||
          this.open = false;
 | 
			
		||||
          this.getList();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认删除秒杀时段编号为"' + id + '"的数据项?').then(function () {
 | 
			
		||||
        return deleteSeckillTime(id);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("删除成功");
 | 
			
		||||
      }).catch(() => { });
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,229 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="商品名称" prop="spuName">
 | 
			
		||||
        <el-input v-model="queryParams.spuName" placeholder="请输入商品 SPU 名称" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="退款编号" prop="no">
 | 
			
		||||
        <el-input v-model="queryParams.no" placeholder="请输入退款编号" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="订单编号" prop="orderNo">
 | 
			
		||||
        <el-input v-model="queryParams.orderNo" placeholder="请输入订单编号" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="售后状态" prop="status">
 | 
			
		||||
        <el-select v-model="queryParams.status" placeholder="请选择售后状态" clearable size="small">
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.TRADE_AFTER_SALE_STATUS)"
 | 
			
		||||
                     :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="售后方式" prop="way">
 | 
			
		||||
        <el-select v-model="queryParams.way" placeholder="请选择售后方式" clearable size="small">
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.TRADE_AFTER_SALE_WAY)"
 | 
			
		||||
                     :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="售后类型" prop="type">
 | 
			
		||||
        <el-select v-model="queryParams.type" placeholder="请选择售后类型" clearable size="small">
 | 
			
		||||
          <el-option v-for="dict in this.getDictDatas(DICT_TYPE.TRADE_AFTER_SALE_TYPE)"
 | 
			
		||||
                     :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
 | 
			
		||||
                        :picker-options="datePickerOptions" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- Tab 选项:真正的内容在 Table -->
 | 
			
		||||
    <el-tabs v-model="activeTab" type="card" @tab-click="tabClick" style="margin-top: -40px;">
 | 
			
		||||
      <el-tab-pane v-for="tab in statusTabs" :key="tab.value" :label="tab.label" :name="tab.value" />
 | 
			
		||||
    </el-tabs>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="退款编号" align="center" prop="no" />
 | 
			
		||||
      <el-table-column label="订单编号" align="center" prop="orderNo" /> <!-- TODO 芋艿:未来要加个订单链接 -->
 | 
			
		||||
      <el-table-column label="商品信息" align="center" prop="spuName" width="auto" min-width="300">
 | 
			
		||||
        <!-- TODO @小红:样式不太对,辛苦改改 -->
 | 
			
		||||
<!--        <div v-slot="{ row }" class="goods-info">-->
 | 
			
		||||
<!--          <img :src="row.picUrl"/>-->
 | 
			
		||||
<!--          <span class="ellipsis-2" :title="row.name">{{row.name}}</span>-->
 | 
			
		||||
<!--        </div>-->
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="订单金额" align="center" prop="refundPrice">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>¥{{ (scope.row.refundPrice / 100.0).toFixed(2) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="买家" align="center" prop="user.nickname" /> <!-- TODO 芋艿:未来要加个会员链接 -->
 | 
			
		||||
      <el-table-column label="申请时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="售后状态" align="center">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.TRADE_AFTER_SALE_STATUS" :value="scope.row.status" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="售后方式" align="center">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.TRADE_AFTER_SALE_WAY" :value="scope.row.way" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-thumb"
 | 
			
		||||
                     >处理退款</el-button>
 | 
			
		||||
<!--      @click="handleUpdate(scope.row)"    v-hasPermi="['trade:after-sale:update']"-->
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { getAfterSalePage } from "@/api/mall/trade/afterSale";
 | 
			
		||||
import { datePickerOptions } from "@/utils/constants";
 | 
			
		||||
import { DICT_TYPE, getDictDatas } from "@/utils/dict";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "TradeAfterSale",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 导出遮罩层
 | 
			
		||||
      exportLoading: false,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 交易售后列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        no: null,
 | 
			
		||||
        status: null,
 | 
			
		||||
        orderNo: null,
 | 
			
		||||
        spuName: null,
 | 
			
		||||
        createTime: [],
 | 
			
		||||
        way: null,
 | 
			
		||||
        type: null,
 | 
			
		||||
      },
 | 
			
		||||
      // Tab 筛选
 | 
			
		||||
      activeTab: 'all',
 | 
			
		||||
      statusTabs: [{
 | 
			
		||||
        label: '全部',
 | 
			
		||||
        value: 'all'
 | 
			
		||||
      }],
 | 
			
		||||
      // 静态变量
 | 
			
		||||
      datePickerOptions: datePickerOptions
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
    // 设置 statuses 过滤
 | 
			
		||||
    for (const dict of getDictDatas(DICT_TYPE.TRADE_AFTER_SALE_STATUS)) {
 | 
			
		||||
      this.statusTabs.push({
 | 
			
		||||
        label: dict.label,
 | 
			
		||||
        value: dict.value
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getAfterSalePage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.activeTab = this.queryParams.status ? this.queryParams.status : 'all'; // 处理 tab
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.activeTab = 'all'; // 处理 tab
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** tab 切换 */
 | 
			
		||||
    tabClick(tab) {
 | 
			
		||||
      this.queryParams.status = tab.name === 'all' ? undefined : tab.name;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    goToDetail (row) {
 | 
			
		||||
      this.$router.push({ path: '/mall/trade/order/detail', query: { orderNo: row.orderNo }})
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
::v-deep .table-wrapper {
 | 
			
		||||
  .el-table__row{
 | 
			
		||||
    .el-table__cell {
 | 
			
		||||
      border-bottom: none;
 | 
			
		||||
      .cell{
 | 
			
		||||
        .el-table {
 | 
			
		||||
          .el-table__row {
 | 
			
		||||
            >.el-table__cell {
 | 
			
		||||
              .goods-info{
 | 
			
		||||
                display: flex;
 | 
			
		||||
                img{
 | 
			
		||||
                  margin-right: 10px;
 | 
			
		||||
                  width: 60px;
 | 
			
		||||
                  height: 60px;
 | 
			
		||||
                  border: 1px solid #e2e2e2;
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
              .ellipsis-2 {
 | 
			
		||||
                display: -webkit-box;
 | 
			
		||||
                overflow: hidden;
 | 
			
		||||
                text-overflow: ellipsis;
 | 
			
		||||
                white-space: normal;
 | 
			
		||||
                -webkit-line-clamp: 2; /* 要显示的行数 */
 | 
			
		||||
                -webkit-box-orient: vertical;
 | 
			
		||||
                word-break: break-all;
 | 
			
		||||
                line-height: 22px !important;
 | 
			
		||||
                max-height: 44px !important;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,279 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container order-detail-page">
 | 
			
		||||
    <!-- 订单信息 -->
 | 
			
		||||
    <el-descriptions title="订单信息">
 | 
			
		||||
      <el-descriptions-item label="订单号">{{ order.no }}</el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="配送方式">物流配送</el-descriptions-item> <!-- TODO 芋艿:待实现 -->
 | 
			
		||||
      <el-descriptions-item label="营销活动">物流配送</el-descriptions-item> <!-- TODO 芋艿:待实现 -->
 | 
			
		||||
      <el-descriptions-item label="订单类型">
 | 
			
		||||
        <dict-tag :type="DICT_TYPE.TRADE_ORDER_TYPE" :value="order.type" />
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="收货人">{{ order.receiverName }}</el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="买家留言">{{ order.userRemark }}</el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="订单来源">
 | 
			
		||||
        <dict-tag :type="DICT_TYPE.TERMINAL" :value="order.terminal" />
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="联系电话">{{ order.receiverMobile }}</el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="商家备注">{{ order.remark }}</el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="支付单号">{{ order.payOrderId }}</el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="付款方式">
 | 
			
		||||
        <dict-tag :type="DICT_TYPE.PAY_CHANNEL_CODE_TYPE" :value="order.payChannelCode" />
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="买家">{{ order.user.nickname }}</el-descriptions-item> <!-- TODO 芋艿:待实现:跳转会员 -->
 | 
			
		||||
      <el-descriptions-item label="收货地址">
 | 
			
		||||
        {{ order.receiverAreaName }}   {{ order.receiverDetailAddress }}  
 | 
			
		||||
        <el-link v-clipboard:copy="order.receiverAreaName + ' ' + order.receiverDetailAddress"
 | 
			
		||||
                 v-clipboard:success="clipboardSuccess" icon="el-icon-document-copy" type="primary"/>
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
    </el-descriptions>
 | 
			
		||||
 | 
			
		||||
    <!-- 订单状态 -->
 | 
			
		||||
    <el-descriptions title="订单状态" :column="1">
 | 
			
		||||
      <el-descriptions-item label="订单状态">
 | 
			
		||||
        <dict-tag :type="DICT_TYPE.TRADE_ORDER_STATUS" :value="order.status" />
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label-class-name="no-colon">
 | 
			
		||||
        <el-button type="primary" size="small">调整价格</el-button>  <!-- TODO 芋艿:待实现 -->
 | 
			
		||||
        <el-button type="primary" size="small">备注</el-button> <!-- TODO 芋艿:待实现 -->
 | 
			
		||||
        <el-button type="primary" size="small">发货</el-button> <!-- TODO 芋艿:待实现 -->
 | 
			
		||||
        <el-button type="primary" size="small">关闭订单</el-button>  <!-- TODO 芋艿:待实现 -->
 | 
			
		||||
        <el-button type="primary" size="small">修改地址</el-button>  <!-- TODO 芋艿:待实现 -->
 | 
			
		||||
        <el-button type="primary" size="small">打印电子面单</el-button>  <!-- TODO 芋艿:待实现 -->
 | 
			
		||||
        <el-button type="primary" size="small">打印发货单</el-button>  <!-- TODO 芋艿:待实现 -->
 | 
			
		||||
        <el-button type="primary" size="small">确认收货</el-button>  <!-- TODO 芋艿:待实现 -->
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="提醒" label-style="color: red">
 | 
			
		||||
        买家付款成功后,货款将直接进入您的商户号(微信、支付宝)<br />
 | 
			
		||||
        请及时关注你发出的包裹状态,确保可以配送至买家手中 <br />
 | 
			
		||||
        如果买家表示没收到货或货物有问题,请及时联系买家处理,友好协商
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
    </el-descriptions>
 | 
			
		||||
 | 
			
		||||
    <!-- 物流信息 TODO -->
 | 
			
		||||
 | 
			
		||||
    <!-- 商品信息 -->
 | 
			
		||||
    <el-descriptions title="商品信息" :column="6">
 | 
			
		||||
      <el-descriptions-item labelClassName="no-colon">
 | 
			
		||||
        <el-table :data="order.items" border>
 | 
			
		||||
          <el-table-column prop="spuName" label="商品" width="700">
 | 
			
		||||
            <template v-slot="{ row }">
 | 
			
		||||
              {{row.spuName}}
 | 
			
		||||
              <el-tag size="medium" v-for="property in row.properties" :key="property.propertyId">
 | 
			
		||||
                {{property.propertyName}}:{{property.valueName}}</el-tag>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="originalUnitPrice" label="单价(元)" width="180">
 | 
			
		||||
            <template v-slot="{ row }">
 | 
			
		||||
              ¥{{ (row.originalUnitPrice / 100.0).toFixed(2) }}
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="count" label="数量" width="180"/>
 | 
			
		||||
          <el-table-column prop="originalPrice" label="小计(元)" width="180">
 | 
			
		||||
            <template v-slot="{ row }">
 | 
			
		||||
              ¥{{ (row.originalPrice / 100.0).toFixed(2) }}
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="afterSaleStatus" label="退款状态">
 | 
			
		||||
            <template v-slot="{ row }">
 | 
			
		||||
              <dict-tag :type="DICT_TYPE.TRADE_ORDER_ITEM_AFTER_SALE_STATUS" :value="row.afterSaleStatus" />
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table>
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item v-for="(item,index) in 5" label-class-name="no-colon" :key="item" /> <!-- 占位 -->
 | 
			
		||||
      <el-descriptions-item label="商品总额">¥{{ (order.originalPrice / 100.0).toFixed(2) }}</el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="运费金额">¥{{ (order.deliveryPrice / 100.0).toFixed(2) }}</el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="订单调价">¥{{ (order.adjustPrice / 100.0).toFixed(2) }}</el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="商品优惠" label-style="color: red">
 | 
			
		||||
        ¥{{ ((order.originalPrice - order.originalPrice) / 100.0).toFixed(2) }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="订单优惠" label-style="color: red">
 | 
			
		||||
        ¥{{ (order.discountPrice / 100.0).toFixed(2) }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="积分抵扣" label-style="color: red">
 | 
			
		||||
        ¥{{ (order.pointPrice / 100.0).toFixed(2) }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item v-for="(item,index) in 5" label-class-name="no-colon" :key="item" /> <!-- 占位 -->
 | 
			
		||||
      <el-descriptions-item label="应付金额">
 | 
			
		||||
        ¥{{ (order.payPrice / 100.0).toFixed(2) }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
    </el-descriptions>
 | 
			
		||||
 | 
			
		||||
    <template v-for="(group, index) in detailGroups">
 | 
			
		||||
      <el-descriptions v-bind="group.groupProps" :key="`group_${index}`" :title="group.title">
 | 
			
		||||
 | 
			
		||||
        <!-- 订单操作日志 -->
 | 
			
		||||
        <el-descriptions-item  v-if="group.key === 'orderLog'" labelClassName="no-colon">
 | 
			
		||||
          <el-timeline>
 | 
			
		||||
            <el-timeline-item
 | 
			
		||||
              v-for="(activity, index) in detailInfo[group.key]"
 | 
			
		||||
              :key="index"
 | 
			
		||||
              :timestamp="activity.timestamp"
 | 
			
		||||
            >
 | 
			
		||||
              {{activity.content}}
 | 
			
		||||
            </el-timeline-item>
 | 
			
		||||
          </el-timeline>
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
 | 
			
		||||
        <!-- 物流信息 -->
 | 
			
		||||
        <el-descriptions-item v-if="group.key === 'expressInfo'" labelClassName="no-colon">
 | 
			
		||||
          <el-tabs type="card">
 | 
			
		||||
            <!-- 循环包裹物流信息 -->
 | 
			
		||||
            <el-tab-pane v-for="(pkgInfo, pInIdx) in detailInfo[group.key]" :key="`pkgInfo_${pInIdx}`" :label="pkgInfo.label">
 | 
			
		||||
              <!-- 包裹详情 -->
 | 
			
		||||
              <el-descriptions>
 | 
			
		||||
                <el-descriptions-item v-for="(pkgChild, pkgCIdx) in group.children" v-bind="pkgChild.childProps" :key="`pkgChild_${pkgCIdx}`" :label="pkgChild.label">
 | 
			
		||||
                  <!-- 包裹商品列表 -->
 | 
			
		||||
                  <template v-if="pkgChild.valueKey === 'goodsList' && pkgInfo[pkgChild.valueKey]">
 | 
			
		||||
                    <div v-for="(goodInfo, goodInfoIdx) in pkgInfo[pkgChild.valueKey]" :key="`goodInfo_${goodInfoIdx}`" style="display: flex;">
 | 
			
		||||
                      <el-image
 | 
			
		||||
                        style="width: 100px;height: 100px;flex: none"
 | 
			
		||||
                        :src="goodInfo.imgUrl">
 | 
			
		||||
                      </el-image>
 | 
			
		||||
                      <el-descriptions :column="1">
 | 
			
		||||
                        <el-descriptions-item labelClassName="no-colon">{{goodInfo.name}}</el-descriptions-item>
 | 
			
		||||
                        <el-descriptions-item label="数量">{{goodInfo.count}}</el-descriptions-item>
 | 
			
		||||
                      </el-descriptions>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </template>
 | 
			
		||||
 | 
			
		||||
                  <!-- 包裹物流详情 -->
 | 
			
		||||
                  <el-timeline v-else-if="pkgChild.valueKey==='wlxq'">
 | 
			
		||||
                    <el-timeline-item
 | 
			
		||||
                      v-for="(activity, index) in pkgInfo[pkgChild.valueKey]"
 | 
			
		||||
                      :key="index"
 | 
			
		||||
                      :timestamp="activity.timestamp"
 | 
			
		||||
                    >
 | 
			
		||||
                      {{activity.content}}
 | 
			
		||||
                    </el-timeline-item>
 | 
			
		||||
                  </el-timeline>
 | 
			
		||||
 | 
			
		||||
                  <template v-else>
 | 
			
		||||
                    {{pkgInfo[pkgChild.valueKey]}}
 | 
			
		||||
                  </template>
 | 
			
		||||
                </el-descriptions-item>
 | 
			
		||||
              </el-descriptions>
 | 
			
		||||
            </el-tab-pane>
 | 
			
		||||
          </el-tabs>
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
      </el-descriptions>
 | 
			
		||||
    </template>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { getOrderDetail } from "@/api/mall/trade/order";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "TradeOrderDetail",
 | 
			
		||||
  data () {
 | 
			
		||||
    return {
 | 
			
		||||
      detailGroups: [
 | 
			
		||||
        {
 | 
			
		||||
          title: '物流信息',
 | 
			
		||||
          key: 'expressInfo',
 | 
			
		||||
          children: [
 | 
			
		||||
            { label: '发货时间', valueKey: 'fhsj'},
 | 
			
		||||
            { label: '物流公司', valueKey: 'wlgs'},
 | 
			
		||||
            { label: '运单号', valueKey: 'ydh'},
 | 
			
		||||
            { label: '物流状态', valueKey: 'wlzt', childProps: { span: 3 }},
 | 
			
		||||
            { label: '物流详情', valueKey: 'wlxq'}
 | 
			
		||||
          ]
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          title: '订单操作日志',
 | 
			
		||||
          key: 'orderLog'
 | 
			
		||||
        }
 | 
			
		||||
      ],
 | 
			
		||||
      detailInfo: {
 | 
			
		||||
        expressInfo: [ // 物流信息
 | 
			
		||||
          {
 | 
			
		||||
            label: '包裹1',
 | 
			
		||||
            name: 'bg1',
 | 
			
		||||
            fhsj: '2022-11-03 16:50:45',
 | 
			
		||||
            wlgs: '极兔',
 | 
			
		||||
            ydh: '2132123',
 | 
			
		||||
            wlzt: '不支持此快递公司',
 | 
			
		||||
            wlxq:  [
 | 
			
		||||
              {
 | 
			
		||||
                content: '正在派送途中,请您准备签收(派件人:王涛,电话:13854563814)',
 | 
			
		||||
                timestamp: '2018-04-15 15:00:16'
 | 
			
		||||
              },
 | 
			
		||||
              {
 | 
			
		||||
                content: '快件到达 【烟台龙口东江村委营业点】',
 | 
			
		||||
                timestamp: '2018-04-13 14:54:19'
 | 
			
		||||
              },
 | 
			
		||||
              {
 | 
			
		||||
                content: '快件已发车',
 | 
			
		||||
                timestamp: '2018-04-11 12:55:52'
 | 
			
		||||
              },
 | 
			
		||||
              {
 | 
			
		||||
                content: '快件已发车',
 | 
			
		||||
                timestamp: '2018-04-11 12:55:52'
 | 
			
		||||
              },
 | 
			
		||||
              {
 | 
			
		||||
                content: '快件已发车',
 | 
			
		||||
                timestamp: '2018-04-11 12:55:52'
 | 
			
		||||
              }
 | 
			
		||||
            ]
 | 
			
		||||
          }
 | 
			
		||||
        ],
 | 
			
		||||
        orderLog: [ // 订单操作日志
 | 
			
		||||
          {
 | 
			
		||||
            content: '买家【乌鸦】关闭了订单',
 | 
			
		||||
            timestamp: '2018-04-15 15:00:16'
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            content: '买家【乌鸦】下单了',
 | 
			
		||||
            timestamp: '2018-04-15 15:00:16'
 | 
			
		||||
          }
 | 
			
		||||
        ],
 | 
			
		||||
        goodsInfo: [] // 商品详情tableData
 | 
			
		||||
      },
 | 
			
		||||
      order: {
 | 
			
		||||
        items: [],
 | 
			
		||||
        user: {},
 | 
			
		||||
      },
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    getOrderDetail(this.$route.query.id).then(res => {
 | 
			
		||||
      this.order = res.data
 | 
			
		||||
    })
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    clipboardSuccess() {
 | 
			
		||||
      this.$modal.msgSuccess("复制成功");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
  :deep(.el-descriptions){
 | 
			
		||||
    &:not(:nth-child(1)) {
 | 
			
		||||
      margin-top: 20px;
 | 
			
		||||
    }
 | 
			
		||||
    .el-descriptions__title{
 | 
			
		||||
      display: flex;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      &::before{
 | 
			
		||||
        content: '';
 | 
			
		||||
        display: inline-block;
 | 
			
		||||
        margin-right: 10px;
 | 
			
		||||
        width: 3px;
 | 
			
		||||
        height: 20px;
 | 
			
		||||
        background-color: #409EFF;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    .el-descriptions-item__container{
 | 
			
		||||
      margin: 0 10px;
 | 
			
		||||
      .no-colon{
 | 
			
		||||
        margin: 0;
 | 
			
		||||
        &::after{
 | 
			
		||||
          content: ''
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,281 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" />
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <!-- TODO: inline 看看是不是需要; v-show= 那块逻辑还是要的 -->
 | 
			
		||||
    <el-row :gutter="20">
 | 
			
		||||
      <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
        <el-col :span="6" :xs="24">
 | 
			
		||||
          <el-form-item label="搜索方式" prop="searchValue">
 | 
			
		||||
            <el-input v-model="queryParams.searchValue" style="width: 240px">
 | 
			
		||||
              <el-select v-model="queryParams.searchType" slot="prepend" style="width: 100px">
 | 
			
		||||
                <el-option v-for="dict in searchTypes" :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
              </el-select>
 | 
			
		||||
            </el-input>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </el-col>
 | 
			
		||||
        <el-col :span="6" :xs="24">
 | 
			
		||||
          <el-form-item label="订单类型" prop="type">
 | 
			
		||||
            <el-select v-model="queryParams.type" clearable style="width: 240px">
 | 
			
		||||
              <el-option v-for="dict in this.getDictDatas(DICT_TYPE.TRADE_ORDER_TYPE)"
 | 
			
		||||
                         :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
            </el-select>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </el-col>
 | 
			
		||||
        <el-col :span="6" :xs="24">
 | 
			
		||||
          <el-form-item label="订单状态" prop="status">
 | 
			
		||||
            <el-select v-model="queryParams.status" clearable style="width: 240px">
 | 
			
		||||
              <el-option v-for="dict in this.getDictDatas(DICT_TYPE.TRADE_ORDER_STATUS)"
 | 
			
		||||
                         :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
            </el-select>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </el-col>
 | 
			
		||||
        <el-col :span="6" :xs="24">
 | 
			
		||||
          <el-form-item label="订单来源" prop="terminal">
 | 
			
		||||
            <el-select v-model="queryParams.terminal" clearable style="width: 240px">
 | 
			
		||||
              <el-option v-for="dict in this.getDictDatas(DICT_TYPE.TERMINAL)"
 | 
			
		||||
                         :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
            </el-select>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </el-col>
 | 
			
		||||
        <el-col :span="6" :xs="24">
 | 
			
		||||
          <el-form-item label="支付方式" prop="payChannelCode">
 | 
			
		||||
            <el-select v-model="queryParams.payChannelCode" clearable style="width: 240px">
 | 
			
		||||
              <el-option v-for="dict in this.getDictDatas(DICT_TYPE.PAY_CHANNEL_CODE_TYPE)"
 | 
			
		||||
                         :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
            </el-select>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </el-col>
 | 
			
		||||
        <el-col :span="6" :xs="24">
 | 
			
		||||
          <el-form-item label="下单时间" prop="createTime">
 | 
			
		||||
            <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                            range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"
 | 
			
		||||
                            :picker-options="datePickerOptions" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </el-col>
 | 
			
		||||
        <el-col :span="6" :xs="24" style="line-height: 32px">
 | 
			
		||||
          <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
 | 
			
		||||
          <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
 | 
			
		||||
        </el-col>
 | 
			
		||||
      </el-form>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- tab切换 -->
 | 
			
		||||
    <!-- TODO @小程:看看能不能往上挪 -40px,和【隐藏搜索】【刷新】对齐 -->
 | 
			
		||||
    <el-tabs v-model="activeTab" type="card" @tab-click="tabClick">
 | 
			
		||||
      <el-tab-pane v-for="tab in statusTabs" :key="tab.value" :label="tab.label" :name="tab.value">
 | 
			
		||||
        <!-- 列表 -->
 | 
			
		||||
        <el-table v-loading="loading" :data="list" :show-header="false" class="order-table">
 | 
			
		||||
          <el-table-column>
 | 
			
		||||
            <template v-slot="{ row }">
 | 
			
		||||
              <el-row type="flex" align="middle">
 | 
			
		||||
                <el-col :span="5">
 | 
			
		||||
                  订单号:{{row.no}}
 | 
			
		||||
                  <el-popover title="支付单号:" :content="row.payOrderId + ''" placement="right" width="200" trigger="click">
 | 
			
		||||
                    <el-button slot="reference" type="text">更多</el-button>
 | 
			
		||||
                  </el-popover>
 | 
			
		||||
                </el-col>
 | 
			
		||||
                <el-col :span="5">下单时间:{{ parseTime(row.createTime) }}</el-col>
 | 
			
		||||
                <el-col :span="4">订单来源:
 | 
			
		||||
                  <dict-tag :type="DICT_TYPE.TERMINAL" :value="row.terminal" />
 | 
			
		||||
                </el-col>
 | 
			
		||||
                <el-col :span="4">支付方式:
 | 
			
		||||
                  <dict-tag v-if="row.payChannelCode" :type="DICT_TYPE.PAY_CHANNEL_CODE_TYPE" :value="row.payChannelCode" />
 | 
			
		||||
                  <span v-else>未支付</span>
 | 
			
		||||
                </el-col>
 | 
			
		||||
                <el-col :span="6" align="right">
 | 
			
		||||
                  <el-button type="text" @click="goToDetail(row)">详情</el-button>
 | 
			
		||||
                </el-col>
 | 
			
		||||
              </el-row>
 | 
			
		||||
              <!-- 订单下的商品 -->
 | 
			
		||||
              <el-table :data="row.items" border :show-header="true">
 | 
			
		||||
                <el-table-column label="商品" prop="goods" header-align="center" width="auto" min-width="300">
 | 
			
		||||
                  <template v-slot="{ row, $index }">
 | 
			
		||||
                    <div class="goods-info">
 | 
			
		||||
                      <img :src="row.picUrl"/>
 | 
			
		||||
                      <span class="ellipsis-2" :title="row.spuName">{{row.spuName}}</span>
 | 
			
		||||
                      <!-- TODO @小程:下面是商品属性,想当度一行,放在商品名下面 -->
 | 
			
		||||
                      <el-tag size="medium" v-for="property in row.properties" :key="property.propertyId">
 | 
			
		||||
                        {{property.propertyName}}:{{property.valueName}}</el-tag>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </template>
 | 
			
		||||
                </el-table-column>
 | 
			
		||||
                <el-table-column label="单价(元)/数量" prop="fee" align="center" width="115">
 | 
			
		||||
                  <template v-slot="{ row }">
 | 
			
		||||
                    <div>¥{{ (row.originalUnitPrice / 100.0).toFixed(2) }}</div>
 | 
			
		||||
                    <div>{{row.count}} 件</div>
 | 
			
		||||
                  </template>
 | 
			
		||||
                </el-table-column>
 | 
			
		||||
                <!-- TODO @小程:这里应该是一个订单下,多个商品,只展示订单上的总金额,就是 order.payPrice -->
 | 
			
		||||
                <el-table-column label="实付金额(元)" prop="amount" align="center" width="100"/>
 | 
			
		||||
                <!-- TODO @小程:这里应该是一个订单下,多个商品,只展示订单上的收件信息;使用 order.receiverXXX 开头的字段 -->
 | 
			
		||||
                <el-table-column label="买家/收货人" prop="buyer" header-align="center" width="auto" min-width="300">
 | 
			
		||||
                  <template v-slot="{ row }">
 | 
			
		||||
                    <!-- TODO @芋艿:以后增加一个会员详情界面 -->
 | 
			
		||||
                    <div>{{row.buyer}}</div>
 | 
			
		||||
                    <div>{{row.receiver}}{{row.tel}}</div>
 | 
			
		||||
                    <div class="ellipsis-2" :title="row.address">{{row.address}}</div>
 | 
			
		||||
                  </template>
 | 
			
		||||
                </el-table-column>
 | 
			
		||||
                <!-- TODO @小程:这里应该是一个订单下,多个商品,交易状态是统一的;使用 order.status 字段 -->
 | 
			
		||||
                <el-table-column label="交易状态" prop="status" align="center" width="100"/>
 | 
			
		||||
              </el-table>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table>
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
    </el-tabs>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { getOrderPage } from "@/api/mall/trade/order";
 | 
			
		||||
import { datePickerOptions } from "@/utils/constants";
 | 
			
		||||
import { DICT_TYPE, getDictDatas } from "@/utils/dict";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "TradeOrder",
 | 
			
		||||
  data () {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 导出遮罩层
 | 
			
		||||
      exportLoading: false,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 交易售后列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        searchType: 'no',
 | 
			
		||||
        searchValue: '',
 | 
			
		||||
        type: null,
 | 
			
		||||
        status: null,
 | 
			
		||||
        payChannelCode: null,
 | 
			
		||||
        createTime: [],
 | 
			
		||||
      },
 | 
			
		||||
      // Tab 筛选
 | 
			
		||||
      activeTab: 'all',
 | 
			
		||||
      statusTabs: [{
 | 
			
		||||
        label: '全部',
 | 
			
		||||
        value: 'all'
 | 
			
		||||
      }],
 | 
			
		||||
      // 静态变量
 | 
			
		||||
      datePickerOptions: datePickerOptions,
 | 
			
		||||
      searchTypes: [
 | 
			
		||||
        { label: '订单号', value: 'no' },
 | 
			
		||||
        { label: '会员编号', value: 'userId' },
 | 
			
		||||
        { label: '会员昵称', value: 'userNickname' },
 | 
			
		||||
        { label: '会员手机号', value: 'userMobile' },
 | 
			
		||||
        { label: '收货人姓名', value: 'receiverName' },
 | 
			
		||||
        { label: '收货人手机号码', value: 'receiverMobile' },
 | 
			
		||||
      ],
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
    // 设置 statuses 过滤
 | 
			
		||||
    for (const dict of getDictDatas(DICT_TYPE.TRADE_ORDER_STATUS)) {
 | 
			
		||||
      this.statusTabs.push({
 | 
			
		||||
        label: dict.label,
 | 
			
		||||
        value: dict.value
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getOrderPage({
 | 
			
		||||
        ...this.queryParams,
 | 
			
		||||
        searchType: undefined,
 | 
			
		||||
        searchValue: undefined,
 | 
			
		||||
        no: this.queryParams.searchType === 'no' ? this.queryParams.searchValue : undefined,
 | 
			
		||||
        userId: this.queryParams.searchType === 'userId' ? this.queryParams.searchValue : undefined,
 | 
			
		||||
        userNickname: this.queryParams.searchType === 'userNickname' ? this.queryParams.searchValue : undefined,
 | 
			
		||||
        userMobile: this.queryParams.searchType === 'userMobile' ? this.queryParams.searchValue : undefined,
 | 
			
		||||
        receiverName: this.queryParams.searchType === 'receiverName' ? this.queryParams.searchValue : undefined,
 | 
			
		||||
        receiverMobile: this.queryParams.searchType === 'receiverMobile' ? this.queryParams.searchValue : undefined,
 | 
			
		||||
      }).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.activeTab = this.queryParams.status ? this.queryParams.status : 'all'; // 处理 tab
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** tab 切换 */
 | 
			
		||||
    tabClick(tab) {
 | 
			
		||||
      this.queryParams.status = tab.name === 'all' ? undefined : tab.name;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    goToDetail (row) {
 | 
			
		||||
      this.$router.push({ name: 'TradeOrderDetail', query: { id: row.id }})
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
::v-deep .order-table{
 | 
			
		||||
  border-bottom: none;
 | 
			
		||||
  &::before{
 | 
			
		||||
    height: 0;
 | 
			
		||||
  }
 | 
			
		||||
  .el-table__row{
 | 
			
		||||
    .el-table__cell{
 | 
			
		||||
      border-bottom: none;
 | 
			
		||||
      .cell{
 | 
			
		||||
        .el-table {
 | 
			
		||||
          .el-table__row{
 | 
			
		||||
            >.el-table__cell{
 | 
			
		||||
              .goods-info{
 | 
			
		||||
                display: flex;
 | 
			
		||||
                img{
 | 
			
		||||
                  margin-right: 10px;
 | 
			
		||||
                  width: 60px;
 | 
			
		||||
                  height: 60px;
 | 
			
		||||
                  border: 1px solid #e2e2e2;
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
              .ellipsis-2{
 | 
			
		||||
                display: -webkit-box;
 | 
			
		||||
                overflow: hidden;
 | 
			
		||||
                text-overflow: ellipsis;
 | 
			
		||||
                white-space: normal;
 | 
			
		||||
                -webkit-line-clamp: 2; /* 要显示的行数 */
 | 
			
		||||
                -webkit-box-orient: vertical;
 | 
			
		||||
                word-break: break-all;
 | 
			
		||||
                line-height: 22px !important;
 | 
			
		||||
                max-height: 44px !important;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -21,7 +21,7 @@
 | 
			
		||||
          </el-col>
 | 
			
		||||
          <el-col :span='4'>
 | 
			
		||||
            <div class="blodTip">产品名称</div>
 | 
			
		||||
            <div class="lightTip">{{ orderMsg.productName }}</div>
 | 
			
		||||
            <div class="lightTip" :title='orderMsg.productName'>{{ orderMsg.productName }}</div>
 | 
			
		||||
          </el-col>
 | 
			
		||||
          <el-col :span='4'>
 | 
			
		||||
            <div class="blodTip">产品规格</div>
 | 
			
		||||
@@ -282,6 +282,9 @@ export default {
 | 
			
		||||
      font-weight: 400;
 | 
			
		||||
      color: rgba(102, 102, 102, 0.75);
 | 
			
		||||
      margin-bottom: 12px;
 | 
			
		||||
      white-space: nowrap;
 | 
			
		||||
      overflow: hidden;
 | 
			
		||||
      text-overflow: ellipsis;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,38 +1,21 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container orderMonitoring">
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <search-bar
 | 
			
		||||
      :formConfigs="formConfig"
 | 
			
		||||
      ref="searchBarForm"
 | 
			
		||||
      @headBtnClick="buttonClick"
 | 
			
		||||
    />
 | 
			
		||||
    <search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
 | 
			
		||||
    <el-tabs v-model="activeName" @tab-click="toggleTab">
 | 
			
		||||
      <el-tab-pane label="数据列表" name="dataList"></el-tab-pane>
 | 
			
		||||
      <el-tab-pane label="环形图" name="barChart"></el-tab-pane>
 | 
			
		||||
    </el-tabs>
 | 
			
		||||
    <!-- 表 -->
 | 
			
		||||
    <div v-if="activeName === 'dataList'">
 | 
			
		||||
      <base-table
 | 
			
		||||
        :page="1"
 | 
			
		||||
        :limit="1000000000000"
 | 
			
		||||
        :table-props="tableProps"
 | 
			
		||||
        :table-data="list"
 | 
			
		||||
        :max-height="tableH"
 | 
			
		||||
        row-key="id"
 | 
			
		||||
        :tree-props="{children: 'orderMonitorVOS', hasChildren: 'hasChildren'}"
 | 
			
		||||
      >
 | 
			
		||||
        <method-btn
 | 
			
		||||
          v-if="tableBtn.length"
 | 
			
		||||
          slot="handleBtn"
 | 
			
		||||
          :width="100"
 | 
			
		||||
          label="操作"
 | 
			
		||||
          :method-list="tableBtn"
 | 
			
		||||
          @clickBtn="handleClick"
 | 
			
		||||
        />
 | 
			
		||||
      <base-table :page="1" :limit="1000000000000" :table-props="tableProps" :table-data="list" :max-height="tableH"
 | 
			
		||||
        row-key="id" :tree-props="{ children: 'orderMonitorVOS', hasChildren: 'hasChildren' }">
 | 
			
		||||
        <method-btn v-if="tableBtn.length" slot="handleBtn" :width="100" label="操作" :method-list="tableBtn"
 | 
			
		||||
          @clickBtn="handleClick" />
 | 
			
		||||
      </base-table>
 | 
			
		||||
    </div>
 | 
			
		||||
    <!-- 图 -->
 | 
			
		||||
    <monitoring-ring-charts ref='monitoringRingCharts' v-else :chart-list='chartList'/>
 | 
			
		||||
    <monitoring-ring-charts ref='monitoringRingCharts' v-else :chart-list='chartList' />
 | 
			
		||||
    <!-- <pagination
 | 
			
		||||
      :page.sync="queryParams.pageNo"
 | 
			
		||||
      :limit.sync="queryParams.pageSize"
 | 
			
		||||
@@ -168,65 +151,65 @@ export default {
 | 
			
		||||
      },
 | 
			
		||||
      tableProps,
 | 
			
		||||
      list: [],
 | 
			
		||||
      tableH: this.tableHeight(305),
 | 
			
		||||
      tableH: this.tableHeight(260),
 | 
			
		||||
      total: 0,
 | 
			
		||||
      tableBtn: [
 | 
			
		||||
      this.$auth.hasPermi('base:order-completion-monitoring:orderDet')
 | 
			
		||||
        this.$auth.hasPermi('base:order-completion-monitoring:orderDet')
 | 
			
		||||
          ? {
 | 
			
		||||
              type: 'orderDetail',
 | 
			
		||||
              btnName: '详情',
 | 
			
		||||
              showTip: '订单/工单详情',
 | 
			
		||||
              showParam: {
 | 
			
		||||
                type: '&',
 | 
			
		||||
                data: [
 | 
			
		||||
                  {
 | 
			
		||||
                    type: 'more',
 | 
			
		||||
                    name: 'orderNum',
 | 
			
		||||
                    value: 1
 | 
			
		||||
                  }
 | 
			
		||||
                ]
 | 
			
		||||
              }
 | 
			
		||||
            type: 'orderDetail',
 | 
			
		||||
            btnName: '详情',
 | 
			
		||||
            showTip: '订单/工单详情',
 | 
			
		||||
            showParam: {
 | 
			
		||||
              type: '&',
 | 
			
		||||
              data: [
 | 
			
		||||
                {
 | 
			
		||||
                  type: 'more',
 | 
			
		||||
                  name: 'orderNum',
 | 
			
		||||
                  value: 1
 | 
			
		||||
                }
 | 
			
		||||
              ]
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          : undefined,
 | 
			
		||||
      this.$auth.hasPermi('base:order-completion-monitoring:qualityDet')
 | 
			
		||||
        this.$auth.hasPermi('base:order-completion-monitoring:qualityDet')
 | 
			
		||||
          ? {
 | 
			
		||||
              type: 'qualityDetail',
 | 
			
		||||
              btnName: '质量',
 | 
			
		||||
              showTip: '质量详情',
 | 
			
		||||
              showParam: {
 | 
			
		||||
                type: '&',
 | 
			
		||||
                data: [
 | 
			
		||||
                  {
 | 
			
		||||
                    type: 'more',
 | 
			
		||||
                    name: 'orderNum',
 | 
			
		||||
                    value: 1
 | 
			
		||||
                  },
 | 
			
		||||
                  {
 | 
			
		||||
                    type: 'unequal',
 | 
			
		||||
                    name: 'woIdString',
 | 
			
		||||
                    value: ''
 | 
			
		||||
                  }
 | 
			
		||||
                ]
 | 
			
		||||
              }
 | 
			
		||||
            type: 'qualityDetail',
 | 
			
		||||
            btnName: '质量',
 | 
			
		||||
            showTip: '质量详情',
 | 
			
		||||
            showParam: {
 | 
			
		||||
              type: '&',
 | 
			
		||||
              data: [
 | 
			
		||||
                {
 | 
			
		||||
                  type: 'more',
 | 
			
		||||
                  name: 'orderNum',
 | 
			
		||||
                  value: 1
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                  type: 'unequal',
 | 
			
		||||
                  name: 'woIdString',
 | 
			
		||||
                  value: ''
 | 
			
		||||
                }
 | 
			
		||||
              ]
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          : undefined
 | 
			
		||||
      // this.$auth.hasPermi('base:order-completion-monitoring:sendOut')
 | 
			
		||||
      //     ? {
 | 
			
		||||
      //         type: 'sendOutDetail',
 | 
			
		||||
      //         btnName: '发货',
 | 
			
		||||
      //         showTip: '发货详情',
 | 
			
		||||
      //         showParam: {
 | 
			
		||||
      //           type: '&',
 | 
			
		||||
      //           data: [
 | 
			
		||||
      //             {
 | 
			
		||||
      //               type: 'more',
 | 
			
		||||
      //               name: 'workOrderNum',
 | 
			
		||||
      //               value: 1
 | 
			
		||||
      //             }
 | 
			
		||||
      //           ]
 | 
			
		||||
      //         }
 | 
			
		||||
      //       }
 | 
			
		||||
      //     : undefined
 | 
			
		||||
        // this.$auth.hasPermi('base:order-completion-monitoring:sendOut')
 | 
			
		||||
        //     ? {
 | 
			
		||||
        //         type: 'sendOutDetail',
 | 
			
		||||
        //         btnName: '发货',
 | 
			
		||||
        //         showTip: '发货详情',
 | 
			
		||||
        //         showParam: {
 | 
			
		||||
        //           type: '&',
 | 
			
		||||
        //           data: [
 | 
			
		||||
        //             {
 | 
			
		||||
        //               type: 'more',
 | 
			
		||||
        //               name: 'workOrderNum',
 | 
			
		||||
        //               value: 1
 | 
			
		||||
        //             }
 | 
			
		||||
        //           ]
 | 
			
		||||
        //         }
 | 
			
		||||
        //       }
 | 
			
		||||
        //     : undefined
 | 
			
		||||
      ].filter((v) => v),
 | 
			
		||||
      chartList: []
 | 
			
		||||
    }
 | 
			
		||||
@@ -234,7 +217,7 @@ export default {
 | 
			
		||||
  components: { MonitoringRingCharts },
 | 
			
		||||
  mounted() {
 | 
			
		||||
    window.addEventListener('resize', () => {
 | 
			
		||||
      this.tableH = this.tableHeight(305)
 | 
			
		||||
      this.tableH = this.tableHeight(260)
 | 
			
		||||
    })
 | 
			
		||||
    let start = moment().subtract(30, 'days').format('yyyy-MM-DD')
 | 
			
		||||
    let end = moment().format('yyyy-MM-DD')
 | 
			
		||||
@@ -245,10 +228,10 @@ export default {
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    getPage() {
 | 
			
		||||
      orderGroupMonitor({...this.queryParams}).then(res => {
 | 
			
		||||
      orderGroupMonitor({ ...this.queryParams }).then(res => {
 | 
			
		||||
        let arr = res.data || []
 | 
			
		||||
        if (arr.length > 0) {
 | 
			
		||||
          let color = ['#7164FF','#288AFF','#63BDFF','#8EF0AB','#FFCE6A']
 | 
			
		||||
          let color = ['#7164FF', '#288AFF', '#63BDFF', '#8EF0AB', '#FFCE6A']
 | 
			
		||||
          let arr2 = []
 | 
			
		||||
          arr.map(item => {
 | 
			
		||||
            item.orderType = '集团订单'//前端写死订单类型
 | 
			
		||||
@@ -261,11 +244,11 @@ export default {
 | 
			
		||||
            obj.num = item.planQuantity || 0
 | 
			
		||||
            let sunNum = 0
 | 
			
		||||
            if (item.orderMonitorVOS && item.orderMonitorVOS.length > 0) {
 | 
			
		||||
              for(let i = 0; i < item.orderMonitorVOS.length; i++) {
 | 
			
		||||
              for (let i = 0; i < item.orderMonitorVOS.length; i++) {
 | 
			
		||||
                item.orderMonitorVOS[i].orderType = '厂务订单'//前端写死订单类型
 | 
			
		||||
                item.orderMonitorVOS[i].id = item.orderMonitorVOS[i].orderid
 | 
			
		||||
                item.orderMonitorVOS[i].orderNum = item.orderMonitorVOS[i].workOrderNum
 | 
			
		||||
                woIdString+=item.orderMonitorVOS[i].woIdString?item.orderMonitorVOS[i].woIdString:''
 | 
			
		||||
                woIdString += item.orderMonitorVOS[i].woIdString ? item.orderMonitorVOS[i].woIdString : ''
 | 
			
		||||
                //==============图数据
 | 
			
		||||
                let subObj = {}
 | 
			
		||||
                subObj.value = item.orderMonitorVOS[i].actualquantity
 | 
			
		||||
@@ -273,9 +256,9 @@ export default {
 | 
			
		||||
                if (i < 5) {
 | 
			
		||||
                  subObj.color = color[i]
 | 
			
		||||
                } else {
 | 
			
		||||
                  subObj.color = color[i%5]
 | 
			
		||||
                  subObj.color = color[i % 5]
 | 
			
		||||
                }
 | 
			
		||||
                sunNum+=(item.orderMonitorVOS[i].actualquantity || 0)
 | 
			
		||||
                sunNum += (item.orderMonitorVOS[i].actualquantity || 0)
 | 
			
		||||
                arr3.push(subObj)
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
@@ -295,7 +278,7 @@ export default {
 | 
			
		||||
              this.$refs.monitoringRingCharts.initChart()
 | 
			
		||||
            })
 | 
			
		||||
          }
 | 
			
		||||
        }else{
 | 
			
		||||
        } else {
 | 
			
		||||
          // 显示无数据的图片
 | 
			
		||||
          this.chartList = []
 | 
			
		||||
        }
 | 
			
		||||
@@ -320,24 +303,24 @@ export default {
 | 
			
		||||
        case 'orderDetail':
 | 
			
		||||
          if (val.data.orderType === '集团订单') {
 | 
			
		||||
            this.$router.push({// 去厂务订单详情
 | 
			
		||||
              path: '/order/base/order-manage/order-detail-data?orderIdString='+ val.data.orderIds.join(',')
 | 
			
		||||
              path: '/order/base/order-manage/order-detail-data?orderIdString=' + val.data.orderIds.join(',')
 | 
			
		||||
            })
 | 
			
		||||
          }else{
 | 
			
		||||
          } else {
 | 
			
		||||
            this.$router.push({// 去工单详情
 | 
			
		||||
              path: '/core/core-work-order-detail?woIdString='+val.data.woIdString
 | 
			
		||||
              path: '/core/core-work-order-detail?woIdString=' + val.data.woIdString
 | 
			
		||||
            })
 | 
			
		||||
          }
 | 
			
		||||
          break
 | 
			
		||||
        case 'qualityDetail':
 | 
			
		||||
          this.$router.push({
 | 
			
		||||
            path: '/quality/base/quality-inspection-data/detection-information/statistical-data?woIdString='+val.data.woIdString
 | 
			
		||||
            path: '/quality/base/quality-inspection-data/detection-information/statistical-data?woIdString=' + val.data.woIdString
 | 
			
		||||
          })
 | 
			
		||||
          break
 | 
			
		||||
        default:
 | 
			
		||||
          // this.$router.push({
 | 
			
		||||
          //   path: '/delivery/delivery-log?orderId='+encodeURI(val.data.name)
 | 
			
		||||
          // })
 | 
			
		||||
        }
 | 
			
		||||
        // this.$router.push({
 | 
			
		||||
        //   path: '/delivery/delivery-log?orderId='+encodeURI(val.data.name)
 | 
			
		||||
        // })
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    toggleTab() {
 | 
			
		||||
      if (this.activeName === 'barChart' && this.chartList.length > 0) {
 | 
			
		||||
@@ -346,7 +329,7 @@ export default {
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
<style lang='scss'>
 | 
			
		||||
@@ -360,31 +343,39 @@ export default {
 | 
			
		||||
    height: 2px;
 | 
			
		||||
    background-color: #e4e7ed;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .el-tabs__nav-wrap::after {
 | 
			
		||||
    width: 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .el-tabs__item {
 | 
			
		||||
    padding: 0 10px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .el-tabs__item:hover {
 | 
			
		||||
    color: rgba(0, 0, 0, 0.85);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .el-tabs__item.is-active {
 | 
			
		||||
    color: rgba(0, 0, 0, 0.85);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .el-tabs__item {
 | 
			
		||||
    color: rgba(0, 0, 0, 0.45);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .searchBarBox {
 | 
			
		||||
    margin-bottom: 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .boxTitle {
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    font-size: 16px;
 | 
			
		||||
    font-weight: 400;
 | 
			
		||||
    color: #000000;
 | 
			
		||||
    margin:0 10px 16px 0;
 | 
			
		||||
    margin: 0 10px 16px 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .blueTitle {
 | 
			
		||||
    content: '';
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,358 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <el-dialog :visible.sync="transferParam.aliPayOpen" :title="title" @closed="close" append-to-body width="800px">
 | 
			
		||||
      <el-form ref="aliPayForm" :model="form" :rules="rules" size="medium" label-width="100px"
 | 
			
		||||
               v-loading="transferParam.loading">
 | 
			
		||||
        <el-form-item label-width="180px" label="渠道费率" prop="feeRate">
 | 
			
		||||
          <el-input v-model="form.feeRate" placeholder="请输入渠道费率" clearable :style="{width: '100%'}">
 | 
			
		||||
            <template slot="append">%</template>
 | 
			
		||||
          </el-input>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label-width="180px" label="开放平台APPID" prop="aliPayConfig.appId">
 | 
			
		||||
          <el-input v-model="form.aliPayConfig.appId" placeholder="请输入开放平台APPID" clearable :style="{width: '100%'}">
 | 
			
		||||
          </el-input>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label-width="180px" label="渠道状态" prop="status">
 | 
			
		||||
          <el-radio-group v-model="form.status" size="medium">
 | 
			
		||||
            <el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
 | 
			
		||||
              {{ dict.label }}
 | 
			
		||||
            </el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label-width="180px" label="网关地址" prop="aliPayConfig.serverUrl">
 | 
			
		||||
          <el-radio-group v-model="form.aliPayConfig.serverUrl" size="medium">
 | 
			
		||||
            <el-radio v-for="dict in aliPayServerDatas" :key="dict.value" :label="dict.value">
 | 
			
		||||
              {{ dict.label }}
 | 
			
		||||
            </el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label-width="180px" label="算法类型" prop="aliPayConfig.signType">
 | 
			
		||||
          <el-radio-group v-model="form.aliPayConfig.signType" size="medium">
 | 
			
		||||
            <el-radio v-for="dict in aliPaySignTypeDatas" :key="dict.value" :label="dict.value">
 | 
			
		||||
              {{ dict.label }}
 | 
			
		||||
            </el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label-width="180px" label="公钥类型" prop="aliPayConfig.mode">
 | 
			
		||||
          <el-radio-group v-model="form.aliPayConfig.mode" size="medium">
 | 
			
		||||
            <el-radio v-for="dict in aliPayModeDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
 | 
			
		||||
              {{ dict.label }}
 | 
			
		||||
            </el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <div v-if="form.aliPayConfig.mode === 1">
 | 
			
		||||
          <el-form-item label-width="180px" label="商户私钥" prop="aliPayConfig.privateKey">
 | 
			
		||||
            <el-input type="textarea" :autosize="{minRows: 8, maxRows: 8}" v-model="form.aliPayConfig.privateKey"
 | 
			
		||||
                      placeholder="请输入商户私钥" clearable :style="{width: '100%'}">
 | 
			
		||||
            </el-input>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label-width="180px" label="支付宝公钥字符串" prop="aliPayConfig.alipayPublicKey">
 | 
			
		||||
            <el-input
 | 
			
		||||
              type="textarea"
 | 
			
		||||
              :autosize="{minRows: 8, maxRows: 8}"
 | 
			
		||||
              v-model="form.aliPayConfig.alipayPublicKey"
 | 
			
		||||
              placeholder="请输入支付宝公钥字符串" clearable
 | 
			
		||||
              :style="{width: '100%'}">
 | 
			
		||||
            </el-input>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div v-if="form.aliPayConfig.mode === 2">
 | 
			
		||||
          <el-form-item label-width="180px" label="商户公钥应用证书" prop="aliPayConfig.appCertContent">
 | 
			
		||||
            <el-input v-model="form.aliPayConfig.appCertContent" type="textarea"
 | 
			
		||||
                      placeholder="请上传商户公钥应用证书"
 | 
			
		||||
                      readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label-width="180px" label="">
 | 
			
		||||
            <el-upload
 | 
			
		||||
              action=""
 | 
			
		||||
              ref="privateKeyContentFile"
 | 
			
		||||
              :limit="1"
 | 
			
		||||
              :accept="fileAccept"
 | 
			
		||||
              :http-request="appCertUpload"
 | 
			
		||||
              :before-upload="fileBeforeUpload">
 | 
			
		||||
              <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
 | 
			
		||||
            </el-upload>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label-width="180px" label="支付宝公钥证书" prop="aliPayConfig.alipayPublicCertContent">
 | 
			
		||||
            <el-input v-model="form.aliPayConfig.alipayPublicCertContent" type="textarea"
 | 
			
		||||
                      placeholder="请上传支付宝公钥证书"
 | 
			
		||||
                      readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label-width="180px" label="">
 | 
			
		||||
            <el-upload
 | 
			
		||||
              ref="privateCertContentFile"
 | 
			
		||||
              action=""
 | 
			
		||||
              :limit="1"
 | 
			
		||||
              :accept="fileAccept"
 | 
			
		||||
              :before-upload="fileBeforeUpload"
 | 
			
		||||
              :http-request="alipayPublicCertUpload">
 | 
			
		||||
              <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
 | 
			
		||||
            </el-upload>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label-width="180px" label="根证书" prop="aliPayConfig.rootCertContent">
 | 
			
		||||
            <el-input
 | 
			
		||||
              v-model="form.aliPayConfig.rootCertContent"
 | 
			
		||||
              type="textarea"
 | 
			
		||||
              placeholder="请上传根证书"
 | 
			
		||||
              readonly :autosize="{minRows: 8, maxRows: 8}"
 | 
			
		||||
              :style="{width: '100%'}">
 | 
			
		||||
            </el-input>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label-width="180px" label="">
 | 
			
		||||
            <el-upload
 | 
			
		||||
              ref="privateCertContentFile"
 | 
			
		||||
              :limit="1"
 | 
			
		||||
              :accept="fileAccept"
 | 
			
		||||
              action=""
 | 
			
		||||
              :before-upload="fileBeforeUpload"
 | 
			
		||||
              :http-request="rootCertUpload">
 | 
			
		||||
              <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
 | 
			
		||||
            </el-upload>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </div>
 | 
			
		||||
        <el-form-item label-width="180px" label="备注" prop="remark">
 | 
			
		||||
          <el-input v-model="form.remark" :style="{width: '100%'}"></el-input>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button @click="close">取消</el-button>
 | 
			
		||||
        <el-button type="primary" @click="handleConfirm">确定</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
 | 
			
		||||
import {createChannel, getChannel, updateChannel} from "@/api/pay/channel";
 | 
			
		||||
 | 
			
		||||
const defaultForm = {
 | 
			
		||||
  code: '',
 | 
			
		||||
  status: null,
 | 
			
		||||
  remark: '',
 | 
			
		||||
  feeRate: null,
 | 
			
		||||
  appId: '',
 | 
			
		||||
  merchantId: null,
 | 
			
		||||
  aliPayConfig: {
 | 
			
		||||
    appId: '',
 | 
			
		||||
    serverUrl: null,
 | 
			
		||||
    signType: '',
 | 
			
		||||
    mode: null,
 | 
			
		||||
    privateKey: '',
 | 
			
		||||
    alipayPublicKey: '',
 | 
			
		||||
    appCertContent: '',
 | 
			
		||||
    alipayPublicCertContent: '',
 | 
			
		||||
    rootCertContent: ''
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "aliPayChannelForm",
 | 
			
		||||
  components: {},
 | 
			
		||||
  props: {
 | 
			
		||||
    // 传输的参数
 | 
			
		||||
    transferParam: {
 | 
			
		||||
      // 加载动画
 | 
			
		||||
      "loading": false,
 | 
			
		||||
      // 是否修改
 | 
			
		||||
      "edit": false,
 | 
			
		||||
      // 是否显示
 | 
			
		||||
      "aliPayOpen": false,
 | 
			
		||||
      // 应用ID
 | 
			
		||||
      "appId": null,
 | 
			
		||||
      // 渠道编码
 | 
			
		||||
      "payCode": null,
 | 
			
		||||
      // 商户对象
 | 
			
		||||
      "payMerchant": {
 | 
			
		||||
        // 编号
 | 
			
		||||
        "id": null,
 | 
			
		||||
        // 名称
 | 
			
		||||
        "name": null
 | 
			
		||||
      },
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      title:'',
 | 
			
		||||
      form: JSON.parse(JSON.stringify(defaultForm)),
 | 
			
		||||
      rules: {
 | 
			
		||||
        feeRate: [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '请输入渠道费率',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        'aliPayConfig.appId': [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '请输入开放平台上创建的应用的 ID',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        status: [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '渠道状态不能为空',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        'aliPayConfig.serverUrl': [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '请传入网关地址',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        'aliPayConfig.signType': [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '请传入签名算法类型',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        'aliPayConfig.mode': [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '公钥类型不能为空',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        'aliPayConfig.privateKey': [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '请输入商户私钥',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        'aliPayConfig.alipayPublicKey': [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '请输入支付宝公钥字符串',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        'aliPayConfig.appCertContent': [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '请上传商户公钥应用证书',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        'aliPayConfig.alipayPublicCertContent': [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '请上传支付宝公钥证书',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        'aliPayConfig.rootCertContent': [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '请上传指定根证书',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
      },
 | 
			
		||||
      fileAccept: ".crt",
 | 
			
		||||
      // 渠道状态 数据字典
 | 
			
		||||
      statusDictDatas: getDictDatas(DICT_TYPE.COMMON_STATUS),
 | 
			
		||||
      // 支付宝加密方式
 | 
			
		||||
      aliPaySignTypeDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_SIGN_TYPE),
 | 
			
		||||
      // 版本状态 数据字典
 | 
			
		||||
      aliPayModeDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_MODE),
 | 
			
		||||
      // 支付宝网关地址
 | 
			
		||||
      aliPayServerDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_SERVER_TYPE),
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  watch: {
 | 
			
		||||
    transferParam: {
 | 
			
		||||
      deep: true,  // 深度监听
 | 
			
		||||
      handler(newVal) {
 | 
			
		||||
        if (newVal.aliPayOpen) {
 | 
			
		||||
          this.form.code = newVal.payCode;
 | 
			
		||||
          this.form.appId = newVal.appId;
 | 
			
		||||
          this.form.merchantId = newVal.payMerchant.id;
 | 
			
		||||
          // 只有在初次进来为编辑 并且为加载中的时候才回去请求数据
 | 
			
		||||
          if (newVal.edit === true && newVal.loading) {
 | 
			
		||||
            this.title = "编辑支付渠道";
 | 
			
		||||
            this.init();
 | 
			
		||||
          } else {
 | 
			
		||||
            this.title = "创建支付渠道";
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  methods: {
 | 
			
		||||
    init() {
 | 
			
		||||
      getChannel(this.transferParam.payMerchant.id, this.transferParam.appId, this.transferParam.payCode)
 | 
			
		||||
        .then(response => {
 | 
			
		||||
          this.form.id = response.data.id;
 | 
			
		||||
          this.form.feeRate = response.data.feeRate;
 | 
			
		||||
          this.form.status = response.data.status;
 | 
			
		||||
          this.form.remark = response.data.remark;
 | 
			
		||||
 | 
			
		||||
          let config = JSON.parse(response.data.config);
 | 
			
		||||
          this.form.aliPayConfig.appId = config.appId;
 | 
			
		||||
          this.form.aliPayConfig.serverUrl = config.serverUrl;
 | 
			
		||||
          this.form.aliPayConfig.signType = config.signType;
 | 
			
		||||
          this.form.aliPayConfig.mode = config.mode;
 | 
			
		||||
          this.form.aliPayConfig.privateKey = config.privateKey;
 | 
			
		||||
          this.form.aliPayConfig.alipayPublicKey = config.alipayPublicKey;
 | 
			
		||||
          this.form.aliPayConfig.appCertContent = config.appCertContent;
 | 
			
		||||
          this.form.aliPayConfig.alipayPublicCertContent = config.alipayPublicCertContent;
 | 
			
		||||
          this.form.aliPayConfig.rootCertContent = config.rootCertContent;
 | 
			
		||||
          this.transferParam.loading = false;
 | 
			
		||||
        })
 | 
			
		||||
    },
 | 
			
		||||
    close() {
 | 
			
		||||
      this.transferParam.aliPayOpen = false;
 | 
			
		||||
      this.form = JSON.parse(JSON.stringify(defaultForm));
 | 
			
		||||
    },
 | 
			
		||||
    handleConfirm() {
 | 
			
		||||
      this.$refs['aliPayForm'].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return
 | 
			
		||||
        }
 | 
			
		||||
        let data = this.form;
 | 
			
		||||
        data.config = JSON.stringify(this.form.aliPayConfig);
 | 
			
		||||
        if (this.transferParam.edit) {
 | 
			
		||||
          updateChannel(data).then(response => {
 | 
			
		||||
            if (response.code === 0) {
 | 
			
		||||
              this.$modal.msgSuccess("修改成功");
 | 
			
		||||
              this.close();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          })
 | 
			
		||||
        } else {
 | 
			
		||||
 | 
			
		||||
          createChannel(data).then(response => {
 | 
			
		||||
            if (response.code === 0) {
 | 
			
		||||
              this.$modal.msgSuccess("新增成功");
 | 
			
		||||
              this.$parent.refreshTable();
 | 
			
		||||
              this.close();
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    fileBeforeUpload(file) {
 | 
			
		||||
      let format = '.' + file.name.split(".")[1];
 | 
			
		||||
      if (format !== this.fileAccept) {
 | 
			
		||||
        this.$message.error('请上传指定格式"' + this.fileAccept + '"文件');
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
      let isRightSize = file.size / 1024 / 1024 < 2
 | 
			
		||||
      if (!isRightSize) {
 | 
			
		||||
        this.$message.error('文件大小超过 2MB')
 | 
			
		||||
      }
 | 
			
		||||
      return isRightSize
 | 
			
		||||
    },
 | 
			
		||||
    appCertUpload(event) {
 | 
			
		||||
      const readFile = new FileReader()
 | 
			
		||||
      readFile.onload = (e) => {
 | 
			
		||||
        this.form.aliPayConfig.appCertContent = e.target.result
 | 
			
		||||
      }
 | 
			
		||||
      readFile.readAsText(event.file);
 | 
			
		||||
    },
 | 
			
		||||
    alipayPublicCertUpload(event) {
 | 
			
		||||
      const readFile = new FileReader()
 | 
			
		||||
      readFile.onload = (e) => {
 | 
			
		||||
        this.form.aliPayConfig.alipayPublicCertContent = e.target.result
 | 
			
		||||
      }
 | 
			
		||||
      readFile.readAsText(event.file);
 | 
			
		||||
    },
 | 
			
		||||
    rootCertUpload(event) {
 | 
			
		||||
      const readFile = new FileReader()
 | 
			
		||||
      readFile.onload = (e) => {
 | 
			
		||||
        this.form.aliPayConfig.rootCertContent = e.target.result
 | 
			
		||||
      }
 | 
			
		||||
      readFile.readAsText(event.file);
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
<style scoped>
 | 
			
		||||
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,299 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <el-dialog :visible.sync="transferParam.wechatOpen" :title="title" @close="close" append-to-body width="800px">
 | 
			
		||||
      <el-form ref="wechatJsApiForm" :model="form" :rules="rules" size="medium" label-width="100px"
 | 
			
		||||
               v-loading="transferParam.loading">
 | 
			
		||||
        <el-form-item label-width="180px" label="渠道费率" prop="feeRate">
 | 
			
		||||
          <el-input v-model="form.feeRate" placeholder="请输入渠道费率" clearable :style="{width: '100%'}">
 | 
			
		||||
            <template slot="append">%</template>
 | 
			
		||||
          </el-input>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label-width="180px" label="公众号APPID" prop="weChatConfig.appId">
 | 
			
		||||
          <el-input v-model="form.weChatConfig.appId" placeholder="请输入公众号APPID" clearable :style="{width: '100%'}">
 | 
			
		||||
          </el-input>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label-width="180px" label="商户号" prop="weChatConfig.mchId">
 | 
			
		||||
          <el-input v-model="form.weChatConfig.mchId" :style="{width: '100%'}"></el-input>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label-width="180px" label="渠道状态" prop="status">
 | 
			
		||||
          <el-radio-group v-model="form.status" size="medium">
 | 
			
		||||
            <el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
 | 
			
		||||
              {{ dict.label }}
 | 
			
		||||
            </el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label-width="180px" label="API 版本" prop="weChatConfig.apiVersion">
 | 
			
		||||
          <el-radio-group v-model="form.weChatConfig.apiVersion" size="medium">
 | 
			
		||||
            <el-radio v-for="dict in versionDictDatas" :key="dict.value" :label="dict.value">
 | 
			
		||||
              {{ dict.label }}
 | 
			
		||||
            </el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label-width="180px" label="商户密钥" prop="weChatConfig.mchKey"
 | 
			
		||||
                      v-if="form.weChatConfig.apiVersion === 'v2'">
 | 
			
		||||
          <el-input v-model="form.weChatConfig.mchKey" placeholder="请输入商户密钥" clearable
 | 
			
		||||
                    :style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <div v-if="form.weChatConfig.apiVersion === 'v3'">
 | 
			
		||||
          <el-form-item label-width="180px" label="API V3密钥" prop="weChatConfig.apiV3Key">
 | 
			
		||||
            <el-input v-model="form.weChatConfig.apiV3Key" placeholder="请输入API V3密钥" clearable
 | 
			
		||||
                      :style="{width: '100%'}" type="textarea" :autosize="{minRows: 8, maxRows: 8}"></el-input>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label-width="180px" label="apiclient_key.perm证书" prop="weChatConfig.privateKeyContent">
 | 
			
		||||
            <el-input v-model="form.weChatConfig.privateKeyContent" type="textarea"
 | 
			
		||||
                      placeholder="请上传apiclient_key.perm证书"
 | 
			
		||||
                      readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label-width="180px" label="" prop="privateKeyContentFile">
 | 
			
		||||
            <el-upload ref="privateKeyContentFile"
 | 
			
		||||
                       :limit="1"
 | 
			
		||||
                       :accept="fileAccept"
 | 
			
		||||
                       :headers="header"
 | 
			
		||||
                       action=""
 | 
			
		||||
                       :before-upload="pemFileBeforeUpload"
 | 
			
		||||
                       :http-request="privateKeyUpload"
 | 
			
		||||
            >
 | 
			
		||||
              <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
 | 
			
		||||
            </el-upload>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label-width="180px" label="apiclient_cert.perm证书" prop="weChatConfig.privateCertContent">
 | 
			
		||||
            <el-input v-model="form.weChatConfig.privateCertContent" type="textarea"
 | 
			
		||||
                      placeholder="请上传apiclient_cert.perm证书"
 | 
			
		||||
                      readonly :autosize="{minRows: 8, maxRows: 8}" :style="{width: '100%'}"></el-input>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
          <el-form-item label-width="180px" label="" prop="privateCertContentFile">
 | 
			
		||||
            <el-upload ref="privateCertContentFile"
 | 
			
		||||
                       :limit="1"
 | 
			
		||||
                       :accept="fileAccept"
 | 
			
		||||
                       :headers="header"
 | 
			
		||||
                       action=""
 | 
			
		||||
                       :before-upload="pemFileBeforeUpload"
 | 
			
		||||
                       :http-request="privateCertUpload"
 | 
			
		||||
            >
 | 
			
		||||
              <el-button size="small" type="primary" icon="el-icon-upload">点击上传</el-button>
 | 
			
		||||
            </el-upload>
 | 
			
		||||
          </el-form-item>
 | 
			
		||||
        </div>
 | 
			
		||||
        <el-form-item label-width="180px" label="备注" prop="remark">
 | 
			
		||||
          <el-input v-model="form.remark" :style="{width: '100%'}"></el-input>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button @click="close">取消</el-button>
 | 
			
		||||
        <el-button type="primary" @click="handleConfirm">确定</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
 | 
			
		||||
import {createChannel, getChannel, updateChannel} from "@/api/pay/channel";
 | 
			
		||||
 | 
			
		||||
const defaultForm = {
 | 
			
		||||
  code: '',
 | 
			
		||||
  status: null,
 | 
			
		||||
  remark: '',
 | 
			
		||||
  feeRate: null,
 | 
			
		||||
  appId: '',
 | 
			
		||||
  merchantId: null,
 | 
			
		||||
  weChatConfig: {
 | 
			
		||||
    appId: '',
 | 
			
		||||
    mchId: '',
 | 
			
		||||
    apiVersion: '',
 | 
			
		||||
    mchKey: '',
 | 
			
		||||
    privateKeyContent: '',
 | 
			
		||||
    privateCertContent: '',
 | 
			
		||||
    apiV3Key:'',
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "wechatChannelForm",
 | 
			
		||||
  components: {},
 | 
			
		||||
  props: {
 | 
			
		||||
    // 传输的参数
 | 
			
		||||
    transferParam: {
 | 
			
		||||
      // 加载动画
 | 
			
		||||
      "loading": false,
 | 
			
		||||
      // 是否修改
 | 
			
		||||
      "edit": false,
 | 
			
		||||
      // 是否显示
 | 
			
		||||
      "wechatOpen": false,
 | 
			
		||||
      // 应用ID
 | 
			
		||||
      "appId": null,
 | 
			
		||||
      // 渠道编码
 | 
			
		||||
      "payCode": null,
 | 
			
		||||
      // 商户对象
 | 
			
		||||
      "payMerchant": {
 | 
			
		||||
        // 编号
 | 
			
		||||
        "id": null,
 | 
			
		||||
        // 名称
 | 
			
		||||
        "name": null
 | 
			
		||||
      },
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      title:'',
 | 
			
		||||
      form: JSON.parse(JSON.stringify(defaultForm)),
 | 
			
		||||
      rules: {
 | 
			
		||||
        feeRate: [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '请输入渠道费率',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        'weChatConfig.mchId': [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '请传入商户号',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        'weChatConfig.appId': [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '请输入公众号APPID',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        status: [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '渠道状态不能为空',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        'weChatConfig.apiVersion': [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: 'API版本不能为空',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        'weChatConfig.mchKey': [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '请输入商户密钥',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        'weChatConfig.privateKeyContent': [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '请上传apiclient_key.perm证书',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        'weChatConfig.privateCertContent': [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '请上传apiclient_cert.perm证书',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
        'weChatConfig.apiV3Key': [{
 | 
			
		||||
          required: true,
 | 
			
		||||
          message: '请上传apiV3密钥值',
 | 
			
		||||
          trigger: 'blur'
 | 
			
		||||
        }],
 | 
			
		||||
      },
 | 
			
		||||
      // 文件上传的header
 | 
			
		||||
      header: {
 | 
			
		||||
        "Authorization": null
 | 
			
		||||
      },
 | 
			
		||||
      fileAccept: ".pem",
 | 
			
		||||
      // 渠道状态 数据字典
 | 
			
		||||
      statusDictDatas: getDictDatas(DICT_TYPE.COMMON_STATUS),
 | 
			
		||||
      versionDictDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_WECHAT_VERSION),
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  watch: {
 | 
			
		||||
    transferParam: {
 | 
			
		||||
      deep: true,  // 深度监听
 | 
			
		||||
      handler(newVal) {
 | 
			
		||||
        if (newVal.wechatOpen) {
 | 
			
		||||
          this.form.code = newVal.payCode;
 | 
			
		||||
          this.form.appId = newVal.appId;
 | 
			
		||||
          this.form.merchantId = newVal.payMerchant.id;
 | 
			
		||||
          // 只有在初次进来为编辑 并且为加载中的时候才回去请求数据
 | 
			
		||||
          if (newVal.edit && newVal.loading) {
 | 
			
		||||
            this.title = "编辑支付渠道";
 | 
			
		||||
            this.init();
 | 
			
		||||
          } else {
 | 
			
		||||
            this.title = "创建支付渠道";
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    init() {
 | 
			
		||||
      getChannel(this.transferParam.payMerchant.id, this.transferParam.appId, this.transferParam.payCode)
 | 
			
		||||
        .then(response => {
 | 
			
		||||
          this.form.id = response.data.id;
 | 
			
		||||
          this.form.feeRate = response.data.feeRate;
 | 
			
		||||
          this.form.appId = response.data.appId;
 | 
			
		||||
          this.form.status = response.data.status;
 | 
			
		||||
          this.form.remark = response.data.remark;
 | 
			
		||||
 | 
			
		||||
          let config = JSON.parse(response.data.config);
 | 
			
		||||
          this.form.weChatConfig.appId = config.appId;
 | 
			
		||||
          this.form.weChatConfig.apiVersion = config.apiVersion;
 | 
			
		||||
          this.form.weChatConfig.mchId = config.mchId;
 | 
			
		||||
          this.form.weChatConfig.mchKey = config.mchKey;
 | 
			
		||||
          this.form.weChatConfig.privateKeyContent = config.privateKeyContent;
 | 
			
		||||
          this.form.weChatConfig.privateCertContent = config.privateCertContent;
 | 
			
		||||
          this.form.weChatConfig.apiV3Key = config.apiV3Key;
 | 
			
		||||
          this.transferParam.loading = false;
 | 
			
		||||
        })
 | 
			
		||||
    },
 | 
			
		||||
    close() {
 | 
			
		||||
      this.transferParam.wechatOpen = false;
 | 
			
		||||
      this.form = JSON.parse(JSON.stringify(defaultForm));
 | 
			
		||||
    },
 | 
			
		||||
    handleConfirm() {
 | 
			
		||||
      this.$refs['wechatJsApiForm'].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return
 | 
			
		||||
        }
 | 
			
		||||
        let data = this.form;
 | 
			
		||||
        data.config = JSON.stringify(this.form.weChatConfig);
 | 
			
		||||
        if (this.transferParam.edit) {
 | 
			
		||||
          updateChannel(data).then(response => {
 | 
			
		||||
            if (response.code === 0) {
 | 
			
		||||
              this.$modal.msgSuccess("修改成功");
 | 
			
		||||
              this.close();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          })
 | 
			
		||||
        } else {
 | 
			
		||||
 | 
			
		||||
          createChannel(data).then(response => {
 | 
			
		||||
            if (response.code === 0) {
 | 
			
		||||
              this.$modal.msgSuccess("新增成功");
 | 
			
		||||
              this.$parent.refreshTable();
 | 
			
		||||
              this.close();
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    pemFileBeforeUpload(file) {
 | 
			
		||||
      let format = '.' + file.name.split(".")[1];
 | 
			
		||||
      if (format !== this.fileAccept) {
 | 
			
		||||
        this.$message.error('请上传指定格式"' + this.fileAccept + '"文件');
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
      let isRightSize = file.size / 1024 / 1024 < 2
 | 
			
		||||
      if (!isRightSize) {
 | 
			
		||||
        this.$message.error('文件大小超过 2MB')
 | 
			
		||||
      }
 | 
			
		||||
      return isRightSize
 | 
			
		||||
    },
 | 
			
		||||
    privateKeyUpload(event) {
 | 
			
		||||
      const readFile = new FileReader()
 | 
			
		||||
      readFile.onload = (e) => {
 | 
			
		||||
        this.form.weChatConfig.privateKeyContent = e.target.result
 | 
			
		||||
      }
 | 
			
		||||
      readFile.readAsText(event.file);
 | 
			
		||||
    },
 | 
			
		||||
    privateCertUpload(event) {
 | 
			
		||||
      const readFile = new FileReader()
 | 
			
		||||
      readFile.onload = (e) => {
 | 
			
		||||
        this.form.weChatConfig.privateCertContent = e.target.result
 | 
			
		||||
      }
 | 
			
		||||
      readFile.readAsText(event.file);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
<style scoped>
 | 
			
		||||
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,484 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="应用名" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入应用名" clearable
 | 
			
		||||
                  @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="商户名称" prop="merchantName">
 | 
			
		||||
        <el-input v-model="queryParams.merchantName" placeholder="请输入商户名称" clearable
 | 
			
		||||
                  @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="开启状态" prop="status">
 | 
			
		||||
        <el-select v-model="queryParams.status" placeholder="请选择开启状态" clearable>
 | 
			
		||||
          <el-option v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="dict.label"
 | 
			
		||||
                     :value="parseInt(dict.value)"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['pay:app:create']">新增
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
 | 
			
		||||
                   v-hasPermi="['pay:app:export']">导出
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="应用编号" align="center" prop="id"/>
 | 
			
		||||
      <el-table-column label="应用名" align="center" prop="name"/>
 | 
			
		||||
      <el-table-column label="开启状态" align="center" prop="status">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-switch v-model="scope.row.status" :active-value="0" :inactive-value="1"
 | 
			
		||||
                     @change="handleStatusChange(scope.row)"/>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="商户名称" align="center" prop="payMerchant.name"/>
 | 
			
		||||
      <el-table-column label="支付宝配置" align="center">
 | 
			
		||||
        <el-table-column :label="payChannelEnum.ALIPAY_APP.name" align="center">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <el-button type="success" icon="el-icon-check" circle
 | 
			
		||||
                       v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_APP.code)"
 | 
			
		||||
                       @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)">
 | 
			
		||||
            </el-button>
 | 
			
		||||
            <el-button v-else
 | 
			
		||||
                       type="danger" icon="el-icon-close" circle
 | 
			
		||||
                       @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)">
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column :label="payChannelEnum.ALIPAY_PC.name" align="center">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <el-button type="success" icon="el-icon-check" circle
 | 
			
		||||
                       v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_PC.code)"
 | 
			
		||||
                       @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_PC.code,payType.ALIPAY)">
 | 
			
		||||
            </el-button>
 | 
			
		||||
            <el-button v-else
 | 
			
		||||
                       type="danger" icon="el-icon-close" circle
 | 
			
		||||
                       @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_PC.code,payType.ALIPAY)">
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column :label="payChannelEnum.ALIPAY_WAP.name" align="center">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <el-button type="success" icon="el-icon-check" circle
 | 
			
		||||
                       v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_WAP.code)"
 | 
			
		||||
                       @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_WAP.code,payType.ALIPAY)">
 | 
			
		||||
            </el-button>
 | 
			
		||||
            <el-button v-else
 | 
			
		||||
                       type="danger" icon="el-icon-close" circle
 | 
			
		||||
                       @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_WAP.code,payType.ALIPAY)">
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column :label="payChannelEnum.ALIPAY_QR.name" align="center">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <el-button type="success" icon="el-icon-check" circle
 | 
			
		||||
                       v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_QR.code)"
 | 
			
		||||
                       @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_QR.code,payType.ALIPAY)">
 | 
			
		||||
            </el-button>
 | 
			
		||||
            <el-button v-else
 | 
			
		||||
                       type="danger" icon="el-icon-close" circle
 | 
			
		||||
                       @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_QR.code,payType.ALIPAY)">
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column :label="payChannelEnum.ALIPAY_BAR.name" align="center">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <el-button type="success" icon="el-icon-check" circle
 | 
			
		||||
                       v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_BAR.code)"
 | 
			
		||||
                       @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_BAR.code,payType.ALIPAY)">
 | 
			
		||||
            </el-button>
 | 
			
		||||
            <el-button v-else
 | 
			
		||||
                       type="danger" icon="el-icon-close" circle
 | 
			
		||||
                       @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_BAR.code,payType.ALIPAY)">
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="微信配置" align="center">
 | 
			
		||||
        <el-table-column :label="payChannelEnum.WX_LITE.name" align="center">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <el-button type="success" icon="el-icon-check" circle
 | 
			
		||||
                       v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_LITE.code)"
 | 
			
		||||
                       @click="handleUpdateChannel(scope.row,payChannelEnum.WX_LITE.code,payType.WECHAT)">
 | 
			
		||||
            </el-button>
 | 
			
		||||
            <el-button v-else
 | 
			
		||||
                       type="danger" icon="el-icon-close" circle
 | 
			
		||||
                       @click="handleCreateChannel(scope.row,payChannelEnum.WX_LITE.code,payType.WECHAT)">
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column :label="payChannelEnum.WX_PUB.name" align="center">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <el-button type="success" icon="el-icon-check" circle
 | 
			
		||||
                       v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_PUB.code)"
 | 
			
		||||
                       @click="handleUpdateChannel(scope.row,payChannelEnum.WX_PUB.code,payType.WECHAT)">
 | 
			
		||||
            </el-button>
 | 
			
		||||
            <el-button v-else
 | 
			
		||||
                       type="danger" icon="el-icon-close" circle
 | 
			
		||||
                       @click="handleCreateChannel(scope.row,payChannelEnum.WX_PUB.code,payType.WECHAT)">
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column :label="payChannelEnum.WX_APP.name" align="center">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <el-button type="success" icon="el-icon-check" circle
 | 
			
		||||
                       v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_APP.code)"
 | 
			
		||||
                       @click="handleUpdateChannel(scope.row,payChannelEnum.WX_APP.code,payType.WECHAT)">
 | 
			
		||||
            </el-button>
 | 
			
		||||
            <el-button v-else
 | 
			
		||||
                       type="danger" icon="el-icon-close" circle
 | 
			
		||||
                       @click="handleCreateChannel(scope.row,payChannelEnum.WX_APP.code,payType.WECHAT)">
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                     v-hasPermi="['pay:app:update']">修改
 | 
			
		||||
          </el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-hasPermi="['pay:app:delete']">删除
 | 
			
		||||
          </el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="160px">
 | 
			
		||||
        <el-form-item label="应用名" prop="name">
 | 
			
		||||
          <el-input v-model="form.name" placeholder="请输入应用名"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="所属商户" prop="merchantId">
 | 
			
		||||
          <el-select
 | 
			
		||||
            v-model="form.merchantId"
 | 
			
		||||
            filterable
 | 
			
		||||
            remote
 | 
			
		||||
            reserve-keyword
 | 
			
		||||
            placeholder="请选择所属商户"
 | 
			
		||||
            :remote-method="handleGetMerchantListByName"
 | 
			
		||||
            :loading="loading">
 | 
			
		||||
            <el-option
 | 
			
		||||
              v-for="item in merchantList"
 | 
			
		||||
              :key="item.id"
 | 
			
		||||
              :label="item.name"
 | 
			
		||||
              :value="item.id">
 | 
			
		||||
            </el-option>
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="开启状态" prop="status">
 | 
			
		||||
          <el-radio-group v-model="form.status">
 | 
			
		||||
            <el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
 | 
			
		||||
              {{ dict.label }}
 | 
			
		||||
            </el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-form-item label="支付结果的回调地址" prop="payNotifyUrl">
 | 
			
		||||
          <el-input v-model="form.payNotifyUrl" placeholder="请输入支付结果的回调地址"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="退款结果的回调地址" prop="refundNotifyUrl">
 | 
			
		||||
          <el-input v-model="form.refundNotifyUrl" placeholder="请输入退款结果的回调地址"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
 | 
			
		||||
        <el-form-item label="备注" prop="remark">
 | 
			
		||||
          <el-input v-model="form.remark" placeholder="请输入备注"/>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
    <wechat-channel-form :transferParam="channelParam"></wechat-channel-form>
 | 
			
		||||
    <ali-pay-channel-form :transferParam="channelParam"></ali-pay-channel-form>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {createApp, updateApp, changeAppStatus, deleteApp, getApp, getAppPage, exportAppExcel} from "@/api/pay/app";
 | 
			
		||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
 | 
			
		||||
import {PayType, PayChannelEnum, CommonStatusEnum} from "@/utils/constants";
 | 
			
		||||
import {getMerchantListByName} from "@/api/pay/merchant";
 | 
			
		||||
import wechatChannelForm from "@/views/pay/app/components/wechatChannelForm";
 | 
			
		||||
import aliPayChannelForm from "@/views/pay/app/components/aliPayChannelForm";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "PayApp",
 | 
			
		||||
  components: {
 | 
			
		||||
    "wechatChannelForm": wechatChannelForm,
 | 
			
		||||
    "aliPayChannelForm": aliPayChannelForm
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 支付应用信息列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        name: null,
 | 
			
		||||
        status: null,
 | 
			
		||||
        remark: null,
 | 
			
		||||
        payNotifyUrl: null,
 | 
			
		||||
        refundNotifyUrl: null,
 | 
			
		||||
        merchantName: null,
 | 
			
		||||
        createTime: []
 | 
			
		||||
      },
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {},
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        name: [{required: true, message: "应用名不能为空", trigger: "blur"}],
 | 
			
		||||
        status: [{required: true, message: "开启状态不能为空", trigger: "blur"}],
 | 
			
		||||
        payNotifyUrl: [{required: true, message: "支付结果的回调地址不能为空", trigger: "blur"}],
 | 
			
		||||
        refundNotifyUrl: [{required: true, message: "退款结果的回调地址不能为空", trigger: "blur"}],
 | 
			
		||||
        merchantId: [{required: true, message: "商户编号不能为空", trigger: "blur"}],
 | 
			
		||||
      },
 | 
			
		||||
      // 数据字典
 | 
			
		||||
      statusDictDatas: getDictDatas(DICT_TYPE.COMMON_STATUS),
 | 
			
		||||
      sysCommonStatusEnum: CommonStatusEnum,
 | 
			
		||||
      // 支付渠道枚举
 | 
			
		||||
      payChannelEnum: PayChannelEnum,
 | 
			
		||||
      // 支付类型
 | 
			
		||||
      payType: PayType,
 | 
			
		||||
      // 商户列表
 | 
			
		||||
      merchantList: [],
 | 
			
		||||
      // 是否显示支付窗口
 | 
			
		||||
      payOpen: false,
 | 
			
		||||
      // 微信组件传参参数
 | 
			
		||||
      channelParam: {
 | 
			
		||||
        // 是否修改
 | 
			
		||||
        "edit": false,
 | 
			
		||||
        // 微信是否显示
 | 
			
		||||
        "wechatOpen": false,
 | 
			
		||||
        // 支付宝是否显示
 | 
			
		||||
        "aliPayOpen": false,
 | 
			
		||||
        // 应用ID
 | 
			
		||||
        "appId": null,
 | 
			
		||||
        // 渠道编码
 | 
			
		||||
        "payCode": null,
 | 
			
		||||
        // 商户对象
 | 
			
		||||
        "payMerchant": {
 | 
			
		||||
          // 编号
 | 
			
		||||
          "id": null,
 | 
			
		||||
          // 名称
 | 
			
		||||
          "name": null
 | 
			
		||||
        },
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
    this.handleGetMerchantListByName(null);
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getAppPage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        status: undefined,
 | 
			
		||||
        remark: undefined,
 | 
			
		||||
        payNotifyUrl: undefined,
 | 
			
		||||
        refundNotifyUrl: undefined,
 | 
			
		||||
        merchantId: undefined,
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.title = "添加支付应用信息";
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      getApp(id).then(response => {
 | 
			
		||||
        this.form = response.data;
 | 
			
		||||
        this.open = true;
 | 
			
		||||
        this.title = "修改支付应用信息";
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    // 用户状态修改
 | 
			
		||||
    handleStatusChange(row) {
 | 
			
		||||
      let text = row.status === CommonStatusEnum.ENABLE ? "启用" : "停用";
 | 
			
		||||
      this.$modal.confirm('确认要"' + text + '""' + row.name + '"应用吗?').then(function () {
 | 
			
		||||
        return changeAppStatus(row.id, row.status);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.$modal.msgSuccess(text + "成功");
 | 
			
		||||
      }).catch(function () {
 | 
			
		||||
        row.status = row.status === CommonStatusEnum.ENABLE ? CommonStatusEnum.DISABLE
 | 
			
		||||
          : CommonStatusEnum.ENABLE;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 修改的提交
 | 
			
		||||
        if (this.form.id != null) {
 | 
			
		||||
          updateApp(this.form).then(response => {
 | 
			
		||||
            this.$modal.msgSuccess("修改成功");
 | 
			
		||||
            this.open = false;
 | 
			
		||||
            this.getList();
 | 
			
		||||
          });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 添加的提交
 | 
			
		||||
        createApp(this.form).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("新增成功");
 | 
			
		||||
          this.open = false;
 | 
			
		||||
          this.getList();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      this.$modal.confirm('是否确认删除支付应用信息编号为"' + row.id + '"的数据项?').then(function () {
 | 
			
		||||
        return deleteApp(row.id);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("删除成功");
 | 
			
		||||
      }).catch(() => {
 | 
			
		||||
        this.$message({
 | 
			
		||||
          type: 'info',
 | 
			
		||||
          message: '已取消删除'
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 导出按钮操作 */
 | 
			
		||||
    handleExport() {
 | 
			
		||||
      // 处理查询参数
 | 
			
		||||
      let params = {...this.queryParams};
 | 
			
		||||
      params.pageNo = undefined;
 | 
			
		||||
      params.pageSize = undefined;
 | 
			
		||||
      // 执行导出
 | 
			
		||||
      this.$modal.confirm('是否确认导出所有支付应用信息数据项?').then(function () {
 | 
			
		||||
        return exportAppExcel(params);
 | 
			
		||||
      }).then(response => {
 | 
			
		||||
        this.$download.excel(response, '支付应用信息.xls');
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据商户名称模糊匹配商户信息
 | 
			
		||||
     * @param name 商户名称
 | 
			
		||||
     */
 | 
			
		||||
    handleGetMerchantListByName(name) {
 | 
			
		||||
      getMerchantListByName(name).then(response => {
 | 
			
		||||
        this.merchantList = response.data;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * 修改支付渠道信息
 | 
			
		||||
     */
 | 
			
		||||
    handleUpdateChannel(row, payCode, type) {
 | 
			
		||||
      this.settingChannelParam(row, payCode, type)
 | 
			
		||||
      this.channelParam.edit = true;
 | 
			
		||||
      this.channelParam.loading = true;
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * 新增支付渠道信息
 | 
			
		||||
     */
 | 
			
		||||
    handleCreateChannel(row, payCode, type) {
 | 
			
		||||
      this.settingChannelParam(row, payCode, type)
 | 
			
		||||
      this.channelParam.edit = false;
 | 
			
		||||
      this.channelParam.loading = false;
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * 设置支付渠道信息
 | 
			
		||||
     */
 | 
			
		||||
    settingChannelParam(row, payCode, type) {
 | 
			
		||||
      if (type === PayType.WECHAT) {
 | 
			
		||||
        this.channelParam.wechatOpen = true;
 | 
			
		||||
        this.channelParam.aliPayOpen = false;
 | 
			
		||||
      }
 | 
			
		||||
      if (type === PayType.ALIPAY) {
 | 
			
		||||
        this.channelParam.aliPayOpen = true;
 | 
			
		||||
        this.channelParam.wechatOpen = false;
 | 
			
		||||
      }
 | 
			
		||||
      this.channelParam.edit = false;
 | 
			
		||||
      this.channelParam.loading = false;
 | 
			
		||||
      this.channelParam.appId = row.id;
 | 
			
		||||
      this.channelParam.payCode = payCode;
 | 
			
		||||
      this.channelParam.payMerchant = row.payMerchant;
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据渠道编码判断渠道列表中是否存在
 | 
			
		||||
     * @param channels 渠道列表
 | 
			
		||||
     * @param channelCode 渠道编码
 | 
			
		||||
     */
 | 
			
		||||
    judgeChannelExist(channels, channelCode) {
 | 
			
		||||
      return channels.indexOf(channelCode) !== -1;
 | 
			
		||||
    },
 | 
			
		||||
    refreshTable() {
 | 
			
		||||
      this.getList();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,214 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd">发起订单</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="订单编号" align="center" prop="id" />
 | 
			
		||||
      <el-table-column label="用户编号" align="center" prop="userId" />
 | 
			
		||||
      <el-table-column label="商品名字" align="center" prop="spuName" />
 | 
			
		||||
      <el-table-column label="支付价格" align="center" prop="price">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>¥{{ (scope.row.price / 100.0).toFixed(2) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="退款金额" align="center" prop="refundPrice">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>¥{{ (scope.row.refundPrice / 100.0).toFixed(2) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="支付单号" align="center" prop="payOrderId" />
 | 
			
		||||
      <el-table-column label="是否支付" align="center" prop="payed">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.payed" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="支付时间" align="center" prop="payTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.payTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="退款时间" align="center" prop="refundTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.refundTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handlePay(scope.row)"
 | 
			
		||||
                     v-if="!scope.row.payed">前往支付</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleRefund(scope.row)"
 | 
			
		||||
                     v-if="scope.row.payed && !scope.row.payRefundId">发起退款</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="500px" v-dialogDrag append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
 | 
			
		||||
        <el-form-item label="商品" prop="spuId">
 | 
			
		||||
          <el-select v-model="form.spuId" placeholder="请输入下单商品" clearable size="small" style="width: 380px" >
 | 
			
		||||
            <el-option v-for="item in spus" :key="item.id" :label="item.name" :value="item.id">
 | 
			
		||||
              <span style="float: left">{{ item.name}}</span>
 | 
			
		||||
              <span style="float: right; color: #8492a6; font-size: 13px">¥{{ (item.price / 100.0).toFixed(2) }}</span>
 | 
			
		||||
            </el-option>
 | 
			
		||||
          </el-select>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {createDemoOrder, getDemoOrderPage, refundDemoOrder} from "@/api/pay/demo";
 | 
			
		||||
import {deleteMerchant} from "@/api/pay/merchant";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "PayDemoOrder",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 示例订单列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
      },
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {},
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        spuId: [{ required: true, message: "商品编号不能为空", trigger: "blur" }],
 | 
			
		||||
      },
 | 
			
		||||
      // 商品数组
 | 
			
		||||
      spus: [{
 | 
			
		||||
        id: 1,
 | 
			
		||||
        name: '华为手机',
 | 
			
		||||
        price: 1,
 | 
			
		||||
      }, {
 | 
			
		||||
        id: 2,
 | 
			
		||||
        name: '小米电视',
 | 
			
		||||
        price: 10,
 | 
			
		||||
      }, {
 | 
			
		||||
        id: 3,
 | 
			
		||||
        name: '苹果手表',
 | 
			
		||||
        price: 100,
 | 
			
		||||
      }, {
 | 
			
		||||
        id: 4,
 | 
			
		||||
        name: '华硕笔记本',
 | 
			
		||||
        price: 1000,
 | 
			
		||||
      }, {
 | 
			
		||||
        id: 5,
 | 
			
		||||
        name: '蔚来汽车',
 | 
			
		||||
        price: 200000,
 | 
			
		||||
      }]
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getDemoOrderPage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        spuId: undefined,
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.title = "发起订单";
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 添加的提交
 | 
			
		||||
        createDemoOrder(this.form).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("新增成功");
 | 
			
		||||
          this.open = false;
 | 
			
		||||
          this.getList();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 支付按钮操作 */
 | 
			
		||||
    handlePay(row) {
 | 
			
		||||
      this.$router.push({
 | 
			
		||||
          name: 'PayOrderSubmit',
 | 
			
		||||
          query:{
 | 
			
		||||
            id: row.payOrderId
 | 
			
		||||
          }
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    /** 退款按钮操作 */
 | 
			
		||||
    handleRefund(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认退款编号为"' + id + '"的示例订单?').then(function() {
 | 
			
		||||
        return refundDemoOrder(id);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.getList();
 | 
			
		||||
        this.$modal.msgSuccess("发起退款成功!");
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,282 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
 | 
			
		||||
      <el-form-item label="商户号" prop="no">
 | 
			
		||||
        <el-input v-model="queryParams.no" placeholder="请输入商户号" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="商户全称" prop="name">
 | 
			
		||||
        <el-input v-model="queryParams.name" placeholder="请输入商户全称" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="商户简称" prop="shortName">
 | 
			
		||||
        <el-input v-model="queryParams.shortName" placeholder="请输入商户简称" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="开启状态" prop="status">
 | 
			
		||||
        <el-select v-model="queryParams.status" placeholder="请选择开启状态" clearable>
 | 
			
		||||
          <el-option v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="dict.label" :value="parseInt(dict.value)"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="备注" prop="remark">
 | 
			
		||||
        <el-input v-model="queryParams.remark" placeholder="请输入备注" clearable @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
 | 
			
		||||
                   v-hasPermi="['pay:merchant:create']">新增</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="warning" plain icon="el-icon-download" size="mini" :loading="exportLoading" @click="handleExport"
 | 
			
		||||
                   v-hasPermi="['pay:merchant:export']">导出</el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="商户编号" align="center" prop="id" />
 | 
			
		||||
      <el-table-column label="商户号" align="center" prop="no" />
 | 
			
		||||
      <el-table-column label="商户全称" align="center" prop="name" />
 | 
			
		||||
      <el-table-column label="商户简称" align="center" prop="shortName" />
 | 
			
		||||
      <el-table-column label="开启状态" align="center" prop="status" >
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-switch v-model="scope.row.status" :active-value="0" :inactive-value="1" @change="handleStatusChange(scope.row)" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="备注" align="center" prop="remark" />
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
 | 
			
		||||
                     v-hasPermi="['pay:merchant:update']">修改</el-button>
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
 | 
			
		||||
                     v-hasPermi="['pay:merchant:delete']">删除</el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
 | 
			
		||||
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
 | 
			
		||||
<!--        <el-form-item label="商户号" prop="no">-->
 | 
			
		||||
<!--          <el-input v-model="form.no" placeholder="请输入商户号" />-->
 | 
			
		||||
<!--        </el-form-item>-->
 | 
			
		||||
        <el-form-item label="商户全称" prop="name">
 | 
			
		||||
          <el-input v-model="form.name" placeholder="请输入商户全称" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="商户简称" prop="shortName">
 | 
			
		||||
          <el-input v-model="form.shortName" placeholder="请输入商户简称" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="开启状态" prop="status">
 | 
			
		||||
          <el-radio-group v-model="form.status">
 | 
			
		||||
            <el-radio v-for="dict in statusDictDatas" :key="parseInt(dict.value)" :label="parseInt(dict.value)">
 | 
			
		||||
              {{dict.label}}</el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="备注" prop="remark">
 | 
			
		||||
          <el-input v-model="form.remark" placeholder="请输入备注" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submitForm">确 定</el-button>
 | 
			
		||||
        <el-button @click="cancel">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {
 | 
			
		||||
  createMerchant,
 | 
			
		||||
  updateMerchant,
 | 
			
		||||
  changeMerchantStatus,
 | 
			
		||||
  deleteMerchant,
 | 
			
		||||
  getMerchant,
 | 
			
		||||
  getMerchantPage,
 | 
			
		||||
  exportMerchantExcel
 | 
			
		||||
} from "@/api/pay/merchant";
 | 
			
		||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
 | 
			
		||||
import {CommonStatusEnum} from "@/utils/constants";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "PayMerchant",
 | 
			
		||||
  components: {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 导出遮罩层
 | 
			
		||||
      exportLoading: false,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 支付商户信息列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        no: null,
 | 
			
		||||
        name: null,
 | 
			
		||||
        shortName: null,
 | 
			
		||||
        status: null,
 | 
			
		||||
        remark: null,
 | 
			
		||||
        createTime: []
 | 
			
		||||
      },
 | 
			
		||||
      // 表单参数
 | 
			
		||||
      form: {},
 | 
			
		||||
      // 表单校验
 | 
			
		||||
      rules: {
 | 
			
		||||
        no: [{ required: true, message: "商户号不能为空", trigger: "blur" }],
 | 
			
		||||
        name: [{ required: true, message: "商户全称不能为空", trigger: "blur" }],
 | 
			
		||||
        shortName: [{ required: true, message: "商户简称不能为空", trigger: "blur" }],
 | 
			
		||||
        status: [{ required: true, message: "开启状态不能为空", trigger: "blur" }],
 | 
			
		||||
      },
 | 
			
		||||
      // 商户状态数据字典
 | 
			
		||||
      statusDictDatas: getDictDatas(DICT_TYPE.COMMON_STATUS)
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.getList();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getMerchantPage(this.queryParams).then(response => {
 | 
			
		||||
        console.log(response.data);
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
      this.reset();
 | 
			
		||||
    },
 | 
			
		||||
    /** 表单重置 */
 | 
			
		||||
    reset() {
 | 
			
		||||
      this.form = {
 | 
			
		||||
        id: undefined,
 | 
			
		||||
        no: undefined,
 | 
			
		||||
        name: undefined,
 | 
			
		||||
        shortName: undefined,
 | 
			
		||||
        status: undefined,
 | 
			
		||||
        remark: undefined,
 | 
			
		||||
      };
 | 
			
		||||
      this.resetForm("form");
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 新增按钮操作 */
 | 
			
		||||
    handleAdd() {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      this.open = true;
 | 
			
		||||
      this.title = "添加支付商户信息";
 | 
			
		||||
    },
 | 
			
		||||
    /** 修改按钮操作 */
 | 
			
		||||
    handleUpdate(row) {
 | 
			
		||||
      this.reset();
 | 
			
		||||
      getMerchant(row.id).then(response => {
 | 
			
		||||
        this.form = response.data;
 | 
			
		||||
        this.open = true;
 | 
			
		||||
        this.title = "修改支付商户信息";
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    // 用户状态修改
 | 
			
		||||
    handleStatusChange(row) {
 | 
			
		||||
      let text = row.status === CommonStatusEnum.ENABLE ? "启用" : "停用";
 | 
			
		||||
      this.$modal.confirm('确认要"' + text + '""' + row.name + '"商户吗?').then(function() {
 | 
			
		||||
        return changeMerchantStatus(row.id, row.status);
 | 
			
		||||
      }).then(() => {
 | 
			
		||||
        this.$modal.msgSuccess(text + "成功");
 | 
			
		||||
      }).catch(function() {
 | 
			
		||||
        row.status = row.status === CommonStatusEnum.ENABLE ? CommonStatusEnum.DISABLE
 | 
			
		||||
          : CommonStatusEnum.ENABLE;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交按钮 */
 | 
			
		||||
    submitForm() {
 | 
			
		||||
      this.$refs["form"].validate(valid => {
 | 
			
		||||
        if (!valid) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 修改的提交
 | 
			
		||||
        if (this.form.id != null) {
 | 
			
		||||
          updateMerchant(this.form).then(response => {
 | 
			
		||||
            this.$modal.msgSuccess("修改成功");
 | 
			
		||||
            this.open = false;
 | 
			
		||||
            this.getList();
 | 
			
		||||
          });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 添加的提交
 | 
			
		||||
        createMerchant(this.form).then(response => {
 | 
			
		||||
          this.$modal.msgSuccess("新增成功");
 | 
			
		||||
          this.open = false;
 | 
			
		||||
          this.getList();
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 删除按钮操作 */
 | 
			
		||||
    handleDelete(row) {
 | 
			
		||||
      const id = row.id;
 | 
			
		||||
      this.$modal.confirm('是否确认删除支付商户信息编号为"' + id + '"的数据项?').then(function() {
 | 
			
		||||
          return deleteMerchant(id);
 | 
			
		||||
        }).then(() => {
 | 
			
		||||
          this.getList();
 | 
			
		||||
          this.$modal.msgSuccess("删除成功");
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    /** 导出按钮操作 */
 | 
			
		||||
    handleExport() {
 | 
			
		||||
      // 处理查询参数
 | 
			
		||||
      let params = {...this.queryParams};
 | 
			
		||||
      params.pageNo = undefined;
 | 
			
		||||
      params.pageSize = undefined;
 | 
			
		||||
      // 执行导出
 | 
			
		||||
      this.$modal.confirm('是否确认导出所有支付商户信息数据项?').then(() => {
 | 
			
		||||
          this.exportLoading = true;
 | 
			
		||||
          return exportMerchantExcel(params);
 | 
			
		||||
        }).then(response => {
 | 
			
		||||
          this.$download.excel(response, '支付商户信息.xls');
 | 
			
		||||
          this.exportLoading = false;
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
@@ -1,439 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
 | 
			
		||||
      <el-form-item label="所属商户" prop="merchantId">
 | 
			
		||||
        <el-select v-model="queryParams.merchantId" clearable @clear="()=>{queryParams.merchantId = null}"
 | 
			
		||||
          filterable remote reserve-keyword placeholder="请选择所属商户"  @change="handleGetAppListByMerchantId"
 | 
			
		||||
          :remote-method="handleGetMerchantListByName" :loading="merchantLoading">
 | 
			
		||||
          <el-option v-for="item in merchantList" :key="item.id" :label="item.name" :value="item.id"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="应用编号" prop="appId">
 | 
			
		||||
        <el-select clearable v-model="queryParams.appId" filterable placeholder="请选择应用信息">
 | 
			
		||||
          <el-option v-for="item in appList" :key="item.id" :label="item.name" :value="item.id" />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="渠道编码" prop="channelCode">
 | 
			
		||||
        <el-select v-model="queryParams.channelCode" placeholder="请输入渠道编码" clearable
 | 
			
		||||
                   @clear="()=>{queryParams.channelCode = null}">
 | 
			
		||||
          <el-option v-for="dict in payChannelCodeDictDatum" :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="商户订单编号" prop="merchantOrderId">
 | 
			
		||||
        <el-input v-model="queryParams.merchantOrderId" placeholder="请输入商户订单编号" clearable
 | 
			
		||||
                  @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="渠道订单号" prop="channelOrderNo">
 | 
			
		||||
        <el-input v-model="queryParams.channelOrderNo" placeholder="请输入渠道订单号" clearable
 | 
			
		||||
                  @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="支付状态" prop="status">
 | 
			
		||||
        <el-select v-model="queryParams.status" placeholder="请选择支付状态" clearable size="small">
 | 
			
		||||
          <el-option v-for="dict in payOrderDictDatum" :key="parseInt(dict.value)"
 | 
			
		||||
                     :label="dict.label" :value="parseInt(dict.value)"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="退款状态" prop="refundStatus">
 | 
			
		||||
        <el-select v-model="queryParams.refundStatus" placeholder="请选择退款状态" clearable>
 | 
			
		||||
          <el-option v-for="dict in payOrderRefundDictDatum" :key="parseInt(dict.value)"
 | 
			
		||||
                     :label="dict.label" :value="parseInt(dict.value)"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="回调商户状态" prop="notifyStatus">
 | 
			
		||||
        <el-select v-model="queryParams.notifyStatus" placeholder="请选择订单回调商户状态" clearable>
 | 
			
		||||
          <el-option v-for="dict in payOrderNotifyDictDatum" :key="parseInt(dict.value)"
 | 
			
		||||
                     :label="dict.label" :value="parseInt(dict.value)"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
 | 
			
		||||
                   v-hasPermi="['pay:order:export']">导出
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="订单编号" align="center" prop="id" width="80"/>
 | 
			
		||||
<!--      <el-table-column label="商户名称" align="center" prop="merchantName" width="120"/>-->
 | 
			
		||||
<!--      <el-table-column label="应用名称" align="center" prop="appName" width="120"/>-->
 | 
			
		||||
      <el-table-column label="支付渠道" align="center" width="130">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-popover trigger="hover" placement="top">
 | 
			
		||||
            <p>商户名称: {{ scope.row.merchantName }}</p>
 | 
			
		||||
            <p>应用名称: {{ scope.row.appName }}</p>
 | 
			
		||||
            <p>渠道名称: {{ scope.row.channelCodeName }}</p>
 | 
			
		||||
            <div slot="reference" class="name-wrapper">
 | 
			
		||||
              {{ scope.row.channelCodeName }}
 | 
			
		||||
            </div>
 | 
			
		||||
          </el-popover>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="支付订单" align="left" width="280">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <p class="order-font"><el-tag size="mini">商户</el-tag> {{scope.row.merchantOrderId}}</p>
 | 
			
		||||
          <p class="order-font"><el-tag size="mini" type="warning">支付</el-tag> {{scope.row.channelOrderNo}}</p>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
<!--      <el-table-column label="商户订单编号" align="center" prop="merchantOrderId" width="140"/>-->
 | 
			
		||||
<!--      <el-table-column label="渠道订单号" align="center" prop="channelOrderNo" width="140"/>-->
 | 
			
		||||
      <el-table-column label="商品标题" align="center" prop="subject" width="180" :show-overflow-tooltip="true"/>
 | 
			
		||||
      <el-table-column label="支付金额" align="center" prop="amount" width="100">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          ¥{{ parseFloat(scope.row.amount / 100).toFixed(2) }}
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="手续金额" align="center" prop="channelFeeAmount" width="100">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          ¥{{ parseFloat(scope.row.channelFeeAmount / 100).toFixed(2) }}
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="退款金额" align="center" prop="refundAmount" width="100">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          ¥{{ parseFloat(scope.row.refundAmount / 100).toFixed(2) }}
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="支付状态" align="center" prop="status">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.PAY_ORDER_STATUS" :value="scope.row.status" />
 | 
			
		||||
        </template>
 | 
			
		||||
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
<!--      <el-table-column label="退款状态" align="center" prop="refundStatus">-->
 | 
			
		||||
<!--        <template v-slot="scope">-->
 | 
			
		||||
<!--          <span>{{ getDictDataLabel(DICT_TYPE.PAY_ORDER_REFUND_STATUS, scope.row.refundStatus) }}</span>-->
 | 
			
		||||
<!--        </template>-->
 | 
			
		||||
<!--      </el-table-column>-->
 | 
			
		||||
      <el-table-column label="回调状态" align="center" prop="notifyStatus" width="100">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="scope.row.notifyStatus" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="100">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="支付时间" align="center" prop="successTime" width="100">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.successTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-search" @click="handleQueryDetails(scope.row)"
 | 
			
		||||
                     v-hasPermi="['pay:order:query']">查看详情
 | 
			
		||||
          </el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog title="订单详情" :visible.sync="open" width="50%">
 | 
			
		||||
      <el-descriptions :column="2" label-class-name="desc-label">
 | 
			
		||||
        <el-descriptions-item label="商户名称">{{ orderDetail.merchantName }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="应用名称">{{ orderDetail.appName }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="商品名称">{{ orderDetail.subject }}</el-descriptions-item>
 | 
			
		||||
      </el-descriptions>
 | 
			
		||||
      <el-divider></el-divider>
 | 
			
		||||
      <el-descriptions :column="2" label-class-name="desc-label">
 | 
			
		||||
        <el-descriptions-item label="商户订单号">
 | 
			
		||||
          <el-tag size="small">{{ orderDetail.merchantOrderId }}</el-tag>
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="渠道订单号">
 | 
			
		||||
          <el-tag class="tag-purple" size="small">{{ orderDetail.channelOrderNo }}</el-tag>
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="支付订单号">
 | 
			
		||||
          <el-tag v-if="orderDetail.payOrderExtension.no !== ''" class="tag-pink" size="small">
 | 
			
		||||
            {{ orderDetail.payOrderExtension.no }}
 | 
			
		||||
          </el-tag>
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="金额">
 | 
			
		||||
          <el-tag type="success" size="small">{{ parseFloat(orderDetail.amount / 100, 2) }}</el-tag>
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="手续费">
 | 
			
		||||
          <el-tag type="warning" size="small">{{ parseFloat(orderDetail.channelFeeAmount / 100, 2) }}</el-tag>
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="手续费比例">
 | 
			
		||||
          {{ parseFloat(orderDetail.channelFeeRate / 100, 2) }}%
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="支付状态">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.PAY_ORDER_STATUS" :value="orderDetail.status" />
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="回调状态">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="orderDetail.notifyStatus" />
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="回调地址">{{ orderDetail.notifyUrl }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="创建时间">{{ parseTime(orderDetail.createTime) }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="支付时间">{{ parseTime(orderDetail.successTime) }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="失效时间">{{ parseTime(orderDetail.expireTime) }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="通知时间">{{ parseTime(orderDetail.notifyTime) }}</el-descriptions-item>
 | 
			
		||||
      </el-descriptions>
 | 
			
		||||
      <el-divider></el-divider>
 | 
			
		||||
      <el-descriptions :column="2" label-class-name="desc-label">
 | 
			
		||||
        <el-descriptions-item label="支付渠道">{{ orderDetail.channelCodeName }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="支付IP">{{ orderDetail.userIp }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="退款状态">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.PAY_ORDER_REFUND_STATUS" :value="orderDetail.refundStatus" />
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="退款次数">{{ orderDetail.refundTimes }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="退款金额">
 | 
			
		||||
          <el-tag type="warning">
 | 
			
		||||
            {{ parseFloat(orderDetail.refundAmount / 100, 2) }}
 | 
			
		||||
          </el-tag>
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
      </el-descriptions>
 | 
			
		||||
      <el-divider></el-divider>
 | 
			
		||||
      <el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border>
 | 
			
		||||
        <el-descriptions-item label="商品描述">
 | 
			
		||||
          {{ orderDetail.body }}
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="支付通道异步回调内容">
 | 
			
		||||
          {{ orderDetail.payOrderExtension.channelNotifyData }}
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
      </el-descriptions>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { getOrderDetail, getOrderPage, exportOrderExcel} from "@/api/pay/order";
 | 
			
		||||
import {getMerchantListByName} from "@/api/pay/merchant";
 | 
			
		||||
import {getAppListByMerchantId} from "@/api/pay/app";
 | 
			
		||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
 | 
			
		||||
import { getNowDateTime} from "@/utils/ruoyi";
 | 
			
		||||
 | 
			
		||||
const defaultOrderDetail = {
 | 
			
		||||
  merchantName: '',
 | 
			
		||||
  appName: '',
 | 
			
		||||
  channelCodeName: '',
 | 
			
		||||
  subject: '',
 | 
			
		||||
  merchantOrderId: null,
 | 
			
		||||
  channelOrderNo: '',
 | 
			
		||||
  body: '',
 | 
			
		||||
  amount: null,
 | 
			
		||||
  channelFeeRate: null,
 | 
			
		||||
  channelFeeAmount: null,
 | 
			
		||||
  userIp: '',
 | 
			
		||||
  status: null,
 | 
			
		||||
  notifyUrl: '',
 | 
			
		||||
  notifyStatus: null,
 | 
			
		||||
  refundStatus: null,
 | 
			
		||||
  refundTimes: '',
 | 
			
		||||
  refundAmount: null,
 | 
			
		||||
  createTime: '',
 | 
			
		||||
  successTime: '',
 | 
			
		||||
  notifyTime: '',
 | 
			
		||||
  expireTime: '',
 | 
			
		||||
  payOrderExtension: {
 | 
			
		||||
    channelNotifyData: '',
 | 
			
		||||
    no: ''
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "PayOrder",
 | 
			
		||||
  components: {},
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 支付订单列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        merchantId: null,
 | 
			
		||||
        appId: null,
 | 
			
		||||
        channelId: null,
 | 
			
		||||
        channelCode: null,
 | 
			
		||||
        merchantOrderId: null,
 | 
			
		||||
        subject: null,
 | 
			
		||||
        body: null,
 | 
			
		||||
        notifyUrl: null,
 | 
			
		||||
        notifyStatus: null,
 | 
			
		||||
        amount: null,
 | 
			
		||||
        channelFeeRate: null,
 | 
			
		||||
        channelFeeAmount: null,
 | 
			
		||||
        status: null,
 | 
			
		||||
        userIp: null,
 | 
			
		||||
        successExtensionId: null,
 | 
			
		||||
        refundStatus: null,
 | 
			
		||||
        refundTimes: null,
 | 
			
		||||
        refundAmount: null,
 | 
			
		||||
        channelUserId: null,
 | 
			
		||||
        channelOrderNo: null,
 | 
			
		||||
        expireTime: [],
 | 
			
		||||
        successTime: [],
 | 
			
		||||
        notifyTime: [],
 | 
			
		||||
        createTime: []
 | 
			
		||||
      },
 | 
			
		||||
      // 商户加载遮罩层
 | 
			
		||||
      merchantLoading: false,
 | 
			
		||||
      // 商户列表集合
 | 
			
		||||
      merchantList: null,
 | 
			
		||||
      // 支付应用列表集合
 | 
			
		||||
      appList: null,
 | 
			
		||||
      // 支付渠道编码字典数据集合
 | 
			
		||||
      payChannelCodeDictDatum: getDictDatas(DICT_TYPE.PAY_CHANNEL_CODE_TYPE),
 | 
			
		||||
      // 订单回调商户状态字典数据集合
 | 
			
		||||
      payOrderNotifyDictDatum: getDictDatas(DICT_TYPE.PAY_ORDER_NOTIFY_STATUS),
 | 
			
		||||
      // 订单状态字典数据集合
 | 
			
		||||
      payOrderDictDatum: getDictDatas(DICT_TYPE.PAY_ORDER_STATUS),
 | 
			
		||||
      // 订单退款状态字典数据集合
 | 
			
		||||
      payOrderRefundDictDatum: getDictDatas(DICT_TYPE.PAY_ORDER_REFUND_STATUS),
 | 
			
		||||
      orderDetail: JSON.parse(JSON.stringify(defaultOrderDetail)),
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    // 初始化默认时间
 | 
			
		||||
    this.initTime();
 | 
			
		||||
    this.getList();
 | 
			
		||||
    this.handleGetMerchantListByName(null);
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    initTime(){
 | 
			
		||||
      this.queryParams.createTime = [getNowDateTime("00:00:00"), getNowDateTime("23:59:59")];
 | 
			
		||||
    },
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      // 判断选择的日期是否超过了一个月
 | 
			
		||||
      let oneMonthTime = 31 * 24 * 3600 * 1000;
 | 
			
		||||
      if (this.queryParams.createTime == null){
 | 
			
		||||
        this.initTime();
 | 
			
		||||
      } else {
 | 
			
		||||
        let minDateTime = new Date(this.queryParams.createTime[0]).getTime();
 | 
			
		||||
        let maxDateTime = new Date(this.queryParams.createTime[1]).getTime()
 | 
			
		||||
        if (maxDateTime - minDateTime > oneMonthTime) {
 | 
			
		||||
          this.$message.error('时间范围最大为 31 天!');
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getOrderPage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.initTime();
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * 查看订单详情
 | 
			
		||||
     */
 | 
			
		||||
    handleQueryDetails(row) {
 | 
			
		||||
      this.orderDetail = JSON.parse(JSON.stringify(defaultOrderDetail));
 | 
			
		||||
      getOrderDetail(row.id).then(response => {
 | 
			
		||||
        this.orderDetail = response.data;
 | 
			
		||||
        if (response.data.payOrderExtension === null) {
 | 
			
		||||
          this.orderDetail.payOrderExtension = Object.assign(defaultOrderDetail.payOrderExtension, {});
 | 
			
		||||
        }
 | 
			
		||||
        this.open = true;
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
    /** 导出按钮操作 */
 | 
			
		||||
    handleExport() {
 | 
			
		||||
      // 处理查询参数
 | 
			
		||||
      let params = {...this.queryParams};
 | 
			
		||||
      params.pageNo = undefined;
 | 
			
		||||
      params.pageSize = undefined;
 | 
			
		||||
      // 执行导出
 | 
			
		||||
      this.$modal.confirm('是否确认导出所有支付订单数据项?').then(function () {
 | 
			
		||||
        return exportOrderExcel(params);
 | 
			
		||||
      }).then(response => {
 | 
			
		||||
        this.$download.excel(response, '支付订单.xls');
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据商户名称模糊匹配商户信息
 | 
			
		||||
     * @param name 商户名称
 | 
			
		||||
     */
 | 
			
		||||
    handleGetMerchantListByName(name) {
 | 
			
		||||
      getMerchantListByName(name).then(response => {
 | 
			
		||||
        this.merchantList = response.data;
 | 
			
		||||
        this.merchantLoading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据商户 ID 查询支付应用信息
 | 
			
		||||
     */
 | 
			
		||||
    handleGetAppListByMerchantId() {
 | 
			
		||||
      this.queryParams.appId = null;
 | 
			
		||||
      getAppListByMerchantId(this.queryParams.merchantId).then(response => {
 | 
			
		||||
        this.appList = response.data;
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
<style>
 | 
			
		||||
.desc-label {
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.tag-purple {
 | 
			
		||||
  color: #722ed1;
 | 
			
		||||
  background: #f9f0ff;
 | 
			
		||||
  border-color: #d3adf7;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.tag-cyan {
 | 
			
		||||
  color: #13c2c2;
 | 
			
		||||
  background: #e6fffb;
 | 
			
		||||
  border-color: #87e8de;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.tag-pink {
 | 
			
		||||
  color: #eb2f96;
 | 
			
		||||
  background: #fff0f6;
 | 
			
		||||
  border-color: #ffadd2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.order-font{
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
  padding: 2px 0;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,397 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <!-- 支付信息 -->
 | 
			
		||||
    <el-card v-loading="loading">
 | 
			
		||||
      <el-descriptions title="支付信息" :column="3" border>
 | 
			
		||||
        <el-descriptions-item label="支付单号">{{ payOrder.id }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="商品标题">{{ payOrder.subject }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="商品内容">{{ payOrder.body }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="支付金额">¥{{ (payOrder.amount / 100.0).toFixed(2) }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="创建时间">{{ parseTime(payOrder.createTime) }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="过期时间">{{ parseTime(payOrder.expireTime) }}</el-descriptions-item>
 | 
			
		||||
      </el-descriptions>
 | 
			
		||||
    </el-card>
 | 
			
		||||
 | 
			
		||||
    <!-- 支付选择框 -->
 | 
			
		||||
    <el-card style="margin-top: 10px" v-loading="submitLoading"  element-loading-text="提交支付中...">
 | 
			
		||||
      <!-- 支付宝 -->
 | 
			
		||||
      <el-descriptions title="选择支付宝支付">
 | 
			
		||||
      </el-descriptions>
 | 
			
		||||
      <div class="pay-channel-container">
 | 
			
		||||
        <div class="box" v-for="channel in aliPayChannels" :key="channel.code" @click="submit(channel.code)">
 | 
			
		||||
          <img :src="icons[channel.code]">
 | 
			
		||||
          <div class="title">{{ channel.name }}</div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <!-- 微信支付 -->
 | 
			
		||||
      <el-descriptions title="选择微信支付" style="margin-top: 20px;" />
 | 
			
		||||
      <div class="pay-channel-container">
 | 
			
		||||
        <div class="box" v-for="channel in wxPayChannels" :key="channel.code">
 | 
			
		||||
          <img :src="icons[channel.code]">
 | 
			
		||||
          <div class="title">{{ channel.name }}</div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <!-- 其它支付 -->
 | 
			
		||||
      <el-descriptions title="选择其它支付" style="margin-top: 20px;" />
 | 
			
		||||
      <div class="pay-channel-container">
 | 
			
		||||
        <div class="box" v-for="channel in otherPayChannels" :key="channel.code">
 | 
			
		||||
          <img :src="icons[channel.code]">
 | 
			
		||||
          <div class="title">{{ channel.name }}</div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-card>
 | 
			
		||||
 | 
			
		||||
    <!-- 展示形式:二维码 URL -->
 | 
			
		||||
    <el-dialog :title="qrCode.title" :visible.sync="qrCode.visible" width="350px" append-to-body
 | 
			
		||||
               :close-on-press-escape="false">
 | 
			
		||||
      <qrcode-vue :value="qrCode.url" size="310" level="L" />
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
 | 
			
		||||
    <!-- 展示形式:IFrame -->
 | 
			
		||||
    <el-dialog :title="iframe.title" :visible.sync="iframe.visible" width="800px" height="800px" append-to-body
 | 
			
		||||
               :close-on-press-escape="false">
 | 
			
		||||
      <iframe :src="iframe.url" width="100%" />
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
 | 
			
		||||
    <!-- 展示形式:Form -->
 | 
			
		||||
    <div ref="formRef" v-html="form.value" />
 | 
			
		||||
 | 
			
		||||
    <!-- 展示形式:BarCode 条形码 -->
 | 
			
		||||
    <el-dialog :title="barCode.title" :visible.sync="barCode.visible" width="500px" append-to-body
 | 
			
		||||
               :close-on-press-escape="false">
 | 
			
		||||
      <el-form ref="form" label-width="80px">
 | 
			
		||||
        <el-row>
 | 
			
		||||
          <el-col :span="24">
 | 
			
		||||
            <el-form-item label="条形码" prop="name">
 | 
			
		||||
              <el-input v-model="barCode.value" placeholder="请输入条形码" required />
 | 
			
		||||
            </el-form-item>
 | 
			
		||||
          </el-col>
 | 
			
		||||
          <el-col :span="24">
 | 
			
		||||
            <div style="text-align: right">
 | 
			
		||||
              或使用
 | 
			
		||||
              <el-link type="danger" target="_blank"
 | 
			
		||||
                       href="https://baike.baidu.com/item/条码支付/10711903">(扫码枪/扫码盒)</el-link>
 | 
			
		||||
              扫码
 | 
			
		||||
            </div>
 | 
			
		||||
          </el-col>
 | 
			
		||||
        </el-row>
 | 
			
		||||
      </el-form>
 | 
			
		||||
      <div slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button type="primary" @click="submit0(barCode.channelCode)"
 | 
			
		||||
                   :disabled="barCode.value.length === 0">确认支付</el-button>
 | 
			
		||||
        <el-button @click="barCode.visible = false">取 消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script>
 | 
			
		||||
import QrcodeVue from 'qrcode.vue'
 | 
			
		||||
import { DICT_TYPE, getDictDatas } from "@/utils/dict";
 | 
			
		||||
import { getOrder, submitOrder } from '@/api/pay/order';
 | 
			
		||||
import {PayChannelEnum, PayDisplayModeEnum, PayOrderStatusEnum} from "@/utils/constants";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "PayOrderSubmit",
 | 
			
		||||
  components: {
 | 
			
		||||
    QrcodeVue,
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      id: undefined, // 请假编号
 | 
			
		||||
      loading: false, // 支付信息的 loading
 | 
			
		||||
      payOrder: {}, // 支付信息
 | 
			
		||||
      aliPayChannels: [], // 阿里支付的渠道
 | 
			
		||||
      wxPayChannels: [], // 微信支付的渠道
 | 
			
		||||
      otherPayChannels: [], // 其它的支付渠道
 | 
			
		||||
      icons: {
 | 
			
		||||
        alipay_qr: require("@/assets/images/pay/icon/alipay_qr.svg"),
 | 
			
		||||
        alipay_app: require("@/assets/images/pay/icon/alipay_app.svg"),
 | 
			
		||||
        alipay_wap: require("@/assets/images/pay/icon/alipay_wap.svg"),
 | 
			
		||||
        alipay_pc: require("@/assets/images/pay/icon/alipay_pc.svg"),
 | 
			
		||||
        alipay_bar: require("@/assets/images/pay/icon/alipay_bar.svg"),
 | 
			
		||||
        wx_app: require("@/assets/images/pay/icon/wx_app.svg"),
 | 
			
		||||
        wx_lite: require("@/assets/images/pay/icon/wx_lite.svg"),
 | 
			
		||||
        wx_pub: require("@/assets/images/pay/icon/wx_pub.svg"),
 | 
			
		||||
        mock: require("@/assets/images/pay/icon/mock.svg"),
 | 
			
		||||
      },
 | 
			
		||||
      submitLoading: false, // 提交支付的 loading
 | 
			
		||||
      interval: undefined, // 定时任务,轮询是否完成支付
 | 
			
		||||
      qrCode: { // 展示形式:二维码
 | 
			
		||||
        url: '',
 | 
			
		||||
        title: '',
 | 
			
		||||
        visible: false,
 | 
			
		||||
      },
 | 
			
		||||
      iframe: { // 展示形式:iframe
 | 
			
		||||
        url: '',
 | 
			
		||||
        title: '',
 | 
			
		||||
        visible: false
 | 
			
		||||
      },
 | 
			
		||||
      form: { // 展示形式:form
 | 
			
		||||
        html: '',
 | 
			
		||||
      },
 | 
			
		||||
      barCode: { // 展示形式:条形码
 | 
			
		||||
        channelCode: '',
 | 
			
		||||
        value: '',
 | 
			
		||||
        title: '',
 | 
			
		||||
        visible: false,
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.id = this.$route.query.id;
 | 
			
		||||
    this.getDetail();
 | 
			
		||||
    this.initPayChannels();
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    /** 初始化支付渠道 */
 | 
			
		||||
    initPayChannels() {
 | 
			
		||||
      // 微信支付
 | 
			
		||||
      for (const dict of getDictDatas(DICT_TYPE.PAY_CHANNEL_CODE_TYPE)) {
 | 
			
		||||
        const payChannel = {
 | 
			
		||||
          name: dict.label,
 | 
			
		||||
          code: dict.value
 | 
			
		||||
        }
 | 
			
		||||
        if (dict.value.indexOf('wx_') === 0) {
 | 
			
		||||
          this.wxPayChannels.push(payChannel);
 | 
			
		||||
        } else if (dict.value.indexOf('alipay_') === 0) {
 | 
			
		||||
          this.aliPayChannels.push(payChannel);
 | 
			
		||||
        } else {
 | 
			
		||||
          this.otherPayChannels.push(payChannel);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    /** 获得支付信息 */
 | 
			
		||||
    getDetail() {
 | 
			
		||||
      // 1.1 未传递订单编号
 | 
			
		||||
      if (!this.id) {
 | 
			
		||||
        this.$message.error('未传递支付单号,无法查看对应的支付信息');
 | 
			
		||||
        this.goBackToList();
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      getOrder(this.id).then(response => {
 | 
			
		||||
        // 1.2 无法查询到支付信息
 | 
			
		||||
        if (!response.data) {
 | 
			
		||||
          this.$message.error('支付订单不存在,请检查!');
 | 
			
		||||
          this.goBackToList();
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        // 1.3 订单已支付
 | 
			
		||||
        if (response.data.status !== PayOrderStatusEnum.WAITING.status) {
 | 
			
		||||
          this.$message.error('支付订单不处于待支付状态,请检查!');
 | 
			
		||||
          this.goBackToList();
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 2. 可以展示
 | 
			
		||||
        this.payOrder = response.data;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交支付 */
 | 
			
		||||
    submit(channelCode) {
 | 
			
		||||
      // 条形码支付,需要特殊处理
 | 
			
		||||
      if (channelCode === PayChannelEnum.ALIPAY_BAR.code) {
 | 
			
		||||
        this.barCode = {
 | 
			
		||||
          channelCode: channelCode,
 | 
			
		||||
          value: '',
 | 
			
		||||
          title: '“支付宝”条码支付',
 | 
			
		||||
          visible: true
 | 
			
		||||
        }
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // 默认的提交处理
 | 
			
		||||
      this.submit0(channelCode)
 | 
			
		||||
    },
 | 
			
		||||
    submit0(channelCode) {
 | 
			
		||||
      this.submitLoading = true
 | 
			
		||||
      submitOrder({
 | 
			
		||||
        id: this.id,
 | 
			
		||||
        channelCode: channelCode,
 | 
			
		||||
        ...this.buildSubmitParam(channelCode)
 | 
			
		||||
      }).then(response => {
 | 
			
		||||
        const data = response.data
 | 
			
		||||
        if (data.displayMode === PayDisplayModeEnum.IFRAME.mode) {
 | 
			
		||||
          this.displayIFrame(channelCode, data)
 | 
			
		||||
        } else if (data.displayMode === PayDisplayModeEnum.URL.mode) {
 | 
			
		||||
          this.displayUrl(channelCode, data)
 | 
			
		||||
        } else if (data.displayMode === PayDisplayModeEnum.FORM.mode) {
 | 
			
		||||
          this.displayForm(channelCode, data)
 | 
			
		||||
        } else if (data.displayMode === PayDisplayModeEnum.QR_CODE.mode) {
 | 
			
		||||
          this.displayQrCode(channelCode, data)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 打开轮询任务
 | 
			
		||||
        this.createQueryInterval()
 | 
			
		||||
      }).catch(() => {
 | 
			
		||||
        this.submitLoading = false
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 构建提交支付的额外参数 */
 | 
			
		||||
    buildSubmitParam(channelCode) {
 | 
			
		||||
      // ① 支付宝 PC 支付时,有多种展示形态
 | 
			
		||||
      if (channelCode === PayChannelEnum.ALIPAY_PC.code) {
 | 
			
		||||
        // 情况【前置模式】:将二维码前置到商户的订单确认页的模式。需要商户在自己的页面中以 iframe 方式请求支付宝页面。具体支持的枚举值有以下几种:
 | 
			
		||||
        // 0:订单码-简约前置模式,对应 iframe 宽度不能小于 600px,高度不能小于 300px
 | 
			
		||||
        // return {
 | 
			
		||||
        //   "channelExtras": {
 | 
			
		||||
        //     "qr_pay_mode": "0"
 | 
			
		||||
        //   }
 | 
			
		||||
        // }
 | 
			
		||||
        // 1:订单码-前置模式,对应iframe 宽度不能小于 300px,高度不能小于 600px
 | 
			
		||||
        // return {
 | 
			
		||||
        //   "channelExtras": {
 | 
			
		||||
        //     "qr_pay_mode": "1"
 | 
			
		||||
        //   }
 | 
			
		||||
        // }
 | 
			
		||||
        // 3:订单码-迷你前置模式,对应 iframe 宽度不能小于 75px,高度不能小于 75px
 | 
			
		||||
        // return {
 | 
			
		||||
        //   "channelExtras": {
 | 
			
		||||
        //     "qr_pay_mode": "3"
 | 
			
		||||
        //   }
 | 
			
		||||
        // }
 | 
			
		||||
        // 4:订单码-可定义宽度的嵌入式二维码,商户可根据需要设定二维码的大小
 | 
			
		||||
        // return {
 | 
			
		||||
        //   "channelExtras": {
 | 
			
		||||
        //     "qr_pay_mode": "4"
 | 
			
		||||
        //   }
 | 
			
		||||
        // }
 | 
			
		||||
        // 情况【跳转模式】:跳转模式下,用户的扫码界面是由支付宝生成的,不在商户的域名下。支持传入的枚举值有
 | 
			
		||||
        return {
 | 
			
		||||
          "channelExtras": {
 | 
			
		||||
            "qr_pay_mode": "2"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        // 情况【表单模式】:直接提交当前页面到支付宝
 | 
			
		||||
        // return {
 | 
			
		||||
        //   displayMode: PayDisplayModeEnum.FORM.mode
 | 
			
		||||
        // }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // ② 支付宝 Wap 支付时,引导手机扫码支付
 | 
			
		||||
      if (channelCode === PayChannelEnum.ALIPAY_WAP.code) {
 | 
			
		||||
        return {
 | 
			
		||||
          displayMode: PayDisplayModeEnum.QR_CODE.mode
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // ③ 支付宝 BarCode 支付时,需要传递 authCode 条形码
 | 
			
		||||
      if (channelCode === PayChannelEnum.ALIPAY_BAR.code) {
 | 
			
		||||
        return {
 | 
			
		||||
          "channelExtras": {
 | 
			
		||||
            "auth_code": this.barCode.value
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      return {}
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交支付后,IFrame 内置 URL 的展示形式 */
 | 
			
		||||
    displayIFrame(channelCode, data) {
 | 
			
		||||
      // TODO 芋艿:目前有点奇怪,支付宝总是会显示“支付环境存在风险”
 | 
			
		||||
      this.iframe = {
 | 
			
		||||
        title: '支付窗口',
 | 
			
		||||
        url: data.displayContent,
 | 
			
		||||
        visible: true
 | 
			
		||||
      }
 | 
			
		||||
      this.submitLoading = false
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交支付后,URL 的展示形式 */
 | 
			
		||||
    displayUrl(channelCode, data) {
 | 
			
		||||
      window.open(data.displayContent)
 | 
			
		||||
      this.submitLoading = false
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交支付后,Form 的展示形式 */
 | 
			
		||||
    displayForm(channelCode, data) {
 | 
			
		||||
      // 渲染支付页面
 | 
			
		||||
      this.form = {
 | 
			
		||||
        value: data.displayContent
 | 
			
		||||
      }
 | 
			
		||||
      // 防抖避免重复支付
 | 
			
		||||
      this.$nextTick(() => {
 | 
			
		||||
        // 提交支付表单
 | 
			
		||||
        this.$refs.formRef.children[0].submit();
 | 
			
		||||
        setTimeout(() => {
 | 
			
		||||
          this.submitLoading = false
 | 
			
		||||
        }, 1000);
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 提交支付后(支付宝扫码支付) */
 | 
			
		||||
    displayQrCode(channelCode, data) {
 | 
			
		||||
      let title = '请使用手机浏览器“扫一扫”';
 | 
			
		||||
      if (channelCode === PayChannelEnum.ALIPAY_WAP.code) {
 | 
			
		||||
        // 考虑到 WAP 测试,所以引导手机浏览器搞
 | 
			
		||||
      } else if (channelCode.indexOf('alipay_') === 0) {
 | 
			
		||||
        title = '请使用支付宝“扫一扫”扫码支付';
 | 
			
		||||
      } else if (channelCode.indexOf('wx_') === 0) {
 | 
			
		||||
        title = '请使用微信“扫一扫”扫码支付';
 | 
			
		||||
      }
 | 
			
		||||
      this.qrCode = {
 | 
			
		||||
        title: title,
 | 
			
		||||
        url: data.displayContent,
 | 
			
		||||
        visible: true
 | 
			
		||||
      }
 | 
			
		||||
      this.submitLoading = false
 | 
			
		||||
    },
 | 
			
		||||
    /** 轮询查询任务 */
 | 
			
		||||
    createQueryInterval() {
 | 
			
		||||
      if (this.interval) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
      this.interval = setInterval(() => {
 | 
			
		||||
        getOrder(this.id).then(response => {
 | 
			
		||||
          // 已支付
 | 
			
		||||
          if (response.data.status === PayOrderStatusEnum.SUCCESS.status) {
 | 
			
		||||
            this.clearQueryInterval();
 | 
			
		||||
            this.$message.success('支付成功!');
 | 
			
		||||
            this.goBackToList();
 | 
			
		||||
          }
 | 
			
		||||
          // 已取消
 | 
			
		||||
          if (response.data.status === PayOrderStatusEnum.CLOSED.status) {
 | 
			
		||||
            this.clearQueryInterval();
 | 
			
		||||
            this.$message.error('支付已关闭!');
 | 
			
		||||
            this.goBackToList();
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
      }, 1000 * 2)
 | 
			
		||||
    },
 | 
			
		||||
    /** 清空查询任务 */
 | 
			
		||||
    clearQueryInterval() {
 | 
			
		||||
      // 清空各种弹窗
 | 
			
		||||
      this.qrCode = {
 | 
			
		||||
        title: '',
 | 
			
		||||
        url: '',
 | 
			
		||||
        visible: false
 | 
			
		||||
      }
 | 
			
		||||
      // 清空任务
 | 
			
		||||
      clearInterval(this.interval)
 | 
			
		||||
      this.interval = undefined
 | 
			
		||||
    },
 | 
			
		||||
    /** 回到列表 **/
 | 
			
		||||
    goBackToList() {
 | 
			
		||||
      this.$tab.closePage();
 | 
			
		||||
      this.$router.go(-1);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
.pay-channel-container {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  margin-top: -10px;
 | 
			
		||||
  .box {
 | 
			
		||||
    width: 130px;
 | 
			
		||||
    border: 1px solid #e6ebf5;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    padding-top: 10px;
 | 
			
		||||
    padding-bottom: 5px;
 | 
			
		||||
    margin-right: 10px;
 | 
			
		||||
    img {
 | 
			
		||||
      width: 40px;
 | 
			
		||||
      height: 40px;
 | 
			
		||||
    }
 | 
			
		||||
    .title {
 | 
			
		||||
      padding-top: 5px
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,486 +0,0 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
 | 
			
		||||
      <el-form-item label="所属商户" prop="merchantId">
 | 
			
		||||
        <el-select v-model="queryParams.merchantId" clearable @clear="()=>{queryParams.merchantId = null}"
 | 
			
		||||
          filterable remote reserve-keyword placeholder="请选择所属商户" @change="handleGetAppListByMerchantId"
 | 
			
		||||
          :remote-method="handleGetMerchantListByName" :loading="merchantLoading">
 | 
			
		||||
          <el-option v-for="item in merchantList" :key="item.id" :label="item.name" :value="item.id" />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="应用编号" prop="appId">
 | 
			
		||||
        <el-select clearable v-model="queryParams.appId" filterable placeholder="请选择应用信息">
 | 
			
		||||
          <el-option v-for="item in appList" :key="item.id" :label="item.name" :value="item.id" />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="渠道编码" prop="channelCode">
 | 
			
		||||
        <el-select v-model="queryParams.channelCode" placeholder="请输入渠道编码" clearable
 | 
			
		||||
                   @clear="()=>{queryParams.channelCode = null}">
 | 
			
		||||
          <el-option v-for="dict in payChannelCodeDictDatum" :key="dict.value" :label="dict.label" :value="dict.value"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="退款类型" prop="type">
 | 
			
		||||
        <el-select v-model="queryParams.type" placeholder="请选择退款类型" clearable>
 | 
			
		||||
          <el-option v-for="dict in payRefundOrderTypeDictDatum" :key="parseInt(dict.value)"
 | 
			
		||||
                     :label="dict.label" :value="parseInt(dict.value)"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="商户退款订单号" prop="merchantRefundNo">
 | 
			
		||||
        <el-input v-model="queryParams.merchantRefundNo" placeholder="请输入商户退款订单号" clearable
 | 
			
		||||
                  @keyup.enter.native="handleQuery"/>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="退款状态" prop="status">
 | 
			
		||||
        <el-select v-model="queryParams.status" placeholder="请选择退款状态" clearable>
 | 
			
		||||
          <el-option v-for="dict in payRefundOrderDictDatum" :key="parseInt(dict.value)"
 | 
			
		||||
                     :label="dict.label" :value="parseInt(dict.value)"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="退款回调状态" prop="notifyStatus">
 | 
			
		||||
        <el-select v-model="queryParams.notifyStatus" placeholder="请选择通知商户退款结果的回调状态" clearable>
 | 
			
		||||
          <el-option v-for="dict in payOrderNotifyDictDatum" :key="parseInt(dict.value)"
 | 
			
		||||
                     :label="dict.label" :value="parseInt(dict.value)"/>
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="创建时间" prop="createTime">
 | 
			
		||||
        <el-date-picker v-model="queryParams.createTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" type="daterange"
 | 
			
		||||
                        range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="['00:00:00', '23:59:59']" />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
 | 
			
		||||
        <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
 | 
			
		||||
    <!-- 操作工具栏 -->
 | 
			
		||||
    <el-row :gutter="10" class="mb8">
 | 
			
		||||
      <el-col :span="1.5">
 | 
			
		||||
        <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
 | 
			
		||||
                   v-hasPermi="['pay:refund:export']">导出
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </el-col>
 | 
			
		||||
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
 | 
			
		||||
    </el-row>
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <el-table v-loading="loading" :data="list">
 | 
			
		||||
      <el-table-column label="编号" align="center" prop="id"/>
 | 
			
		||||
      <!--      <el-table-column label="商户名称" align="center" prop="merchantName" width="120"/>-->
 | 
			
		||||
      <!--      <el-table-column label="应用名称" align="center" prop="appName" width="120"/>-->
 | 
			
		||||
      <el-table-column label="支付渠道" align="center" width="130">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-popover trigger="hover" placement="top">
 | 
			
		||||
            <p>商户名称: {{ scope.row.merchantName }}</p>
 | 
			
		||||
            <p>应用名称: {{ scope.row.appName }}</p>
 | 
			
		||||
            <p>渠道名称: {{ scope.row.channelCodeName }}</p>
 | 
			
		||||
            <div slot="reference" class="name-wrapper">
 | 
			
		||||
              {{ scope.row.channelCodeName }}
 | 
			
		||||
            </div>
 | 
			
		||||
          </el-popover>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <!--      <el-table-column label="交易订单号" align="center" prop="tradeNo" width="140"/>-->
 | 
			
		||||
      <!--      <el-table-column label="商户订单编号" align="center" prop="merchantOrderId" width="140"/>-->
 | 
			
		||||
      <el-table-column label="商户订单号" align="left" width="230">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <p class="order-font">
 | 
			
		||||
            <el-tag size="mini">退款</el-tag>
 | 
			
		||||
            {{ scope.row.merchantRefundNo }}
 | 
			
		||||
          </p>
 | 
			
		||||
          <p class="order-font">
 | 
			
		||||
            <el-tag type="success">交易</el-tag>
 | 
			
		||||
            {{ scope.row.merchantOrderId }}
 | 
			
		||||
          </p>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="支付订单号" align="center" prop="merchantRefundNo" width="250">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <p class="order-font">
 | 
			
		||||
            <el-tag size="mini">交易</el-tag>
 | 
			
		||||
            {{ scope.row.tradeNo }}
 | 
			
		||||
          </p>
 | 
			
		||||
          <p class="order-font">
 | 
			
		||||
            <el-tag size="mini" type="warning">渠道</el-tag>
 | 
			
		||||
            {{ scope.row.channelOrderNo }}
 | 
			
		||||
          </p>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="支付金额(元)" align="center" prop="payAmount" width="100">
 | 
			
		||||
        <template v-slot="scope" class="">
 | 
			
		||||
          ¥{{ parseFloat(scope.row.payAmount / 100).toFixed(2) }}
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="退款金额(元)" align="center" prop="refundAmount" width="100">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          ¥{{ parseFloat(scope.row.refundAmount / 100).toFixed(2) }}
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="退款类型" align="center" prop="type" width="80">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_TYPE" :value="scope.row.type" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="退款状态" align="center" prop="status">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_STATUS" :value="scope.row.status" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="回调状态" align="center" prop="notifyStatus">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="scope.row.notifyStatus" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="退款原因" align="center" prop="reason" width="140" :show-overflow-tooltip="true"/>
 | 
			
		||||
      <el-table-column label="创建时间" align="center" prop="createTime" width="100">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.createTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="退款成功时间" align="center" prop="successTime" width="100">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <span>{{ parseTime(scope.row.successTime) }}</span>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
 | 
			
		||||
        <template v-slot="scope">
 | 
			
		||||
          <el-button size="mini" type="text" icon="el-icon-search" @click="handleQueryDetails(scope.row)"
 | 
			
		||||
                     v-hasPermi="['pay:order:query']">查看详情
 | 
			
		||||
          </el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页组件 -->
 | 
			
		||||
    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
 | 
			
		||||
                @pagination="getList"/>
 | 
			
		||||
 | 
			
		||||
    <!-- 对话框(添加 / 修改) -->
 | 
			
		||||
    <el-dialog title="退款订单详情" :visible.sync="open" width="700px" append-to-body>
 | 
			
		||||
      <el-descriptions :column="2" label-class-name="desc-label">
 | 
			
		||||
        <el-descriptions-item label="商户名称">{{ refundDetail.merchantName }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="应用名称">{{ refundDetail.appName }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="商品名称">{{ refundDetail.subject }}</el-descriptions-item>
 | 
			
		||||
      </el-descriptions>
 | 
			
		||||
      <el-divider></el-divider>
 | 
			
		||||
      <el-descriptions :column="2" label-class-name="desc-label">
 | 
			
		||||
        <el-descriptions-item label="商户退款单号">
 | 
			
		||||
          <el-tag  size="mini">{{ refundDetail.merchantRefundNo }}</el-tag>
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="商户订单号">{{ refundDetail.merchantOrderId }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="交易订单号">{{ refundDetail.tradeNo }}</el-descriptions-item>
 | 
			
		||||
      </el-descriptions>
 | 
			
		||||
      <el-divider></el-divider>
 | 
			
		||||
      <el-descriptions :column="2" label-class-name="desc-label">
 | 
			
		||||
        <el-descriptions-item label="支付金额">
 | 
			
		||||
          {{ parseFloat(refundDetail.payAmount / 100).toFixed(2) }}
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="退款金额" size="mini">
 | 
			
		||||
          <el-tag class="tag-purple" size="mini">{{ parseFloat(refundDetail.refundAmount / 100).toFixed(2) }}</el-tag>
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="退款类型">
 | 
			
		||||
          <template v-slot="scope">
 | 
			
		||||
            <dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_TYPE" :value="refundDetail.type" />
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="退款状态">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.PAY_REFUND_ORDER_STATUS" :value="refundDetail.status" />
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="创建时间">{{ parseTime(refundDetail.createTime) }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="退款成功时间">{{ parseTime(refundDetail.successTime) }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="退款失效时间">{{ parseTime(refundDetail.expireTime) }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="更新时间">{{ parseTime(refundDetail.updateTime) }}</el-descriptions-item>
 | 
			
		||||
      </el-descriptions>
 | 
			
		||||
      <el-divider></el-divider>
 | 
			
		||||
      <el-descriptions :column="2" label-class-name="desc-label">
 | 
			
		||||
        <el-descriptions-item label="支付渠道">
 | 
			
		||||
          {{ refundDetail.channelCodeName }}
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="支付IP" size="mini">
 | 
			
		||||
          {{refundDetail.userIp}}
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="回调地址">{{ refundDetail.notifyUrl }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="回调状态">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.PAY_ORDER_NOTIFY_STATUS" :value="refundDetail.notifyStatus" />
 | 
			
		||||
        </el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="回调时间">{{ parseTime(refundDetail.notifyTime) }}</el-descriptions-item>
 | 
			
		||||
      </el-descriptions>
 | 
			
		||||
      <el-divider></el-divider>
 | 
			
		||||
      <el-descriptions :column="2" label-class-name="desc-label">
 | 
			
		||||
        <el-descriptions-item label="渠道订单号">{{ refundDetail.channelOrderNo }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="渠道退款单号">{{ refundDetail.channelRefundNo }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="渠道错误码">{{refundDetail.channelErrorCode}}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="渠道错误码描述">{{refundDetail.channelErrorMsg}}</el-descriptions-item>
 | 
			
		||||
      </el-descriptions>
 | 
			
		||||
      <br>
 | 
			
		||||
      <el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border>
 | 
			
		||||
        <el-descriptions-item label="渠道额外参数">{{ refundDetail.channelExtras }}</el-descriptions-item>
 | 
			
		||||
        <el-descriptions-item label="退款原因">{{ refundDetail.reason }}</el-descriptions-item>
 | 
			
		||||
      </el-descriptions>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {getRefundPage, exportRefundExcel, getRefund} from "@/api/pay/refund";
 | 
			
		||||
import {getMerchantListByName} from "@/api/pay/merchant";
 | 
			
		||||
import {getAppListByMerchantId} from "@/api/pay/app";
 | 
			
		||||
import {DICT_TYPE, getDictDatas} from "@/utils/dict";
 | 
			
		||||
import {
 | 
			
		||||
  PayOrderRefundStatusEnum,
 | 
			
		||||
  PayRefundStatusEnum
 | 
			
		||||
} from "@/utils/constants";
 | 
			
		||||
import {getNowDateTime} from "@/utils/ruoyi";
 | 
			
		||||
 | 
			
		||||
const defaultRefundDetail = {
 | 
			
		||||
  id: null,
 | 
			
		||||
  appId: null,
 | 
			
		||||
  appName: '',
 | 
			
		||||
  channelCode: '',
 | 
			
		||||
  channelCodeName: '',
 | 
			
		||||
  channelErrorCode: '',
 | 
			
		||||
  channelErrorMsg: '',
 | 
			
		||||
  channelExtras: '',
 | 
			
		||||
  channelId: null,
 | 
			
		||||
  channelOrderNo: '',
 | 
			
		||||
  channelRefundNo: '',
 | 
			
		||||
  createTime: null,
 | 
			
		||||
  expireTime: null,
 | 
			
		||||
  merchantId: null,
 | 
			
		||||
  merchantName: '',
 | 
			
		||||
  merchantOrderId: '',
 | 
			
		||||
  merchantRefundNo: '',
 | 
			
		||||
  notifyStatus: null,
 | 
			
		||||
  notifyTime: null,
 | 
			
		||||
  notifyUrl: '',
 | 
			
		||||
  orderId: null,
 | 
			
		||||
  payAmount: null,
 | 
			
		||||
  reason: '',
 | 
			
		||||
  refundAmount: null,
 | 
			
		||||
  status: null,
 | 
			
		||||
  subject: '',
 | 
			
		||||
  successTime: null,
 | 
			
		||||
  tradeNo: '',
 | 
			
		||||
  type: null,
 | 
			
		||||
  userIp: ''
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "PayRefund",
 | 
			
		||||
  components: {},
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // 遮罩层
 | 
			
		||||
      loading: true,
 | 
			
		||||
      // 显示搜索条件
 | 
			
		||||
      showSearch: true,
 | 
			
		||||
      // 总条数
 | 
			
		||||
      total: 0,
 | 
			
		||||
      // 退款订单列表
 | 
			
		||||
      list: [],
 | 
			
		||||
      // 弹出层标题
 | 
			
		||||
      title: "",
 | 
			
		||||
      // 是否显示弹出层
 | 
			
		||||
      open: false,
 | 
			
		||||
      // 查询参数
 | 
			
		||||
      queryParams: {
 | 
			
		||||
        pageNo: 1,
 | 
			
		||||
        pageSize: 10,
 | 
			
		||||
        merchantId: null,
 | 
			
		||||
        appId: null,
 | 
			
		||||
        channelId: null,
 | 
			
		||||
        channelCode: null,
 | 
			
		||||
        orderId: null,
 | 
			
		||||
        tradeNo: null,
 | 
			
		||||
        merchantOrderId: null,
 | 
			
		||||
        merchantRefundNo: null,
 | 
			
		||||
        notifyUrl: null,
 | 
			
		||||
        notifyStatus: null,
 | 
			
		||||
        status: null,
 | 
			
		||||
        type: null,
 | 
			
		||||
        payAmount: null,
 | 
			
		||||
        refundAmount: null,
 | 
			
		||||
        reason: null,
 | 
			
		||||
        userIp: null,
 | 
			
		||||
        channelOrderNo: null,
 | 
			
		||||
        channelRefundNo: null,
 | 
			
		||||
        channelErrorCode: null,
 | 
			
		||||
        channelErrorMsg: null,
 | 
			
		||||
        channelExtras: null,
 | 
			
		||||
        expireTime: [],
 | 
			
		||||
        successTime: [],
 | 
			
		||||
        notifyTime: [],
 | 
			
		||||
        createTime: []
 | 
			
		||||
      },
 | 
			
		||||
      // 商户加载遮罩层
 | 
			
		||||
      merchantLoading: false,
 | 
			
		||||
      // 商户列表集合
 | 
			
		||||
      merchantList: null,
 | 
			
		||||
      // 支付应用列表集合
 | 
			
		||||
      appList: null,
 | 
			
		||||
      // 支付渠道编码字典数据集合
 | 
			
		||||
      payChannelCodeDictDatum: getDictDatas(DICT_TYPE.PAY_CHANNEL_CODE_TYPE),
 | 
			
		||||
      // 订单退款状态字典数据集合
 | 
			
		||||
      payRefundOrderDictDatum: getDictDatas(DICT_TYPE.PAY_REFUND_ORDER_STATUS),
 | 
			
		||||
      // 退款订单类别字典数据集合
 | 
			
		||||
      payRefundOrderTypeDictDatum: getDictDatas(DICT_TYPE.PAY_REFUND_ORDER_TYPE),
 | 
			
		||||
      // 订单回调商户状态字典数据集合
 | 
			
		||||
      payOrderNotifyDictDatum: getDictDatas(DICT_TYPE.PAY_ORDER_NOTIFY_STATUS),
 | 
			
		||||
      // el-tag订单退款状态type值
 | 
			
		||||
      refundStatusType: '',
 | 
			
		||||
      // 退款订单详情
 | 
			
		||||
      refundDetail: JSON.parse(JSON.stringify(defaultRefundDetail)),
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    this.initTime();
 | 
			
		||||
    this.getList();
 | 
			
		||||
    this.handleGetMerchantListByName(null);
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    initTime(){
 | 
			
		||||
      this.queryParams.createTime = [getNowDateTime("00:00:00"), getNowDateTime("23:59:59")];
 | 
			
		||||
    },
 | 
			
		||||
    /** 查询列表 */
 | 
			
		||||
    getList() {
 | 
			
		||||
      // 判断选择的日期是否超过了一个月
 | 
			
		||||
      let oneMonthTime = 31 * 24 * 3600 * 1000;
 | 
			
		||||
      if (this.queryParams.createTime == null){
 | 
			
		||||
        this.initTime();
 | 
			
		||||
      } else {
 | 
			
		||||
        let minDateTime = new Date(this.queryParams.createTime[0]).getTime();
 | 
			
		||||
        let maxDateTime = new Date(this.queryParams.createTime[1]).getTime()
 | 
			
		||||
        if (maxDateTime - minDateTime > oneMonthTime) {
 | 
			
		||||
          this.$message.error('时间范围最大为 31 天!');
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      this.loading = true;
 | 
			
		||||
      // 执行查询
 | 
			
		||||
      getRefundPage(this.queryParams).then(response => {
 | 
			
		||||
        this.list = response.data.list;
 | 
			
		||||
        this.total = response.data.total;
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /** 取消按钮 */
 | 
			
		||||
    cancel() {
 | 
			
		||||
      this.open = false;
 | 
			
		||||
    },
 | 
			
		||||
    /** 搜索按钮操作 */
 | 
			
		||||
    handleQuery() {
 | 
			
		||||
      this.queryParams.pageNo = 1;
 | 
			
		||||
      this.getList();
 | 
			
		||||
    },
 | 
			
		||||
    /** 重置按钮操作 */
 | 
			
		||||
    resetQuery() {
 | 
			
		||||
      this.resetForm("queryForm");
 | 
			
		||||
      this.handleQuery();
 | 
			
		||||
    },
 | 
			
		||||
    /** 导出按钮操作 */
 | 
			
		||||
    handleExport() {
 | 
			
		||||
      // 处理查询参数
 | 
			
		||||
      let params = {...this.queryParams};
 | 
			
		||||
      params.pageNo = undefined;
 | 
			
		||||
      params.pageSize = undefined;
 | 
			
		||||
      // 执行导出
 | 
			
		||||
      this.$modal.confirm('是否确认导出所有退款订单数据项?').then(function () {
 | 
			
		||||
        return exportRefundExcel(params);
 | 
			
		||||
      }).then(response => {
 | 
			
		||||
        this.$download.excel(response, '退款订单.xls');
 | 
			
		||||
      }).catch(() => {});
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据商户名称模糊匹配商户信息
 | 
			
		||||
     * @param name 商户名称
 | 
			
		||||
     */
 | 
			
		||||
    handleGetMerchantListByName(name) {
 | 
			
		||||
      getMerchantListByName(name).then(response => {
 | 
			
		||||
        this.merchantList = response.data;
 | 
			
		||||
        this.merchantLoading = false;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据商户 ID 查询支付应用信息
 | 
			
		||||
     */
 | 
			
		||||
    handleGetAppListByMerchantId() {
 | 
			
		||||
      this.queryParams.appId = null;
 | 
			
		||||
      getAppListByMerchantId(this.queryParams.merchantId).then(response => {
 | 
			
		||||
        this.appList = response.data;
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据退款类别得到样式名称
 | 
			
		||||
     * @param refundType 退款类别
 | 
			
		||||
     */
 | 
			
		||||
    findByRefundTypeGetStyle(refundType) {
 | 
			
		||||
      switch (refundType) {
 | 
			
		||||
        case PayOrderRefundStatusEnum.NO.status:
 | 
			
		||||
          return "success";
 | 
			
		||||
        case PayOrderRefundStatusEnum.SOME.status:
 | 
			
		||||
          return "warning";
 | 
			
		||||
        case PayOrderRefundStatusEnum.ALL.status:
 | 
			
		||||
          return "danger";
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据退款状态得到样式名称
 | 
			
		||||
     * @param refundStatus 退款状态
 | 
			
		||||
     */
 | 
			
		||||
    findByRefundStatusGetStyle(refundStatus) {
 | 
			
		||||
      switch (refundStatus) {
 | 
			
		||||
        case PayRefundStatusEnum.CREATE.status:
 | 
			
		||||
          return "info";
 | 
			
		||||
        case PayRefundStatusEnum.SUCCESS.status:
 | 
			
		||||
          return "success";
 | 
			
		||||
        case PayRefundStatusEnum.FAILURE.status:
 | 
			
		||||
        case PayRefundStatusEnum.CLOSE.status:
 | 
			
		||||
          return "danger";
 | 
			
		||||
        case PayRefundStatusEnum.PROCESSING_NOTIFY.status:
 | 
			
		||||
        case PayRefundStatusEnum.PROCESSING_QUERY.status:
 | 
			
		||||
        case PayRefundStatusEnum.UNKNOWN_RETRY.status:
 | 
			
		||||
        case PayRefundStatusEnum.UNKNOWN_QUERY.status:
 | 
			
		||||
          return "warning";
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    /**
 | 
			
		||||
     * 查看订单详情
 | 
			
		||||
     */
 | 
			
		||||
    handleQueryDetails(row) {
 | 
			
		||||
      this.refundDetail = JSON.parse(JSON.stringify(defaultRefundDetail));
 | 
			
		||||
      getRefund(row.id).then(response => {
 | 
			
		||||
        this.refundDetail = response.data;
 | 
			
		||||
        this.open = true;
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
<style>
 | 
			
		||||
.desc-label {
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.tag-purple {
 | 
			
		||||
  color: #722ed1;
 | 
			
		||||
  background: #f9f0ff;
 | 
			
		||||
  border-color: #d3adf7;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.tag-cyan {
 | 
			
		||||
  color: #13c2c2;
 | 
			
		||||
  background: #e6fffb;
 | 
			
		||||
  border-color: #87e8de;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.tag-pink {
 | 
			
		||||
  color: #eb2f96;
 | 
			
		||||
  background: #fff0f6;
 | 
			
		||||
  border-color: #ffadd2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.order-font {
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
  padding: 2px 0;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -42,7 +42,7 @@ export function WsConnect(url, agentData, successCallback, errCallback) {
 | 
			
		||||
      this.lockReconnect = true;
 | 
			
		||||
      this.wsCreateHandler && clearTimeout(this.wsCreateHandler);
 | 
			
		||||
      // 关闭心跳检查
 | 
			
		||||
      // heartCheck.stop();
 | 
			
		||||
      heartCheck.stop();
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  const initWsEventHandle = () => {
 | 
			
		||||
@@ -50,13 +50,13 @@ export function WsConnect(url, agentData, successCallback, errCallback) {
 | 
			
		||||
      // 连接成功
 | 
			
		||||
      this.wsObj.onopen = (event) => {
 | 
			
		||||
        onWsOpen(event);
 | 
			
		||||
        // heartCheck.start();
 | 
			
		||||
        heartCheck.start();
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      // 监听服务器端返回的信息
 | 
			
		||||
      this.wsObj.onmessage = (event) => {
 | 
			
		||||
        onWsMessage(event);
 | 
			
		||||
        // heartCheck.start();
 | 
			
		||||
        heartCheck.start();
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      this.wsObj.onclose = (event) => {
 | 
			
		||||
@@ -123,7 +123,7 @@ export function WsConnect(url, agentData, successCallback, errCallback) {
 | 
			
		||||
    if (this.lockReconnect) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    writeToScreen("3秒后重连");
 | 
			
		||||
    writeToScreen("5秒后重连");
 | 
			
		||||
    this.lockReconnect = true;
 | 
			
		||||
    // 没连接上会一直重连,设置延迟避免请求过多
 | 
			
		||||
    this.wsCreateHandler && clearTimeout(this.wsCreateHandler);
 | 
			
		||||
@@ -132,10 +132,40 @@ export function WsConnect(url, agentData, successCallback, errCallback) {
 | 
			
		||||
      this.createWebSoket();
 | 
			
		||||
      this.lockReconnect = false;
 | 
			
		||||
      writeToScreen("重连完成");
 | 
			
		||||
    }, 3000);
 | 
			
		||||
    }, 5000);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // 心跳检查(看看websocket是否还在正常连接中)
 | 
			
		||||
  // 心跳检查(看看websocket是否还在正常连接中,不需要服务端返回,单向的)
 | 
			
		||||
  let _this = this
 | 
			
		||||
  let heartCheck = {
 | 
			
		||||
    timeout: 55000,
 | 
			
		||||
    timeoutObj: null,
 | 
			
		||||
    // 重启
 | 
			
		||||
    reset() {
 | 
			
		||||
      clearTimeout(this.timeoutObj);
 | 
			
		||||
      this.start();
 | 
			
		||||
    },
 | 
			
		||||
    // 停止
 | 
			
		||||
    stop() {
 | 
			
		||||
      clearTimeout(this.timeoutObj);
 | 
			
		||||
    },
 | 
			
		||||
    // 开启定时器
 | 
			
		||||
    start() {
 | 
			
		||||
      this.timeoutObj && clearTimeout(this.timeoutObj);
 | 
			
		||||
      this.timeoutObj = setTimeout(() => {
 | 
			
		||||
        writeToScreen("心跳检查,发送ping到后台");
 | 
			
		||||
        try {
 | 
			
		||||
          const datas = { ping: true };
 | 
			
		||||
          _this.wsObj.send(JSON.stringify(datas));
 | 
			
		||||
        } catch (err) {
 | 
			
		||||
          writeToScreen("发送ping异常");
 | 
			
		||||
        }
 | 
			
		||||
      }, this.timeout);
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  // 心跳检查(看看websocket是否还在正常连接中,和服务端通信,双向的)
 | 
			
		||||
  // let heartCheck = {
 | 
			
		||||
  //   timeout: 15000,
 | 
			
		||||
  //   timeoutObj: null,
 | 
			
		||||
@@ -160,7 +190,7 @@ export function WsConnect(url, agentData, successCallback, errCallback) {
 | 
			
		||||
  //       writeToScreen("心跳检查,发送ping到后台");
 | 
			
		||||
  //       try {
 | 
			
		||||
  //         const datas = { ping: true };
 | 
			
		||||
  //         this.wsObj.send(JSON.stringify(datas));
 | 
			
		||||
  //         _this.wsObj.send(JSON.stringify(datas));
 | 
			
		||||
  //       } catch (err) {
 | 
			
		||||
  //         writeToScreen("发送ping异常");
 | 
			
		||||
  //       }
 | 
			
		||||
 
 | 
			
		||||
@@ -6,28 +6,33 @@ import store from "@/store";
 | 
			
		||||
const timestr = new Date().getTime()
 | 
			
		||||
const dcsConn = new WsConnect(
 | 
			
		||||
  // websocket地址
 | 
			
		||||
  process.env.VUE_APP_Socket_Dcs_API + '/xc-screen/websocket/dcsmsg'+timestr,
 | 
			
		||||
  process.env.VUE_APP_Socket_Dcs_API + '/xc-screen/websocket/dcsmsg' + timestr,
 | 
			
		||||
  // 传递给后台的数据
 | 
			
		||||
  '',
 | 
			
		||||
  (data) => {
 | 
			
		||||
    // console.log('dcs成功的回调函数, 接收到的data数据: ', data)
 | 
			
		||||
    let msgData = JSON.parse(data)
 | 
			
		||||
    let msgData = {}
 | 
			
		||||
    try {
 | 
			
		||||
      msgData = JSON.parse(data)
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      console.log("websocket: [unable to msgData] :  ", data);
 | 
			
		||||
    }
 | 
			
		||||
    if (msgData == null) return;
 | 
			
		||||
    switch (msgData?.type) {
 | 
			
		||||
      case "FanFrequencyInfo": {
 | 
			
		||||
        store.dispatch({type: "websocket/setFanFrequencyInfo", payload:msgData.data.FanFrequencyInfo})
 | 
			
		||||
        store.dispatch({ type: "websocket/setFanFrequencyInfo", payload: msgData.data.FanFrequencyInfo })
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case "KilnInfo": {
 | 
			
		||||
        store.dispatch({type: "websocket/setKilnInfo", payload: msgData.data})
 | 
			
		||||
        store.dispatch({ type: "websocket/setKilnInfo", payload: msgData.data })
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case "GasInfo": {
 | 
			
		||||
        store.dispatch({type: "websocket/setGasInfo", payload: msgData.data})
 | 
			
		||||
        store.dispatch({ type: "websocket/setGasInfo", payload: msgData.data })
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case "SumGasInfo": {
 | 
			
		||||
        store.dispatch({type: "websocket/setSumGasInfo", payload: msgData.data})
 | 
			
		||||
        store.dispatch({ type: "websocket/setSumGasInfo", payload: msgData.data })
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      default:
 | 
			
		||||
@@ -39,16 +44,20 @@ const dcsConn = new WsConnect(
 | 
			
		||||
)
 | 
			
		||||
// ISRA
 | 
			
		||||
const mesIsra = new WsConnect(
 | 
			
		||||
  process.env.VUE_APP_Socket_API + '/websocket/message?userId=KILN'+timestr,
 | 
			
		||||
  process.env.VUE_APP_Socket_API + '/websocket/message?userId=KILN' + timestr,
 | 
			
		||||
  '',
 | 
			
		||||
  (data) => {
 | 
			
		||||
    // console.log('mes ISRA成功的回调函数, 接收到的data数据: ', data)
 | 
			
		||||
    let msgData = JSON.parse(data)
 | 
			
		||||
    // console.log(msgData)
 | 
			
		||||
    let msgData = {}
 | 
			
		||||
    try {
 | 
			
		||||
      msgData = JSON.parse(data)
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      console.log("websocket: [unable to msgData] :  ", data);
 | 
			
		||||
    }
 | 
			
		||||
    if (msgData == null) return;
 | 
			
		||||
    switch (msgData?.type) {
 | 
			
		||||
      case "israKiln": {
 | 
			
		||||
        store.dispatch({type: "websocket/setIsraKiln", payload:msgData.detData.dayStatistic})
 | 
			
		||||
        store.dispatch({ type: "websocket/setIsraKiln", payload: msgData.detData.dayStatistic })
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      default:
 | 
			
		||||
@@ -61,15 +70,20 @@ const mesIsra = new WsConnect(
 | 
			
		||||
 | 
			
		||||
// 原料 MA
 | 
			
		||||
const mesMA = new WsConnect(
 | 
			
		||||
  process.env.VUE_APP_Socket_API + '/websocket/message?userId=MA'+timestr,
 | 
			
		||||
  process.env.VUE_APP_Socket_API + '/websocket/message?userId=MA' + timestr,
 | 
			
		||||
  '',
 | 
			
		||||
  (data) => {
 | 
			
		||||
    // console.log('mes 原料成功的回调函数, 接收到的data数据: ', data)
 | 
			
		||||
    let msgData = JSON.parse(data)
 | 
			
		||||
    let msgData = {}
 | 
			
		||||
    try {
 | 
			
		||||
      msgData = JSON.parse(data)
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      console.log("websocket: [unable to msgData] :  ", data);
 | 
			
		||||
    }
 | 
			
		||||
    if (msgData == null) return;
 | 
			
		||||
    switch (msgData?.type) {
 | 
			
		||||
      case "material": {
 | 
			
		||||
        store.dispatch({type: "websocket/setMaterial", payload:msgData.data})
 | 
			
		||||
        store.dispatch({ type: "websocket/setMaterial", payload: msgData.data })
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      default:
 | 
			
		||||
@@ -82,25 +96,30 @@ const mesMA = new WsConnect(
 | 
			
		||||
// 能耗 EN
 | 
			
		||||
const mesEN = new WsConnect(
 | 
			
		||||
  // websocket地址
 | 
			
		||||
  process.env.VUE_APP_Socket_API + '/websocket/message?userId=ENERGY'+timestr,
 | 
			
		||||
  process.env.VUE_APP_Socket_API + '/websocket/message?userId=ENERGY' + timestr,
 | 
			
		||||
  // 传递给后台的数据
 | 
			
		||||
  '',
 | 
			
		||||
  // 成功拿到后台返回的数据的回调函数
 | 
			
		||||
  (data) => {
 | 
			
		||||
    // console.log('mes 能耗成功的回调函数, 接收到的data数据: ', data)
 | 
			
		||||
    let msgData = JSON.parse(data)
 | 
			
		||||
    let msgData = {}
 | 
			
		||||
    try {
 | 
			
		||||
      msgData = JSON.parse(data)
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      console.log("websocket: [unable to msgData] :  ", data);
 | 
			
		||||
    }
 | 
			
		||||
    if (msgData == null) return;
 | 
			
		||||
    switch (msgData?.type) {
 | 
			
		||||
      case "EnergyInfo": {
 | 
			
		||||
        store.dispatch({type: "websocket/setEnergyInfo", payload:msgData.data})
 | 
			
		||||
        store.dispatch({ type: "websocket/setEnergyInfo", payload: msgData.data })
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case "EnergyTrend": {
 | 
			
		||||
        store.dispatch({type: "websocket/setEnergyTrend", payload:msgData.data})
 | 
			
		||||
        store.dispatch({ type: "websocket/setEnergyTrend", payload: msgData.data })
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case "EnergyMonitoring": {
 | 
			
		||||
        store.dispatch({type: "websocket/setEnergyMonitoring", payload:msgData.data})
 | 
			
		||||
        store.dispatch({ type: "websocket/setEnergyMonitoring", payload: msgData.data })
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      default:
 | 
			
		||||
@@ -114,23 +133,30 @@ const mesEN = new WsConnect(
 | 
			
		||||
// 烟气 GAS
 | 
			
		||||
const mesGAS = new WsConnect(
 | 
			
		||||
  // websocket地址
 | 
			
		||||
  process.env.VUE_APP_Socket_API + '/websocket/message?userId=GAS'+timestr,
 | 
			
		||||
  process.env.VUE_APP_Socket_API + '/websocket/message?userId=GAS' + timestr,
 | 
			
		||||
  // 传递给后台的数据
 | 
			
		||||
  '',
 | 
			
		||||
  // 成功拿到后台返回的数据的回调函数
 | 
			
		||||
  (data) => {
 | 
			
		||||
    // console.log('mes 烟气成功的回调函数, 接收到的data数据: ', data)
 | 
			
		||||
    let msgData = JSON.parse(data)
 | 
			
		||||
    let msgData = {}
 | 
			
		||||
    try {
 | 
			
		||||
      msgData = JSON.parse(data)
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      console.log("websocket: [unable to msgData] :  ", data);
 | 
			
		||||
    }
 | 
			
		||||
    if (msgData == null) return;
 | 
			
		||||
    switch (msgData?.type) {
 | 
			
		||||
      case "exhaustGas": {
 | 
			
		||||
        store.dispatch({type: "websocket/setExhaustGasInfo", payload:msgData.realtime})
 | 
			
		||||
        store.dispatch({type: "websocket/setExhaustGasChart", payload:{
 | 
			
		||||
          dayTrend: msgData.dayTrend,
 | 
			
		||||
          weekTrend: msgData.weekTrend,
 | 
			
		||||
          monthTrend: msgData.monthTrend,
 | 
			
		||||
          yearTrend: msgData.yearTrend,
 | 
			
		||||
        }})
 | 
			
		||||
        store.dispatch({ type: "websocket/setExhaustGasInfo", payload: msgData.realtime })
 | 
			
		||||
        store.dispatch({
 | 
			
		||||
          type: "websocket/setExhaustGasChart", payload: {
 | 
			
		||||
            dayTrend: msgData.dayTrend,
 | 
			
		||||
            weekTrend: msgData.weekTrend,
 | 
			
		||||
            monthTrend: msgData.monthTrend,
 | 
			
		||||
            yearTrend: msgData.yearTrend,
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      default:
 | 
			
		||||
@@ -145,23 +171,30 @@ const mesGAS = new WsConnect(
 | 
			
		||||
// 缺陷分类/统计 IS
 | 
			
		||||
const mesIS = new WsConnect(
 | 
			
		||||
  // websocket地址
 | 
			
		||||
  process.env.VUE_APP_Socket_API + '/websocket/message?userId=IS'+timestr,
 | 
			
		||||
  process.env.VUE_APP_Socket_API + '/websocket/message?userId=IS' + timestr,
 | 
			
		||||
  // 传递给后台的数据
 | 
			
		||||
  '',
 | 
			
		||||
  // 成功拿到后台返回的数据的回调函数
 | 
			
		||||
  (data) => {
 | 
			
		||||
    // console.log('mes 缺陷成功的回调函数, 接收到的data数据: ', data)
 | 
			
		||||
    let msgData = JSON.parse(data)
 | 
			
		||||
    let msgData = {}
 | 
			
		||||
    try {
 | 
			
		||||
      msgData = JSON.parse(data)
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      console.log("websocket: [unable to msgData] :  ", data);
 | 
			
		||||
    }
 | 
			
		||||
    if (msgData == null) return;
 | 
			
		||||
    switch (msgData?.type) {
 | 
			
		||||
      case "isra": {
 | 
			
		||||
        store.dispatch({type: "websocket/setDefectChart", payload:{
 | 
			
		||||
          checkType: msgData.detData.checkType,
 | 
			
		||||
          dayStatistic: msgData.detData.dayStatistic,
 | 
			
		||||
          weekStatistic: msgData.detData.weekStatistic,
 | 
			
		||||
          monthStatistic: msgData.detData.monthStatistic,
 | 
			
		||||
          yearStatistic: msgData.detData.yearStatistic,
 | 
			
		||||
        }})
 | 
			
		||||
        store.dispatch({
 | 
			
		||||
          type: "websocket/setDefectChart", payload: {
 | 
			
		||||
            checkType: msgData.detData.checkType,
 | 
			
		||||
            dayStatistic: msgData.detData.dayStatistic,
 | 
			
		||||
            weekStatistic: msgData.detData.weekStatistic,
 | 
			
		||||
            monthStatistic: msgData.detData.monthStatistic,
 | 
			
		||||
            yearStatistic: msgData.detData.yearStatistic,
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      default:
 | 
			
		||||
@@ -176,29 +209,34 @@ const mesIS = new WsConnect(
 | 
			
		||||
// 深加工生产运行驾驶舱(除能源) SJG
 | 
			
		||||
const mesSJG = new WsConnect(
 | 
			
		||||
  // websocket地址
 | 
			
		||||
  process.env.VUE_APP_Socket_API + '/websocket/message?userId=SJG'+timestr,
 | 
			
		||||
  process.env.VUE_APP_Socket_API + '/websocket/message?userId=SJG' + timestr,
 | 
			
		||||
  // 传递给后台的数据
 | 
			
		||||
  '',
 | 
			
		||||
  // 成功拿到后台返回的数据的回调函数
 | 
			
		||||
  (data) => {
 | 
			
		||||
    // console.log('mes 产线产量及良品率成功的回调函数, 接收到的data数据: ', data)
 | 
			
		||||
    let msgData = JSON.parse(data)
 | 
			
		||||
    let msgData = {}
 | 
			
		||||
    try {
 | 
			
		||||
      msgData = JSON.parse(data)
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      console.log("websocket: [unable to msgData] :  ", data);
 | 
			
		||||
    }
 | 
			
		||||
    if (msgData == null) return;
 | 
			
		||||
    switch (msgData?.type) {
 | 
			
		||||
      case "productline": {
 | 
			
		||||
        store.dispatch({type: "websocket/setProductline", payload:msgData.detData})
 | 
			
		||||
        store.dispatch({ type: "websocket/setProductline", payload: msgData.detData })
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case "equipment": {
 | 
			
		||||
        store.dispatch({type: "websocket/setSJGEq", payload:msgData.detData})
 | 
			
		||||
        store.dispatch({ type: "websocket/setSJGEq", payload: msgData.detData })
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case "order": {
 | 
			
		||||
        store.dispatch({type: "websocket/setWorkOrder", payload:msgData.detData})
 | 
			
		||||
        store.dispatch({ type: "websocket/setWorkOrder", payload: msgData.detData })
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case "defectSum": {
 | 
			
		||||
        store.dispatch({type: "websocket/setDefectSum", payload:msgData.detData})
 | 
			
		||||
        store.dispatch({ type: "websocket/setDefectSum", payload: msgData.detData })
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      default:
 | 
			
		||||
@@ -213,18 +251,23 @@ const mesSJG = new WsConnect(
 | 
			
		||||
// 订单完成情况 OV
 | 
			
		||||
const mesOV = new WsConnect(
 | 
			
		||||
  // websocket地址
 | 
			
		||||
  process.env.VUE_APP_Socket_API + '/websocket/message?userId=OV'+timestr,
 | 
			
		||||
  process.env.VUE_APP_Socket_API + '/websocket/message?userId=OV' + timestr,
 | 
			
		||||
  // 'ws://192.168.0.33:48082/websocket/message?userId=OV'+timestr,
 | 
			
		||||
  // 传递给后台的数据
 | 
			
		||||
  '',
 | 
			
		||||
  // 成功拿到后台返回的数据的回调函数
 | 
			
		||||
  (data) => {
 | 
			
		||||
    // console.log('mes 产线产量及良品率成功的回调函数, 接收到的data数据: ', data)
 | 
			
		||||
    let msgData = JSON.parse(data)
 | 
			
		||||
    let msgData = {}
 | 
			
		||||
    try {
 | 
			
		||||
      msgData = JSON.parse(data)
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      console.log("websocket: [unable to msgData] :  ", data);
 | 
			
		||||
    }
 | 
			
		||||
    if (msgData == null) return;
 | 
			
		||||
    switch (msgData?.type) {
 | 
			
		||||
      case "order": {
 | 
			
		||||
        store.dispatch({type: "websocket/setOrder", payload:msgData.detData})
 | 
			
		||||
        store.dispatch({ type: "websocket/setOrder", payload: msgData.detData })
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      default:
 | 
			
		||||
@@ -239,35 +282,39 @@ const mesOV = new WsConnect(
 | 
			
		||||
// 本日生产良品率 CUTTING
 | 
			
		||||
const mesCUTTING = new WsConnect(
 | 
			
		||||
  // websocket地址
 | 
			
		||||
  process.env.VUE_APP_Socket_API + '/websocket/message?userId=CUTTING'+timestr,
 | 
			
		||||
  process.env.VUE_APP_Socket_API + '/websocket/message?userId=CUTTING' + timestr,
 | 
			
		||||
  // 传递给后台的数据
 | 
			
		||||
  '',
 | 
			
		||||
  // 成功拿到后台返回的数据的回调函数
 | 
			
		||||
  (data) => {
 | 
			
		||||
    // console.log('mes 产线产量及良品率成功的回调函数, 接收到的data数据: ', data)
 | 
			
		||||
    let msgData = JSON.parse(data)
 | 
			
		||||
    let msgData = {}
 | 
			
		||||
    try {
 | 
			
		||||
      msgData = JSON.parse(data)
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      console.log("websocket: [unable to msgData] :  ", data);
 | 
			
		||||
    }
 | 
			
		||||
    if (msgData == null) return;
 | 
			
		||||
    console.log(msgData)
 | 
			
		||||
    switch (msgData?.type) {
 | 
			
		||||
      case "cutting": {
 | 
			
		||||
        if (msgData?.name === 'table') {
 | 
			
		||||
          store.dispatch({type: "websocket/setYieldRateTable", payload:msgData.data})
 | 
			
		||||
          store.dispatch({ type: "websocket/setYieldRateTable", payload: msgData.data })
 | 
			
		||||
          return
 | 
			
		||||
        }
 | 
			
		||||
        if (msgData?.dateType === 'day') {
 | 
			
		||||
          store.dispatch({type: "websocket/setCutChartDay", payload:msgData.detData})
 | 
			
		||||
          store.dispatch({ type: "websocket/setCutChartDay", payload: msgData.detData })
 | 
			
		||||
          return
 | 
			
		||||
        }
 | 
			
		||||
        if (msgData?.dateType === 'weekly') {
 | 
			
		||||
          store.dispatch({type: "websocket/setCutChartWeek", payload:msgData.detData})
 | 
			
		||||
          store.dispatch({ type: "websocket/setCutChartWeek", payload: msgData.detData })
 | 
			
		||||
          return
 | 
			
		||||
        }
 | 
			
		||||
        if (msgData?.dateType === 'month') {
 | 
			
		||||
          store.dispatch({type: "websocket/setCutChartMonth", payload:msgData.detData})
 | 
			
		||||
          store.dispatch({ type: "websocket/setCutChartMonth", payload: msgData.detData })
 | 
			
		||||
          return
 | 
			
		||||
        }
 | 
			
		||||
        if (msgData?.dateType === 'year') {
 | 
			
		||||
          store.dispatch({type: "websocket/setCutChartYear", payload:msgData.detData})
 | 
			
		||||
          store.dispatch({ type: "websocket/setCutChartYear", payload: msgData.detData })
 | 
			
		||||
          return
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user