Compare commits
	
		
			40 Commits
		
	
	
		
			94c7f803cc
			...
			dad71db912
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| dad71db912 | |||
| 0dae8cd16d | |||
| 
						 | 
					1fd547893f | ||
| 
						 | 
					ad5812df96 | ||
| 
						 | 
					c01106e389 | ||
| 021182e873 | |||
| 
						 | 
					71834ef906 | ||
| 
						 | 
					412ec6ab0c | ||
| 9aca4874c1 | |||
| 
						 | 
					c9d25e5e88 | ||
| 
						 | 
					610090c2a0 | ||
| 83917eaf4a | |||
| 
						 | 
					d64e9b9535 | ||
| 
						 | 
					b0f44c2332 | ||
| 8ae9efe4bd | |||
| 
						 | 
					15358fd7e2 | ||
| 
						 | 
					dfabc9ed23 | ||
| 78f6165cfc | |||
| 
						 | 
					7944824ffe | ||
| 984cf2e7d5 | |||
| 
						 | 
					07bc6aab69 | ||
| 
						 | 
					7a14b2846a | ||
| db7d4745dd | |||
| 6b99175574 | |||
| b8f9d3626f | |||
| 
						 | 
					c8913f192c | ||
| 
						 | 
					0fa651fccf | ||
| 33782e189c | |||
| ee828ec4a7 | |||
| e75d2f1810 | |||
| ff9ee438ae | |||
| df10a757bf | |||
| cb9456358f | |||
| 23334b5017 | |||
| 63e9100368 | |||
| 2e5e423a38 | |||
| 3b8c8b047b | |||
| d9b354f0c4 | |||
| 783cb0c3fe | |||
| 17f31863f9 | 
							
								
								
									
										2
									
								
								.env.dev
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								.env.dev
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
			
		||||
###
 | 
			
		||||
 # @Author: Do not edit
 | 
			
		||||
 # @Date: 2023-08-29 09:40:39
 | 
			
		||||
 # @LastEditTime: 2024-03-25 15:59:53
 | 
			
		||||
 # @LastEditTime: 2024-04-01 08:31:57
 | 
			
		||||
 # @LastEditors: zhp
 | 
			
		||||
 # @Description:
 | 
			
		||||
###
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								src/api/infra/apiAccessLog.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/api/infra/apiAccessLog.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
import request from '@/utils/request'
 | 
			
		||||
 | 
			
		||||
// 获得API 访问日志分页
 | 
			
		||||
export function getApiAccessLogPage(query) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/api-access-log/page',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    params: query
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 导出API 访问日志 Excel
 | 
			
		||||
export function exportApiAccessLogExcel(query) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/api-access-log/export-excel',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    params: query,
 | 
			
		||||
    responseType: 'blob'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								src/api/infra/apiErrorLog.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/api/infra/apiErrorLog.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
import request from '@/utils/request'
 | 
			
		||||
 | 
			
		||||
// 更新 API 错误日志的处理状态
 | 
			
		||||
export function updateApiErrorLogProcess(id, processStatus) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/api-error-log/update-status?id=' + id + '&processStatus=' + processStatus,
 | 
			
		||||
    method: 'put',
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获得API 错误日志分页
 | 
			
		||||
export function getApiErrorLogPage(query) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/api-error-log/page',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    params: query
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 导出API 错误日志 Excel
 | 
			
		||||
export function exportApiErrorLogExcel(query) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/api-error-log/export-excel',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    params: query,
 | 
			
		||||
    responseType: 'blob'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										90
									
								
								src/api/infra/codegen.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/api/infra/codegen.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,90 @@
 | 
			
		||||
import request from '@/utils/request'
 | 
			
		||||
 | 
			
		||||
// 获得表定义分页
 | 
			
		||||
export function getCodegenTablePage(query) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/codegen/table/page',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    params: query
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获得表和字段的明细
 | 
			
		||||
export function getCodegenDetail(tableId) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/codegen/detail?tableId=' + tableId,
 | 
			
		||||
    method: 'get',
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 修改代码生成信息
 | 
			
		||||
export function updateCodegen(data) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/codegen/update',
 | 
			
		||||
    method: 'put',
 | 
			
		||||
    data: data
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 基于数据库的表结构,同步数据库的表和字段定义
 | 
			
		||||
export function syncCodegenFromDB(tableId) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/codegen/sync-from-db?tableId=' + tableId,
 | 
			
		||||
    method: 'put'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 基于 SQL 建表语句,同步数据库的表和字段定义
 | 
			
		||||
export function syncCodegenFromSQL(tableId, sql) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/codegen/sync-from-sql?tableId=' + tableId,
 | 
			
		||||
    method: 'put',
 | 
			
		||||
    headers:{
 | 
			
		||||
      'Content-type': 'application/x-www-form-urlencoded'
 | 
			
		||||
    },
 | 
			
		||||
    data: 'tableId=' + tableId + "&sql=" + sql,
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 预览生成代码
 | 
			
		||||
export function previewCodegen(tableId) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/codegen/preview?tableId=' + tableId,
 | 
			
		||||
    method: 'get',
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 下载生成代码
 | 
			
		||||
export function downloadCodegen(tableId) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/codegen/download?tableId=' + tableId,
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    responseType: 'blob'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获得表定义分页
 | 
			
		||||
export function getSchemaTableList(query) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/codegen/db/table/list',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    params: query
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 基于数据库的表结构,创建代码生成器的表定义
 | 
			
		||||
export function createCodegenList(data) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/codegen/create-list',
 | 
			
		||||
    method: 'post',
 | 
			
		||||
    data: data
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 删除数据库的表和字段定义
 | 
			
		||||
export function deleteCodegen(tableId) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/codegen/delete?tableId=' + tableId,
 | 
			
		||||
    method: 'delete'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										62
									
								
								src/api/infra/config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/api/infra/config.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
import request from '@/utils/request'
 | 
			
		||||
 | 
			
		||||
// 查询参数列表
 | 
			
		||||
export function listConfig(query) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/config/page',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    params: query
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 查询参数详细
 | 
			
		||||
export function getConfig(configId) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/config/get?id=' + configId,
 | 
			
		||||
    method: 'get'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 根据参数键名查询参数值
 | 
			
		||||
export function getConfigKey(configKey) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/config/get-value-by-key?key=' + configKey,
 | 
			
		||||
    method: 'get'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 新增参数配置
 | 
			
		||||
export function addConfig(data) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/config/create',
 | 
			
		||||
    method: 'post',
 | 
			
		||||
    data: data
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 修改参数配置
 | 
			
		||||
export function updateConfig(data) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/config/update',
 | 
			
		||||
    method: 'put',
 | 
			
		||||
    data: data
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 删除参数配置
 | 
			
		||||
export function delConfig(configId) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/config/delete?id=' + configId,
 | 
			
		||||
    method: 'delete'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 导出参数
 | 
			
		||||
export function exportConfig(query) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/config/export',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    params: query,
 | 
			
		||||
    responseType: 'blob'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										43
									
								
								src/api/infra/dataSourceConfig.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/api/infra/dataSourceConfig.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
import request from '@/utils/request'
 | 
			
		||||
 | 
			
		||||
// 创建数据源配置
 | 
			
		||||
export function createDataSourceConfig(data) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/data-source-config/create',
 | 
			
		||||
    method: 'post',
 | 
			
		||||
    data: data
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 更新数据源配置
 | 
			
		||||
export function updateDataSourceConfig(data) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/data-source-config/update',
 | 
			
		||||
    method: 'put',
 | 
			
		||||
    data: data
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 删除数据源配置
 | 
			
		||||
export function deleteDataSourceConfig(id) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/data-source-config/delete?id=' + id,
 | 
			
		||||
    method: 'delete'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获得数据源配置
 | 
			
		||||
export function getDataSourceConfig(id) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/data-source-config/get?id=' + id,
 | 
			
		||||
    method: 'get'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获得数据源配置列表
 | 
			
		||||
export function getDataSourceConfigList() {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/data-source-config/list',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								src/api/infra/dbDoc.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/api/infra/dbDoc.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
// 导出参数
 | 
			
		||||
import request from "@/utils/request";
 | 
			
		||||
 | 
			
		||||
export function exportHtml() {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/db-doc/export-html',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    responseType: 'blob'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function exportWord() {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/db-doc/export-word',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    responseType: 'blob'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function exportMarkdown() {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/db-doc/export-markdown',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    responseType: 'blob'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								src/api/infra/file.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/api/infra/file.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
import request from '@/utils/request'
 | 
			
		||||
 | 
			
		||||
// 删除文件
 | 
			
		||||
export function deleteFile(id) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/file/delete?id=' + id,
 | 
			
		||||
    method: 'delete'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获得文件分页
 | 
			
		||||
export function getFilePage(query) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/file/page',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    params: query
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										59
									
								
								src/api/infra/fileConfig.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/api/infra/fileConfig.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
import request from '@/utils/request'
 | 
			
		||||
 | 
			
		||||
// 创建文件配置
 | 
			
		||||
export function createFileConfig(data) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/file-config/create',
 | 
			
		||||
    method: 'post',
 | 
			
		||||
    data: data
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 更新文件配置
 | 
			
		||||
export function updateFileConfig(data) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/file-config/update',
 | 
			
		||||
    method: 'put',
 | 
			
		||||
    data: data
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 更新文件配置为主配置
 | 
			
		||||
export function updateFileConfigMaster(id) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/file-config/update-master?id=' + id,
 | 
			
		||||
    method: 'put'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 删除文件配置
 | 
			
		||||
export function deleteFileConfig(id) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/file-config/delete?id=' + id,
 | 
			
		||||
    method: 'delete'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获得文件配置
 | 
			
		||||
export function getFileConfig(id) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/file-config/get?id=' + id,
 | 
			
		||||
    method: 'get'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获得文件配置分页
 | 
			
		||||
export function getFileConfigPage(query) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/file-config/page',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    params: query
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function testFileConfig(id) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/file-config/test?id=' + id,
 | 
			
		||||
    method: 'get'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										82
									
								
								src/api/infra/job.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								src/api/infra/job.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,82 @@
 | 
			
		||||
import request from '@/utils/request'
 | 
			
		||||
 | 
			
		||||
// 查询定时任务调度列表
 | 
			
		||||
export function listJob(query) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/job/page',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    params: query
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 查询定时任务调度详细
 | 
			
		||||
export function getJob(jobId) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/job/get?id=' + jobId,
 | 
			
		||||
    method: 'get'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 新增定时任务调度
 | 
			
		||||
export function addJob(data) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/job/create',
 | 
			
		||||
    method: 'post',
 | 
			
		||||
    data: data
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 修改定时任务调度
 | 
			
		||||
export function updateJob(data) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/job/update',
 | 
			
		||||
    method: 'put',
 | 
			
		||||
    data: data
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 删除定时任务调度
 | 
			
		||||
export function delJob(jobId) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/job/delete?id=' + jobId,
 | 
			
		||||
    method: 'delete'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 导出定时任务调度
 | 
			
		||||
export function exportJob(query) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/job/export-excel',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    params: query,
 | 
			
		||||
    responseType: 'blob'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 任务状态修改
 | 
			
		||||
export function updateJobStatus(jobId, status) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/job/update-status',
 | 
			
		||||
    method: 'put',
 | 
			
		||||
    headers:{
 | 
			
		||||
      'Content-type': 'application/x-www-form-urlencoded'
 | 
			
		||||
    },
 | 
			
		||||
    data: 'id=' + jobId + "&status=" + status,
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 定时任务立即执行一次
 | 
			
		||||
export function runJob(jobId) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/job/trigger?id=' + jobId,
 | 
			
		||||
    method: 'put'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获得定时任务的下 n 次执行时间
 | 
			
		||||
export function getJobNextTimes(jobId) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/job/get_next_times?id=' + jobId,
 | 
			
		||||
    method: 'get'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								src/api/infra/jobLog.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/api/infra/jobLog.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
import request from '@/utils/request'
 | 
			
		||||
 | 
			
		||||
// 获得定时任务
 | 
			
		||||
export function getJobLog(id) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/job-log/get?id=' + id,
 | 
			
		||||
    method: 'get'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获得定时任务分页
 | 
			
		||||
export function getJobLogPage(query) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/job-log/page',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    params: query
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 导出定时任务 Excel
 | 
			
		||||
export function exportJobLogExcel(query) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/job-log/export-excel',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    params: query,
 | 
			
		||||
    responseType: 'blob'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								src/api/infra/redis.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/api/infra/redis.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
import request from '@/utils/request'
 | 
			
		||||
 | 
			
		||||
// 查询缓存详细
 | 
			
		||||
export function getCache() {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/redis/get-monitor-info',
 | 
			
		||||
    method: 'get'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										54
									
								
								src/api/infra/testDemo.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/api/infra/testDemo.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
import request from '@/utils/request'
 | 
			
		||||
 | 
			
		||||
// 创建字典类型
 | 
			
		||||
export function createTestDemo(data) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/test-demo/create',
 | 
			
		||||
    method: 'post',
 | 
			
		||||
    data: data
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 更新字典类型
 | 
			
		||||
export function updateTestDemo(data) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/test-demo/update',
 | 
			
		||||
    method: 'put',
 | 
			
		||||
    data: data
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 删除字典类型
 | 
			
		||||
export function deleteTestDemo(id) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/test-demo/delete?id=' + id,
 | 
			
		||||
    method: 'delete'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获得字典类型
 | 
			
		||||
export function getTestDemo(id) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/test-demo/get?id=' + id,
 | 
			
		||||
    method: 'get'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 获得字典类型分页
 | 
			
		||||
export function getTestDemoPage(query) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/test-demo/page',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    params: query
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 导出字典类型 Excel
 | 
			
		||||
export function exportTestDemoExcel(query) {
 | 
			
		||||
  return request({
 | 
			
		||||
    url: '/infra/test-demo/export-excel',
 | 
			
		||||
    method: 'get',
 | 
			
		||||
    params: query,
 | 
			
		||||
    responseType: 'blob'
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 141 KiB  | 
							
								
								
									
										160
									
								
								src/components/Crontab/day.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								src/components/Crontab/day.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,160 @@
 | 
			
		||||
<template>
 | 
			
		||||
	<el-form size="small">
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="1">
 | 
			
		||||
				日,允许的通配符[, - * ? / L W]
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="2">
 | 
			
		||||
				不指定
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="3">
 | 
			
		||||
				周期从
 | 
			
		||||
				<el-input-number v-model='cycle01' :min="1" :max="30" /> -
 | 
			
		||||
				<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 2" :max="31" /> 日
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="4">
 | 
			
		||||
				从
 | 
			
		||||
				<el-input-number v-model='average01' :min="1" :max="30" /> 号开始,每
 | 
			
		||||
				<el-input-number v-model='average02' :min="1" :max="31 - average01 || 1" /> 日执行一次
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="5">
 | 
			
		||||
				每月
 | 
			
		||||
				<el-input-number v-model='workday' :min="1" :max="31" /> 号最近的那个工作日
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="6">
 | 
			
		||||
				本月最后一天
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="7">
 | 
			
		||||
				指定
 | 
			
		||||
				<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
 | 
			
		||||
					<el-option v-for="item in 31" :key="item" :value="item">{{item}}</el-option>
 | 
			
		||||
				</el-select>
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
	</el-form>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			radioValue: 1,
 | 
			
		||||
			workday: 1,
 | 
			
		||||
			cycle01: 1,
 | 
			
		||||
			cycle02: 2,
 | 
			
		||||
			average01: 1,
 | 
			
		||||
			average02: 1,
 | 
			
		||||
			checkboxList: [],
 | 
			
		||||
			checkNum: this.$options.propsData.check
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	name: 'crontab-day',
 | 
			
		||||
	props: ['check', 'cron'],
 | 
			
		||||
	methods: {
 | 
			
		||||
		// 单选按钮值变化时
 | 
			
		||||
		radioChange() {
 | 
			
		||||
			('day rachange');
 | 
			
		||||
			if (this.radioValue !== 2 && this.cron.week !== '?') {
 | 
			
		||||
				this.$emit('update', 'week', '?', 'day')
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			switch (this.radioValue) {
 | 
			
		||||
				case 1:
 | 
			
		||||
					this.$emit('update', 'day', '*');
 | 
			
		||||
					break;
 | 
			
		||||
				case 2:
 | 
			
		||||
					this.$emit('update', 'day', '?');
 | 
			
		||||
					break;
 | 
			
		||||
				case 3:
 | 
			
		||||
					this.$emit('update', 'day', this.cycleTotal);
 | 
			
		||||
					break;
 | 
			
		||||
				case 4:
 | 
			
		||||
					this.$emit('update', 'day', this.averageTotal);
 | 
			
		||||
					break;
 | 
			
		||||
				case 5:
 | 
			
		||||
					this.$emit('update', 'day', this.workday + 'W');
 | 
			
		||||
					break;
 | 
			
		||||
				case 6:
 | 
			
		||||
					this.$emit('update', 'day', 'L');
 | 
			
		||||
					break;
 | 
			
		||||
				case 7:
 | 
			
		||||
					this.$emit('update', 'day', this.checkboxString);
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
			('day rachange end');
 | 
			
		||||
		},
 | 
			
		||||
		// 周期两个值变化时
 | 
			
		||||
		cycleChange() {
 | 
			
		||||
			if (this.radioValue === '3') {
 | 
			
		||||
				this.$emit('update', 'day', this.cycleTotal);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 平均两个值变化时
 | 
			
		||||
		averageChange() {
 | 
			
		||||
			if (this.radioValue === '4') {
 | 
			
		||||
				this.$emit('update', 'day', this.averageTotal);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 最近工作日值变化时
 | 
			
		||||
		workdayChange() {
 | 
			
		||||
			if (this.radioValue === '5') {
 | 
			
		||||
				this.$emit('update', 'day', this.workdayCheck + 'W');
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// checkbox值变化时
 | 
			
		||||
		checkboxChange() {
 | 
			
		||||
			if (this.radioValue === '7') {
 | 
			
		||||
				this.$emit('update', 'day', this.checkboxString);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	watch: {
 | 
			
		||||
		'radioValue': 'radioChange',
 | 
			
		||||
		'cycleTotal': 'cycleChange',
 | 
			
		||||
		'averageTotal': 'averageChange',
 | 
			
		||||
		'workdayCheck': 'workdayChange',
 | 
			
		||||
		'checkboxString': 'checkboxChange',
 | 
			
		||||
	},
 | 
			
		||||
	computed: {
 | 
			
		||||
		// 计算两个周期值
 | 
			
		||||
		cycleTotal: function () {
 | 
			
		||||
			const cycle01 = this.checkNum(this.cycle01, 1, 30)
 | 
			
		||||
			const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 2, 31, 31)
 | 
			
		||||
			return cycle01 + '-' + cycle02;
 | 
			
		||||
		},
 | 
			
		||||
		// 计算平均用到的值
 | 
			
		||||
		averageTotal: function () {
 | 
			
		||||
			const average01 = this.checkNum(this.average01, 1, 30)
 | 
			
		||||
			const average02 = this.checkNum(this.average02, 1, 31 - average01 || 0)
 | 
			
		||||
			return average01 + '/' + average02;
 | 
			
		||||
		},
 | 
			
		||||
		// 计算工作日格式
 | 
			
		||||
		workdayCheck: function () {
 | 
			
		||||
			return this.checkNum(this.workday, 1, 31);
 | 
			
		||||
		},
 | 
			
		||||
		// 计算勾选的checkbox值合集
 | 
			
		||||
		checkboxString: function () {
 | 
			
		||||
			let str = this.checkboxList.join();
 | 
			
		||||
			return str === '' ? '*' : str;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										114
									
								
								src/components/Crontab/hour.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								src/components/Crontab/hour.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,114 @@
 | 
			
		||||
<template>
 | 
			
		||||
	<el-form size="small">
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="1">
 | 
			
		||||
				小时,允许的通配符[, - * /]
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="2">
 | 
			
		||||
				周期从
 | 
			
		||||
				<el-input-number v-model='cycle01' :min="0" :max="22" /> -
 | 
			
		||||
				<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="23" /> 小时
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="3">
 | 
			
		||||
				从
 | 
			
		||||
				<el-input-number v-model='average01' :min="0" :max="22" /> 小时开始,每
 | 
			
		||||
				<el-input-number v-model='average02' :min="1" :max="23 - average01 || 0" /> 小时执行一次
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="4">
 | 
			
		||||
				指定
 | 
			
		||||
				<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
 | 
			
		||||
					<el-option v-for="item in 24" :key="item" :value="item-1">{{item-1}}</el-option>
 | 
			
		||||
				</el-select>
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
	</el-form>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			radioValue: 1,
 | 
			
		||||
			cycle01: 0,
 | 
			
		||||
			cycle02: 1,
 | 
			
		||||
			average01: 0,
 | 
			
		||||
			average02: 1,
 | 
			
		||||
			checkboxList: [],
 | 
			
		||||
			checkNum: this.$options.propsData.check
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	name: 'crontab-hour',
 | 
			
		||||
	props: ['check', 'cron'],
 | 
			
		||||
	methods: {
 | 
			
		||||
		// 单选按钮值变化时
 | 
			
		||||
		radioChange() {
 | 
			
		||||
			switch (this.radioValue) {
 | 
			
		||||
				case 1:
 | 
			
		||||
        	this.$emit('update', 'hour', '*')
 | 
			
		||||
        	break;
 | 
			
		||||
				case 2:
 | 
			
		||||
					this.$emit('update', 'hour', this.cycleTotal);
 | 
			
		||||
					break;
 | 
			
		||||
				case 3:
 | 
			
		||||
					this.$emit('update', 'hour', this.averageTotal);
 | 
			
		||||
					break;
 | 
			
		||||
				case 4:
 | 
			
		||||
					this.$emit('update', 'hour', this.checkboxString);
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 周期两个值变化时
 | 
			
		||||
		cycleChange() {
 | 
			
		||||
			if (this.radioValue === '2') {
 | 
			
		||||
				this.$emit('update', 'hour', this.cycleTotal);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 平均两个值变化时
 | 
			
		||||
		averageChange() {
 | 
			
		||||
			if (this.radioValue === '3') {
 | 
			
		||||
				this.$emit('update', 'hour', this.averageTotal);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// checkbox值变化时
 | 
			
		||||
		checkboxChange() {
 | 
			
		||||
			if (this.radioValue === '4') {
 | 
			
		||||
				this.$emit('update', 'hour', this.checkboxString);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	watch: {
 | 
			
		||||
		'radioValue': 'radioChange',
 | 
			
		||||
		'cycleTotal': 'cycleChange',
 | 
			
		||||
		'averageTotal': 'averageChange',
 | 
			
		||||
		'checkboxString': 'checkboxChange'
 | 
			
		||||
	},
 | 
			
		||||
	computed: {
 | 
			
		||||
		// 计算两个周期值
 | 
			
		||||
		cycleTotal: function () {
 | 
			
		||||
			const cycle01 = this.checkNum(this.cycle01, 0, 22)
 | 
			
		||||
			const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 23)
 | 
			
		||||
			return cycle01 + '-' + cycle02;
 | 
			
		||||
		},
 | 
			
		||||
		// 计算平均用到的值
 | 
			
		||||
		averageTotal: function () {
 | 
			
		||||
			const average01 = this.checkNum(this.average01, 0, 22)
 | 
			
		||||
			const average02 = this.checkNum(this.average02, 1, 23 - average01 || 0)
 | 
			
		||||
			return average01 + '/' + average02;
 | 
			
		||||
		},
 | 
			
		||||
		// 计算勾选的checkbox值合集
 | 
			
		||||
		checkboxString: function () {
 | 
			
		||||
			let str = this.checkboxList.join();
 | 
			
		||||
			return str === '' ? '*' : str;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										430
									
								
								src/components/Crontab/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										430
									
								
								src/components/Crontab/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,430 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <el-tabs type="border-card">
 | 
			
		||||
      <el-tab-pane label="秒" v-if="shouldHide('second')">
 | 
			
		||||
        <CrontabSecond
 | 
			
		||||
          @update="updateCrontabValue"
 | 
			
		||||
          :check="checkNumber"
 | 
			
		||||
          :cron="crontabValueObj"
 | 
			
		||||
          ref="cronsecond"
 | 
			
		||||
        />
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
 | 
			
		||||
      <el-tab-pane label="分钟" v-if="shouldHide('min')">
 | 
			
		||||
        <CrontabMin
 | 
			
		||||
          @update="updateCrontabValue"
 | 
			
		||||
          :check="checkNumber"
 | 
			
		||||
          :cron="crontabValueObj"
 | 
			
		||||
          ref="cronmin"
 | 
			
		||||
        />
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
 | 
			
		||||
      <el-tab-pane label="小时" v-if="shouldHide('hour')">
 | 
			
		||||
        <CrontabHour
 | 
			
		||||
          @update="updateCrontabValue"
 | 
			
		||||
          :check="checkNumber"
 | 
			
		||||
          :cron="crontabValueObj"
 | 
			
		||||
          ref="cronhour"
 | 
			
		||||
        />
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
 | 
			
		||||
      <el-tab-pane label="日" v-if="shouldHide('day')">
 | 
			
		||||
        <CrontabDay
 | 
			
		||||
          @update="updateCrontabValue"
 | 
			
		||||
          :check="checkNumber"
 | 
			
		||||
          :cron="crontabValueObj"
 | 
			
		||||
          ref="cronday"
 | 
			
		||||
        />
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
 | 
			
		||||
      <el-tab-pane label="月" v-if="shouldHide('month')">
 | 
			
		||||
        <CrontabMonth
 | 
			
		||||
          @update="updateCrontabValue"
 | 
			
		||||
          :check="checkNumber"
 | 
			
		||||
          :cron="crontabValueObj"
 | 
			
		||||
          ref="cronmonth"
 | 
			
		||||
        />
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
 | 
			
		||||
      <el-tab-pane label="周" v-if="shouldHide('week')">
 | 
			
		||||
        <CrontabWeek
 | 
			
		||||
          @update="updateCrontabValue"
 | 
			
		||||
          :check="checkNumber"
 | 
			
		||||
          :cron="crontabValueObj"
 | 
			
		||||
          ref="cronweek"
 | 
			
		||||
        />
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
 | 
			
		||||
      <el-tab-pane label="年" v-if="shouldHide('year')">
 | 
			
		||||
        <CrontabYear
 | 
			
		||||
          @update="updateCrontabValue"
 | 
			
		||||
          :check="checkNumber"
 | 
			
		||||
          :cron="crontabValueObj"
 | 
			
		||||
          ref="cronyear"
 | 
			
		||||
        />
 | 
			
		||||
      </el-tab-pane>
 | 
			
		||||
    </el-tabs>
 | 
			
		||||
 | 
			
		||||
    <div class="popup-main">
 | 
			
		||||
      <div class="popup-result">
 | 
			
		||||
        <p class="title">时间表达式</p>
 | 
			
		||||
        <table>
 | 
			
		||||
          <thead>
 | 
			
		||||
            <th v-for="item of tabTitles" width="40" :key="item">{{item}}</th>
 | 
			
		||||
            <th>Cron 表达式</th>
 | 
			
		||||
          </thead>
 | 
			
		||||
          <tbody>
 | 
			
		||||
            <td>
 | 
			
		||||
              <span>{{crontabValueObj.second}}</span>
 | 
			
		||||
            </td>
 | 
			
		||||
            <td>
 | 
			
		||||
              <span>{{crontabValueObj.min}}</span>
 | 
			
		||||
            </td>
 | 
			
		||||
            <td>
 | 
			
		||||
              <span>{{crontabValueObj.hour}}</span>
 | 
			
		||||
            </td>
 | 
			
		||||
            <td>
 | 
			
		||||
              <span>{{crontabValueObj.day}}</span>
 | 
			
		||||
            </td>
 | 
			
		||||
            <td>
 | 
			
		||||
              <span>{{crontabValueObj.month}}</span>
 | 
			
		||||
            </td>
 | 
			
		||||
            <td>
 | 
			
		||||
              <span>{{crontabValueObj.week}}</span>
 | 
			
		||||
            </td>
 | 
			
		||||
            <td>
 | 
			
		||||
              <span>{{crontabValueObj.year}}</span>
 | 
			
		||||
            </td>
 | 
			
		||||
            <td>
 | 
			
		||||
              <span>{{crontabValueString}}</span>
 | 
			
		||||
            </td>
 | 
			
		||||
          </tbody>
 | 
			
		||||
        </table>
 | 
			
		||||
      </div>
 | 
			
		||||
      <CrontabResult :ex="crontabValueString"></CrontabResult>
 | 
			
		||||
 | 
			
		||||
      <div class="pop_btn">
 | 
			
		||||
        <el-button size="small" type="primary" @click="submitFill">确定</el-button>
 | 
			
		||||
        <el-button size="small" type="warning" @click="clearCron">重置</el-button>
 | 
			
		||||
        <el-button size="small" @click="hidePopup">取消</el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import CrontabSecond from "./second.vue";
 | 
			
		||||
import CrontabMin from "./min.vue";
 | 
			
		||||
import CrontabHour from "./hour.vue";
 | 
			
		||||
import CrontabDay from "./day.vue";
 | 
			
		||||
import CrontabMonth from "./month.vue";
 | 
			
		||||
import CrontabWeek from "./week.vue";
 | 
			
		||||
import CrontabYear from "./year.vue";
 | 
			
		||||
import CrontabResult from "./result.vue";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      tabTitles: ["秒", "分钟", "小时", "日", "月", "周", "年"],
 | 
			
		||||
      tabActive: 0,
 | 
			
		||||
      myindex: 0,
 | 
			
		||||
      crontabValueObj: {
 | 
			
		||||
        second: "*",
 | 
			
		||||
        min: "*",
 | 
			
		||||
        hour: "*",
 | 
			
		||||
        day: "*",
 | 
			
		||||
        month: "*",
 | 
			
		||||
        week: "?",
 | 
			
		||||
        year: "",
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  name: "vcrontab",
 | 
			
		||||
  props: ["expression", "hideComponent"],
 | 
			
		||||
  methods: {
 | 
			
		||||
    shouldHide(key) {
 | 
			
		||||
      return !(this.hideComponent && this.hideComponent.includes(key));
 | 
			
		||||
 | 
			
		||||
    },
 | 
			
		||||
    resolveExp() {
 | 
			
		||||
      // 反解析 表达式
 | 
			
		||||
      if (this.expression) {
 | 
			
		||||
        let arr = this.expression.split(" ");
 | 
			
		||||
        if (arr.length >= 6) {
 | 
			
		||||
          //6 位以上是合法表达式
 | 
			
		||||
          let obj = {
 | 
			
		||||
            second: arr[0],
 | 
			
		||||
            min: arr[1],
 | 
			
		||||
            hour: arr[2],
 | 
			
		||||
            day: arr[3],
 | 
			
		||||
            month: arr[4],
 | 
			
		||||
            week: arr[5],
 | 
			
		||||
            year: arr[6] ? arr[6] : "",
 | 
			
		||||
          };
 | 
			
		||||
          this.crontabValueObj = {
 | 
			
		||||
            ...obj,
 | 
			
		||||
          };
 | 
			
		||||
          for (let i in obj) {
 | 
			
		||||
            if (obj[i]) this.changeRadio(i, obj[i]);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        // 没有传入的表达式 则还原
 | 
			
		||||
        this.clearCron();
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    // tab切换值
 | 
			
		||||
    tabCheck(index) {
 | 
			
		||||
      this.tabActive = index;
 | 
			
		||||
    },
 | 
			
		||||
    // 由子组件触发,更改表达式组成的字段值
 | 
			
		||||
    updateCrontabValue(name, value, from) {
 | 
			
		||||
      "updateCrontabValue", name, value, from;
 | 
			
		||||
      this.crontabValueObj[name] = value;
 | 
			
		||||
      if (from && from !== name) {
 | 
			
		||||
        console.log(`来自组件 ${from} 改变了 ${name} ${value}`);
 | 
			
		||||
        this.changeRadio(name, value);
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    // 赋值到组件
 | 
			
		||||
    changeRadio(name, value) {
 | 
			
		||||
      let arr = ["second", "min", "hour", "month"],
 | 
			
		||||
        refName = "cron" + name,
 | 
			
		||||
        insValue;
 | 
			
		||||
 | 
			
		||||
      if (!this.$refs[refName]) return;
 | 
			
		||||
 | 
			
		||||
      if (arr.includes(name)) {
 | 
			
		||||
        if (value === "*") {
 | 
			
		||||
          insValue = 1;
 | 
			
		||||
        } else if (value.indexOf("-") > -1) {
 | 
			
		||||
          let indexArr = value.split("-");
 | 
			
		||||
          isNaN(indexArr[0])
 | 
			
		||||
            ? (this.$refs[refName].cycle01 = 0)
 | 
			
		||||
            : (this.$refs[refName].cycle01 = indexArr[0]);
 | 
			
		||||
          this.$refs[refName].cycle02 = indexArr[1];
 | 
			
		||||
          insValue = 2;
 | 
			
		||||
        } else if (value.indexOf("/") > -1) {
 | 
			
		||||
          let indexArr = value.split("/");
 | 
			
		||||
          isNaN(indexArr[0])
 | 
			
		||||
            ? (this.$refs[refName].average01 = 0)
 | 
			
		||||
            : (this.$refs[refName].average01 = indexArr[0]);
 | 
			
		||||
          this.$refs[refName].average02 = indexArr[1];
 | 
			
		||||
          insValue = 3;
 | 
			
		||||
        } else {
 | 
			
		||||
          insValue = 4;
 | 
			
		||||
          this.$refs[refName].checkboxList = value.split(",");
 | 
			
		||||
        }
 | 
			
		||||
      } else if (name === "day") {
 | 
			
		||||
        if (value === "*") {
 | 
			
		||||
          insValue = 1;
 | 
			
		||||
        } else if (value === "?") {
 | 
			
		||||
          insValue = 2;
 | 
			
		||||
        } else if (value.indexOf("-") > -1) {
 | 
			
		||||
          let indexArr = value.split("-");
 | 
			
		||||
          isNaN(indexArr[0])
 | 
			
		||||
            ? (this.$refs[refName].cycle01 = 0)
 | 
			
		||||
            : (this.$refs[refName].cycle01 = indexArr[0]);
 | 
			
		||||
          this.$refs[refName].cycle02 = indexArr[1];
 | 
			
		||||
          insValue = 3;
 | 
			
		||||
        } else if (value.indexOf("/") > -1) {
 | 
			
		||||
          let indexArr = value.split("/");
 | 
			
		||||
          isNaN(indexArr[0])
 | 
			
		||||
            ? (this.$refs[refName].average01 = 0)
 | 
			
		||||
            : (this.$refs[refName].average01 = indexArr[0]);
 | 
			
		||||
          this.$refs[refName].average02 = indexArr[1];
 | 
			
		||||
          insValue = 4;
 | 
			
		||||
        } else if (value.indexOf("W") > -1) {
 | 
			
		||||
          let indexArr = value.split("W");
 | 
			
		||||
          isNaN(indexArr[0])
 | 
			
		||||
            ? (this.$refs[refName].workday = 0)
 | 
			
		||||
            : (this.$refs[refName].workday = indexArr[0]);
 | 
			
		||||
          insValue = 5;
 | 
			
		||||
        } else if (value === "L") {
 | 
			
		||||
          insValue = 6;
 | 
			
		||||
        } else {
 | 
			
		||||
          this.$refs[refName].checkboxList = value.split(",");
 | 
			
		||||
          insValue = 7;
 | 
			
		||||
        }
 | 
			
		||||
      } else if (name === "week") {
 | 
			
		||||
        if (value === "*") {
 | 
			
		||||
          insValue = 1;
 | 
			
		||||
        } else if (value === "?") {
 | 
			
		||||
          insValue = 2;
 | 
			
		||||
        } else if (value.indexOf("-") > -1) {
 | 
			
		||||
          let indexArr = value.split("-");
 | 
			
		||||
          isNaN(indexArr[0])
 | 
			
		||||
            ? (this.$refs[refName].cycle01 = 0)
 | 
			
		||||
            : (this.$refs[refName].cycle01 = indexArr[0]);
 | 
			
		||||
          this.$refs[refName].cycle02 = indexArr[1];
 | 
			
		||||
          insValue = 3;
 | 
			
		||||
        } else if (value.indexOf("#") > -1) {
 | 
			
		||||
          let indexArr = value.split("#");
 | 
			
		||||
          isNaN(indexArr[0])
 | 
			
		||||
            ? (this.$refs[refName].average01 = 1)
 | 
			
		||||
            : (this.$refs[refName].average01 = indexArr[0]);
 | 
			
		||||
          this.$refs[refName].average02 = indexArr[1];
 | 
			
		||||
          insValue = 4;
 | 
			
		||||
        } else if (value.indexOf("L") > -1) {
 | 
			
		||||
          let indexArr = value.split("L");
 | 
			
		||||
          isNaN(indexArr[0])
 | 
			
		||||
            ? (this.$refs[refName].weekday = 1)
 | 
			
		||||
            : (this.$refs[refName].weekday = indexArr[0]);
 | 
			
		||||
          insValue = 5;
 | 
			
		||||
        } else {
 | 
			
		||||
          this.$refs[refName].checkboxList = value.split(",");
 | 
			
		||||
          insValue = 6;
 | 
			
		||||
        }
 | 
			
		||||
      } else if (name === "year") {
 | 
			
		||||
        if (value === "") {
 | 
			
		||||
          insValue = 1;
 | 
			
		||||
        } else if (value === "*") {
 | 
			
		||||
          insValue = 2;
 | 
			
		||||
        } else if (value.indexOf("-") > -1) {
 | 
			
		||||
          insValue = 3;
 | 
			
		||||
        } else if (value.indexOf("/") > -1) {
 | 
			
		||||
          insValue = 4;
 | 
			
		||||
        } else {
 | 
			
		||||
          this.$refs[refName].checkboxList = value.split(",");
 | 
			
		||||
          insValue = 5;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      this.$refs[refName].radioValue = insValue;
 | 
			
		||||
    },
 | 
			
		||||
    // 表单选项的子组件校验数字格式(通过-props传递)
 | 
			
		||||
    checkNumber(value, minLimit, maxLimit) {
 | 
			
		||||
      // 检查必须为整数
 | 
			
		||||
      value = Math.floor(value);
 | 
			
		||||
      if (value < minLimit) {
 | 
			
		||||
        value = minLimit;
 | 
			
		||||
      } else if (value > maxLimit) {
 | 
			
		||||
        value = maxLimit;
 | 
			
		||||
      }
 | 
			
		||||
      return value;
 | 
			
		||||
    },
 | 
			
		||||
    // 隐藏弹窗
 | 
			
		||||
    hidePopup() {
 | 
			
		||||
      this.$emit("hide");
 | 
			
		||||
    },
 | 
			
		||||
    // 填充表达式
 | 
			
		||||
    submitFill() {
 | 
			
		||||
      this.$emit("fill", this.crontabValueString);
 | 
			
		||||
      this.hidePopup();
 | 
			
		||||
    },
 | 
			
		||||
    clearCron() {
 | 
			
		||||
      // 还原选择项
 | 
			
		||||
      ("准备还原");
 | 
			
		||||
      this.crontabValueObj = {
 | 
			
		||||
        second: "*",
 | 
			
		||||
        min: "*",
 | 
			
		||||
        hour: "*",
 | 
			
		||||
        day: "*",
 | 
			
		||||
        month: "*",
 | 
			
		||||
        week: "?",
 | 
			
		||||
        year: "",
 | 
			
		||||
      };
 | 
			
		||||
      for (let j in this.crontabValueObj) {
 | 
			
		||||
        this.changeRadio(j, this.crontabValueObj[j]);
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
    crontabValueString: function() {
 | 
			
		||||
      let obj = this.crontabValueObj;
 | 
			
		||||
      let str =
 | 
			
		||||
        obj.second +
 | 
			
		||||
        " " +
 | 
			
		||||
        obj.min +
 | 
			
		||||
        " " +
 | 
			
		||||
        obj.hour +
 | 
			
		||||
        " " +
 | 
			
		||||
        obj.day +
 | 
			
		||||
        " " +
 | 
			
		||||
        obj.month +
 | 
			
		||||
        " " +
 | 
			
		||||
        obj.week +
 | 
			
		||||
        (obj.year === "" ? "" : " " + obj.year);
 | 
			
		||||
      return str;
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  components: {
 | 
			
		||||
    CrontabSecond,
 | 
			
		||||
    CrontabMin,
 | 
			
		||||
    CrontabHour,
 | 
			
		||||
    CrontabDay,
 | 
			
		||||
    CrontabMonth,
 | 
			
		||||
    CrontabWeek,
 | 
			
		||||
    CrontabYear,
 | 
			
		||||
    CrontabResult,
 | 
			
		||||
  },
 | 
			
		||||
  watch: {
 | 
			
		||||
    expression: "resolveExp",
 | 
			
		||||
    hideComponent(value) {
 | 
			
		||||
      // 隐藏部分组件
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  mounted: function() {
 | 
			
		||||
    this.resolveExp();
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
<style scoped>
 | 
			
		||||
.pop_btn {
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  margin-top: 20px;
 | 
			
		||||
}
 | 
			
		||||
.popup-main {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  margin: 10px auto;
 | 
			
		||||
  background: #fff;
 | 
			
		||||
  border-radius: 5px;
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
.popup-title {
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  line-height: 34px;
 | 
			
		||||
  padding-top: 6px;
 | 
			
		||||
  background: #f2f2f2;
 | 
			
		||||
}
 | 
			
		||||
.popup-result {
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
  line-height: 24px;
 | 
			
		||||
  margin: 25px auto;
 | 
			
		||||
  padding: 15px 10px 10px;
 | 
			
		||||
  border: 1px solid #ccc;
 | 
			
		||||
  position: relative;
 | 
			
		||||
}
 | 
			
		||||
.popup-result .title {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  top: -28px;
 | 
			
		||||
  left: 50%;
 | 
			
		||||
  width: 140px;
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
  margin-left: -70px;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  line-height: 30px;
 | 
			
		||||
  background: #fff;
 | 
			
		||||
}
 | 
			
		||||
.popup-result table {
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  margin: 0 auto;
 | 
			
		||||
}
 | 
			
		||||
.popup-result table span {
 | 
			
		||||
  display: block;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  font-family: arial;
 | 
			
		||||
  line-height: 30px;
 | 
			
		||||
  height: 30px;
 | 
			
		||||
  white-space: nowrap;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  border: 1px solid #e8e8e8;
 | 
			
		||||
}
 | 
			
		||||
.popup-result-scroll {
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
  line-height: 24px;
 | 
			
		||||
  height: 10em;
 | 
			
		||||
  overflow-y: auto;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										116
									
								
								src/components/Crontab/min.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/components/Crontab/min.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
			
		||||
<template>
 | 
			
		||||
	<el-form size="small">
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="1">
 | 
			
		||||
				分钟,允许的通配符[, - * /]
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="2">
 | 
			
		||||
				周期从
 | 
			
		||||
				<el-input-number v-model='cycle01' :min="0" :max="58" /> -
 | 
			
		||||
				<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="59" /> 分钟
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="3">
 | 
			
		||||
				从
 | 
			
		||||
				<el-input-number v-model='average01' :min="0" :max="58" /> 分钟开始,每
 | 
			
		||||
				<el-input-number v-model='average02' :min="1" :max="59 - average01 || 0" /> 分钟执行一次
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="4">
 | 
			
		||||
				指定
 | 
			
		||||
				<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
 | 
			
		||||
					<el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option>
 | 
			
		||||
				</el-select>
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
	</el-form>
 | 
			
		||||
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			radioValue: 1,
 | 
			
		||||
			cycle01: 1,
 | 
			
		||||
			cycle02: 2,
 | 
			
		||||
			average01: 0,
 | 
			
		||||
			average02: 1,
 | 
			
		||||
			checkboxList: [],
 | 
			
		||||
			checkNum: this.$options.propsData.check
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	name: 'crontab-min',
 | 
			
		||||
	props: ['check', 'cron'],
 | 
			
		||||
	methods: {
 | 
			
		||||
		// 单选按钮值变化时
 | 
			
		||||
		radioChange() {
 | 
			
		||||
			switch (this.radioValue) {
 | 
			
		||||
				case 1:
 | 
			
		||||
					this.$emit('update', 'min', '*', 'min');
 | 
			
		||||
					break;
 | 
			
		||||
				case 2:
 | 
			
		||||
					this.$emit('update', 'min', this.cycleTotal, 'min');
 | 
			
		||||
					break;
 | 
			
		||||
				case 3:
 | 
			
		||||
					this.$emit('update', 'min', this.averageTotal, 'min');
 | 
			
		||||
					break;
 | 
			
		||||
				case 4:
 | 
			
		||||
					this.$emit('update', 'min', this.checkboxString, 'min');
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 周期两个值变化时
 | 
			
		||||
		cycleChange() {
 | 
			
		||||
			if (this.radioValue === '2') {
 | 
			
		||||
				this.$emit('update', 'min', this.cycleTotal, 'min');
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 平均两个值变化时
 | 
			
		||||
		averageChange() {
 | 
			
		||||
			if (this.radioValue === '3') {
 | 
			
		||||
				this.$emit('update', 'min', this.averageTotal, 'min');
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// checkbox值变化时
 | 
			
		||||
		checkboxChange() {
 | 
			
		||||
			if (this.radioValue === '4') {
 | 
			
		||||
				this.$emit('update', 'min', this.checkboxString, 'min');
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
	},
 | 
			
		||||
	watch: {
 | 
			
		||||
		'radioValue': 'radioChange',
 | 
			
		||||
		'cycleTotal': 'cycleChange',
 | 
			
		||||
		'averageTotal': 'averageChange',
 | 
			
		||||
		'checkboxString': 'checkboxChange',
 | 
			
		||||
	},
 | 
			
		||||
	computed: {
 | 
			
		||||
		// 计算两个周期值
 | 
			
		||||
		cycleTotal: function () {
 | 
			
		||||
			const cycle01 = this.checkNum(this.cycle01, 0, 58)
 | 
			
		||||
			const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 59)
 | 
			
		||||
			return cycle01 + '-' + cycle02;
 | 
			
		||||
		},
 | 
			
		||||
		// 计算平均用到的值
 | 
			
		||||
		averageTotal: function () {
 | 
			
		||||
			const average01 = this.checkNum(this.average01, 0, 58)
 | 
			
		||||
			const average02 = this.checkNum(this.average02, 1, 59 - average01 || 0)
 | 
			
		||||
			return average01 + '/' + average02;
 | 
			
		||||
		},
 | 
			
		||||
		// 计算勾选的checkbox值合集
 | 
			
		||||
		checkboxString: function () {
 | 
			
		||||
			let str = this.checkboxList.join();
 | 
			
		||||
			return str === '' ? '*' : str;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										114
									
								
								src/components/Crontab/month.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								src/components/Crontab/month.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,114 @@
 | 
			
		||||
<template>
 | 
			
		||||
	<el-form size='small'>
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="1">
 | 
			
		||||
				月,允许的通配符[, - * /]
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="2">
 | 
			
		||||
				周期从
 | 
			
		||||
				<el-input-number v-model='cycle01' :min="1" :max="11" /> -
 | 
			
		||||
				<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 2" :max="12" /> 月
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="3">
 | 
			
		||||
				从
 | 
			
		||||
				<el-input-number v-model='average01' :min="1" :max="11" /> 月开始,每
 | 
			
		||||
				<el-input-number v-model='average02' :min="1" :max="12 - average01 || 0" /> 月月执行一次
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="4">
 | 
			
		||||
				指定
 | 
			
		||||
				<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
 | 
			
		||||
					<el-option v-for="item in 12" :key="item" :value="item">{{item}}</el-option>
 | 
			
		||||
				</el-select>
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
	</el-form>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			radioValue: 1,
 | 
			
		||||
			cycle01: 1,
 | 
			
		||||
			cycle02: 2,
 | 
			
		||||
			average01: 1,
 | 
			
		||||
			average02: 1,
 | 
			
		||||
			checkboxList: [],
 | 
			
		||||
			checkNum: this.check
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	name: 'crontab-month',
 | 
			
		||||
	props: ['check', 'cron'],
 | 
			
		||||
	methods: {
 | 
			
		||||
		// 单选按钮值变化时
 | 
			
		||||
		radioChange() {
 | 
			
		||||
			switch (this.radioValue) {
 | 
			
		||||
				case 1:
 | 
			
		||||
					this.$emit('update', 'month', '*');
 | 
			
		||||
					break;
 | 
			
		||||
				case 2:
 | 
			
		||||
					this.$emit('update', 'month', this.cycleTotal);
 | 
			
		||||
					break;
 | 
			
		||||
				case 3:
 | 
			
		||||
					this.$emit('update', 'month', this.averageTotal);
 | 
			
		||||
					break;
 | 
			
		||||
				case 4:
 | 
			
		||||
					this.$emit('update', 'month', this.checkboxString);
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 周期两个值变化时
 | 
			
		||||
		cycleChange() {
 | 
			
		||||
			if (this.radioValue === '2') {
 | 
			
		||||
				this.$emit('update', 'month', this.cycleTotal);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 平均两个值变化时
 | 
			
		||||
		averageChange() {
 | 
			
		||||
			if (this.radioValue === '3') {
 | 
			
		||||
				this.$emit('update', 'month', this.averageTotal);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// checkbox值变化时
 | 
			
		||||
		checkboxChange() {
 | 
			
		||||
			if (this.radioValue === '4') {
 | 
			
		||||
				this.$emit('update', 'month', this.checkboxString);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	watch: {
 | 
			
		||||
		'radioValue': 'radioChange',
 | 
			
		||||
		'cycleTotal': 'cycleChange',
 | 
			
		||||
		'averageTotal': 'averageChange',
 | 
			
		||||
		'checkboxString': 'checkboxChange'
 | 
			
		||||
	},
 | 
			
		||||
	computed: {
 | 
			
		||||
		// 计算两个周期值
 | 
			
		||||
		cycleTotal: function () {
 | 
			
		||||
			const cycle01 = this.checkNum(this.cycle01, 1, 11)
 | 
			
		||||
			const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 2, 12)
 | 
			
		||||
			return cycle01 + '-' + cycle02;
 | 
			
		||||
		},
 | 
			
		||||
		// 计算平均用到的值
 | 
			
		||||
		averageTotal: function () {
 | 
			
		||||
			const average01 = this.checkNum(this.average01, 1, 11)
 | 
			
		||||
			const average02 = this.checkNum(this.average02, 1, 12 - average01 || 0)
 | 
			
		||||
			return average01 + '/' + average02;
 | 
			
		||||
		},
 | 
			
		||||
		// 计算勾选的checkbox值合集
 | 
			
		||||
		checkboxString: function () {
 | 
			
		||||
			let str = this.checkboxList.join();
 | 
			
		||||
			return str === '' ? '*' : str;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										559
									
								
								src/components/Crontab/result.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										559
									
								
								src/components/Crontab/result.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,559 @@
 | 
			
		||||
<template>
 | 
			
		||||
	<div class="popup-result">
 | 
			
		||||
		<p class="title">最近5次运行时间</p>
 | 
			
		||||
		<ul class="popup-result-scroll">
 | 
			
		||||
			<template v-if='isShow'>
 | 
			
		||||
				<li v-for='item in resultList' :key="item">{{item}}</li>
 | 
			
		||||
			</template>
 | 
			
		||||
			<li v-else>计算结果中...</li>
 | 
			
		||||
		</ul>
 | 
			
		||||
	</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			dayRule: '',
 | 
			
		||||
			dayRuleSup: '',
 | 
			
		||||
			dateArr: [],
 | 
			
		||||
			resultList: [],
 | 
			
		||||
			isShow: false
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	name: 'crontab-result',
 | 
			
		||||
	methods: {
 | 
			
		||||
		// 表达式值变化时,开始去计算结果
 | 
			
		||||
		expressionChange() {
 | 
			
		||||
 | 
			
		||||
			// 计算开始-隐藏结果
 | 
			
		||||
			this.isShow = false;
 | 
			
		||||
			// 获取规则数组[0秒、1分、2时、3日、4月、5星期、6年]
 | 
			
		||||
			let ruleArr = this.$options.propsData.ex.split(' ');
 | 
			
		||||
			// 用于记录进入循环的次数
 | 
			
		||||
			let nums = 0;
 | 
			
		||||
			// 用于暂时存符号时间规则结果的数组
 | 
			
		||||
			let resultArr = [];
 | 
			
		||||
			// 获取当前时间精确至[年、月、日、时、分、秒]
 | 
			
		||||
			let nTime = new Date();
 | 
			
		||||
			let nYear = nTime.getFullYear();
 | 
			
		||||
			let nMonth = nTime.getMonth() + 1;
 | 
			
		||||
			let nDay = nTime.getDate();
 | 
			
		||||
			let nHour = nTime.getHours();
 | 
			
		||||
			let nMin = nTime.getMinutes();
 | 
			
		||||
			let nSecond = nTime.getSeconds();
 | 
			
		||||
			// 根据规则获取到近100年可能年数组、月数组等等
 | 
			
		||||
			this.getSecondArr(ruleArr[0]);
 | 
			
		||||
			this.getMinArr(ruleArr[1]);
 | 
			
		||||
			this.getHourArr(ruleArr[2]);
 | 
			
		||||
			this.getDayArr(ruleArr[3]);
 | 
			
		||||
			this.getMonthArr(ruleArr[4]);
 | 
			
		||||
			this.getWeekArr(ruleArr[5]);
 | 
			
		||||
			this.getYearArr(ruleArr[6], nYear);
 | 
			
		||||
			// 将获取到的数组赋值-方便使用
 | 
			
		||||
			let sDate = this.dateArr[0];
 | 
			
		||||
			let mDate = this.dateArr[1];
 | 
			
		||||
			let hDate = this.dateArr[2];
 | 
			
		||||
			let DDate = this.dateArr[3];
 | 
			
		||||
			let MDate = this.dateArr[4];
 | 
			
		||||
			let YDate = this.dateArr[5];
 | 
			
		||||
			// 获取当前时间在数组中的索引
 | 
			
		||||
			let sIdx = this.getIndex(sDate, nSecond);
 | 
			
		||||
			let mIdx = this.getIndex(mDate, nMin);
 | 
			
		||||
			let hIdx = this.getIndex(hDate, nHour);
 | 
			
		||||
			let DIdx = this.getIndex(DDate, nDay);
 | 
			
		||||
			let MIdx = this.getIndex(MDate, nMonth);
 | 
			
		||||
			let YIdx = this.getIndex(YDate, nYear);
 | 
			
		||||
			// 重置月日时分秒的函数(后面用的比较多)
 | 
			
		||||
			const resetSecond = function () {
 | 
			
		||||
				sIdx = 0;
 | 
			
		||||
				nSecond = sDate[sIdx]
 | 
			
		||||
			}
 | 
			
		||||
			const resetMin = function () {
 | 
			
		||||
				mIdx = 0;
 | 
			
		||||
				nMin = mDate[mIdx]
 | 
			
		||||
				resetSecond();
 | 
			
		||||
			}
 | 
			
		||||
			const resetHour = function () {
 | 
			
		||||
				hIdx = 0;
 | 
			
		||||
				nHour = hDate[hIdx]
 | 
			
		||||
				resetMin();
 | 
			
		||||
			}
 | 
			
		||||
			const resetDay = function () {
 | 
			
		||||
				DIdx = 0;
 | 
			
		||||
				nDay = DDate[DIdx]
 | 
			
		||||
				resetHour();
 | 
			
		||||
			}
 | 
			
		||||
			const resetMonth = function () {
 | 
			
		||||
				MIdx = 0;
 | 
			
		||||
				nMonth = MDate[MIdx]
 | 
			
		||||
				resetDay();
 | 
			
		||||
			}
 | 
			
		||||
			// 如果当前年份不为数组中当前值
 | 
			
		||||
			if (nYear !== YDate[YIdx]) {
 | 
			
		||||
				resetMonth();
 | 
			
		||||
			}
 | 
			
		||||
			// 如果当前月份不为数组中当前值
 | 
			
		||||
			if (nMonth !== MDate[MIdx]) {
 | 
			
		||||
				resetDay();
 | 
			
		||||
			}
 | 
			
		||||
			// 如果当前“日”不为数组中当前值
 | 
			
		||||
			if (nDay !== DDate[DIdx]) {
 | 
			
		||||
				resetHour();
 | 
			
		||||
			}
 | 
			
		||||
			// 如果当前“时”不为数组中当前值
 | 
			
		||||
			if (nHour !== hDate[hIdx]) {
 | 
			
		||||
				resetMin();
 | 
			
		||||
			}
 | 
			
		||||
			// 如果当前“分”不为数组中当前值
 | 
			
		||||
			if (nMin !== mDate[mIdx]) {
 | 
			
		||||
				resetSecond();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// 循环年份数组
 | 
			
		||||
			goYear: for (let Yi = YIdx; Yi < YDate.length; Yi++) {
 | 
			
		||||
				let YY = YDate[Yi];
 | 
			
		||||
				// 如果到达最大值时
 | 
			
		||||
				if (nMonth > MDate[MDate.length - 1]) {
 | 
			
		||||
					resetMonth();
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				// 循环月份数组
 | 
			
		||||
				goMonth: for (let Mi = MIdx; Mi < MDate.length; Mi++) {
 | 
			
		||||
					// 赋值、方便后面运算
 | 
			
		||||
					let MM = MDate[Mi];
 | 
			
		||||
					MM = MM < 10 ? '0' + MM : MM;
 | 
			
		||||
					// 如果到达最大值时
 | 
			
		||||
					if (nDay > DDate[DDate.length - 1]) {
 | 
			
		||||
						resetDay();
 | 
			
		||||
						if (Mi === MDate.length - 1) {
 | 
			
		||||
							resetMonth();
 | 
			
		||||
							continue goYear;
 | 
			
		||||
						}
 | 
			
		||||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
					// 循环日期数组
 | 
			
		||||
					goDay: for (let Di = DIdx; Di < DDate.length; Di++) {
 | 
			
		||||
						// 赋值、方便后面运算
 | 
			
		||||
						let DD = DDate[Di];
 | 
			
		||||
						let thisDD = DD < 10 ? '0' + DD : DD;
 | 
			
		||||
 | 
			
		||||
						// 如果到达最大值时
 | 
			
		||||
						if (nHour > hDate[hDate.length - 1]) {
 | 
			
		||||
							resetHour();
 | 
			
		||||
							if (Di === DDate.length - 1) {
 | 
			
		||||
								resetDay();
 | 
			
		||||
								if (Mi === MDate.length - 1) {
 | 
			
		||||
									resetMonth();
 | 
			
		||||
									continue goYear;
 | 
			
		||||
								}
 | 
			
		||||
								continue goMonth;
 | 
			
		||||
							}
 | 
			
		||||
							continue;
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						// 判断日期的合法性,不合法的话也是跳出当前循环
 | 
			
		||||
						if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true && this.dayRule !== 'workDay' && this.dayRule !== 'lastWeek' && this.dayRule !== 'lastDay') {
 | 
			
		||||
							resetDay();
 | 
			
		||||
							continue goMonth;
 | 
			
		||||
						}
 | 
			
		||||
						// 如果日期规则中有值时
 | 
			
		||||
						if (this.dayRule === 'lastDay') {
 | 
			
		||||
							// 如果不是合法日期则需要将前将日期调到合法日期即月末最后一天
 | 
			
		||||
 | 
			
		||||
							if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
 | 
			
		||||
								while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
 | 
			
		||||
									DD--;
 | 
			
		||||
 | 
			
		||||
									thisDD = DD < 10 ? '0' + DD : DD;
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
						} else if (this.dayRule === 'workDay') {
 | 
			
		||||
							// 校验并调整如果是2月30号这种日期传进来时需调整至正常月底
 | 
			
		||||
							if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
 | 
			
		||||
								while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
 | 
			
		||||
									DD--;
 | 
			
		||||
									thisDD = DD < 10 ? '0' + DD : DD;
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
							// 获取达到条件的日期是星期X
 | 
			
		||||
							let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week');
 | 
			
		||||
							// 当星期日时
 | 
			
		||||
							if (thisWeek === 1) {
 | 
			
		||||
								// 先找下一个日,并判断是否为月底
 | 
			
		||||
								DD++;
 | 
			
		||||
								thisDD = DD < 10 ? '0' + DD : DD;
 | 
			
		||||
								// 判断下一日已经不是合法日期
 | 
			
		||||
								if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
 | 
			
		||||
									DD -= 3;
 | 
			
		||||
								}
 | 
			
		||||
							} else if (thisWeek === 7) {
 | 
			
		||||
								// 当星期6时只需判断不是1号就可进行操作
 | 
			
		||||
								if (this.dayRuleSup !== 1) {
 | 
			
		||||
									DD--;
 | 
			
		||||
								} else {
 | 
			
		||||
									DD += 2;
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
						} else if (this.dayRule === 'weekDay') {
 | 
			
		||||
							// 如果指定了是星期几
 | 
			
		||||
							// 获取当前日期是属于星期几
 | 
			
		||||
							let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week');
 | 
			
		||||
							// 校验当前星期是否在星期池(dayRuleSup)中
 | 
			
		||||
							if (this.dayRuleSup.indexOf(thisWeek) < 0) {
 | 
			
		||||
								// 如果到达最大值时
 | 
			
		||||
								if (Di === DDate.length - 1) {
 | 
			
		||||
									resetDay();
 | 
			
		||||
									if (Mi === MDate.length - 1) {
 | 
			
		||||
										resetMonth();
 | 
			
		||||
										continue goYear;
 | 
			
		||||
									}
 | 
			
		||||
									continue goMonth;
 | 
			
		||||
								}
 | 
			
		||||
								continue;
 | 
			
		||||
							}
 | 
			
		||||
						} else if (this.dayRule === 'assWeek') {
 | 
			
		||||
							// 如果指定了是第几周的星期几
 | 
			
		||||
							// 获取每月1号是属于星期几
 | 
			
		||||
							let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week');
 | 
			
		||||
							if (this.dayRuleSup[1] >= thisWeek) {
 | 
			
		||||
								DD = (this.dayRuleSup[0] - 1) * 7 + this.dayRuleSup[1] - thisWeek + 1;
 | 
			
		||||
							} else {
 | 
			
		||||
								DD = this.dayRuleSup[0] * 7 + this.dayRuleSup[1] - thisWeek + 1;
 | 
			
		||||
							}
 | 
			
		||||
						} else if (this.dayRule === 'lastWeek') {
 | 
			
		||||
							// 如果指定了每月最后一个星期几
 | 
			
		||||
							// 校验并调整如果是2月30号这种日期传进来时需调整至正常月底
 | 
			
		||||
							if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
 | 
			
		||||
								while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) {
 | 
			
		||||
									DD--;
 | 
			
		||||
									thisDD = DD < 10 ? '0' + DD : DD;
 | 
			
		||||
								}
 | 
			
		||||
							}
 | 
			
		||||
							// 获取月末最后一天是星期几
 | 
			
		||||
							let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week');
 | 
			
		||||
							// 找到要求中最近的那个星期几
 | 
			
		||||
							if (this.dayRuleSup < thisWeek) {
 | 
			
		||||
								DD -= thisWeek - this.dayRuleSup;
 | 
			
		||||
							} else if (this.dayRuleSup > thisWeek) {
 | 
			
		||||
								DD -= 7 - (this.dayRuleSup - thisWeek)
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
						// 判断时间值是否小于10置换成“05”这种格式
 | 
			
		||||
						DD = DD < 10 ? '0' + DD : DD;
 | 
			
		||||
 | 
			
		||||
						// 循环“时”数组
 | 
			
		||||
						goHour: for (let hi = hIdx; hi < hDate.length; hi++) {
 | 
			
		||||
							let hh = hDate[hi] < 10 ? '0' + hDate[hi] : hDate[hi]
 | 
			
		||||
 | 
			
		||||
							// 如果到达最大值时
 | 
			
		||||
							if (nMin > mDate[mDate.length - 1]) {
 | 
			
		||||
								resetMin();
 | 
			
		||||
								if (hi === hDate.length - 1) {
 | 
			
		||||
									resetHour();
 | 
			
		||||
									if (Di === DDate.length - 1) {
 | 
			
		||||
										resetDay();
 | 
			
		||||
										if (Mi === MDate.length - 1) {
 | 
			
		||||
											resetMonth();
 | 
			
		||||
											continue goYear;
 | 
			
		||||
										}
 | 
			
		||||
										continue goMonth;
 | 
			
		||||
									}
 | 
			
		||||
									continue goDay;
 | 
			
		||||
								}
 | 
			
		||||
								continue;
 | 
			
		||||
							}
 | 
			
		||||
							// 循环"分"数组
 | 
			
		||||
							goMin: for (let mi = mIdx; mi < mDate.length; mi++) {
 | 
			
		||||
								let mm = mDate[mi] < 10 ? '0' + mDate[mi] : mDate[mi];
 | 
			
		||||
 | 
			
		||||
								// 如果到达最大值时
 | 
			
		||||
								if (nSecond > sDate[sDate.length - 1]) {
 | 
			
		||||
									resetSecond();
 | 
			
		||||
									if (mi === mDate.length - 1) {
 | 
			
		||||
										resetMin();
 | 
			
		||||
										if (hi === hDate.length - 1) {
 | 
			
		||||
											resetHour();
 | 
			
		||||
											if (Di === DDate.length - 1) {
 | 
			
		||||
												resetDay();
 | 
			
		||||
												if (Mi === MDate.length - 1) {
 | 
			
		||||
													resetMonth();
 | 
			
		||||
													continue goYear;
 | 
			
		||||
												}
 | 
			
		||||
												continue goMonth;
 | 
			
		||||
											}
 | 
			
		||||
											continue goDay;
 | 
			
		||||
										}
 | 
			
		||||
										continue goHour;
 | 
			
		||||
									}
 | 
			
		||||
									continue;
 | 
			
		||||
								}
 | 
			
		||||
								// 循环"秒"数组
 | 
			
		||||
								goSecond: for (let si = sIdx; si <= sDate.length - 1; si++) {
 | 
			
		||||
									let ss = sDate[si] < 10 ? '0' + sDate[si] : sDate[si];
 | 
			
		||||
									// 添加当前时间(时间合法性在日期循环时已经判断)
 | 
			
		||||
									if (MM !== '00' && DD !== '00') {
 | 
			
		||||
										resultArr.push(YY + '-' + MM + '-' + DD + ' ' + hh + ':' + mm + ':' + ss)
 | 
			
		||||
										nums++;
 | 
			
		||||
									}
 | 
			
		||||
									// 如果条数满了就退出循环
 | 
			
		||||
									if (nums === 5) break goYear;
 | 
			
		||||
									// 如果到达最大值时
 | 
			
		||||
									if (si === sDate.length - 1) {
 | 
			
		||||
										resetSecond();
 | 
			
		||||
										if (mi === mDate.length - 1) {
 | 
			
		||||
											resetMin();
 | 
			
		||||
											if (hi === hDate.length - 1) {
 | 
			
		||||
												resetHour();
 | 
			
		||||
												if (Di === DDate.length - 1) {
 | 
			
		||||
													resetDay();
 | 
			
		||||
													if (Mi === MDate.length - 1) {
 | 
			
		||||
														resetMonth();
 | 
			
		||||
														continue goYear;
 | 
			
		||||
													}
 | 
			
		||||
													continue goMonth;
 | 
			
		||||
												}
 | 
			
		||||
												continue goDay;
 | 
			
		||||
											}
 | 
			
		||||
											continue goHour;
 | 
			
		||||
										}
 | 
			
		||||
										continue goMin;
 | 
			
		||||
									}
 | 
			
		||||
								} //goSecond
 | 
			
		||||
							} //goMin
 | 
			
		||||
						}//goHour
 | 
			
		||||
					}//goDay
 | 
			
		||||
				}//goMonth
 | 
			
		||||
			}
 | 
			
		||||
			// 判断100年内的结果条数
 | 
			
		||||
			if (resultArr.length === 0) {
 | 
			
		||||
				this.resultList = ['没有达到条件的结果!'];
 | 
			
		||||
			} else {
 | 
			
		||||
				this.resultList = resultArr;
 | 
			
		||||
				if (resultArr.length !== 5) {
 | 
			
		||||
					this.resultList.push('最近100年内只有上面' + resultArr.length + '条结果!')
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			// 计算完成-显示结果
 | 
			
		||||
			this.isShow = true;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		},
 | 
			
		||||
		// 用于计算某位数字在数组中的索引
 | 
			
		||||
		getIndex(arr, value) {
 | 
			
		||||
			if (value <= arr[0] || value > arr[arr.length - 1]) {
 | 
			
		||||
				return 0;
 | 
			
		||||
			} else {
 | 
			
		||||
				for (let i = 0; i < arr.length - 1; i++) {
 | 
			
		||||
					if (value > arr[i] && value <= arr[i + 1]) {
 | 
			
		||||
						return i + 1;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 获取"年"数组
 | 
			
		||||
		getYearArr(rule, year) {
 | 
			
		||||
			this.dateArr[5] = this.getOrderArr(year, year + 100);
 | 
			
		||||
			if (rule !== undefined) {
 | 
			
		||||
				if (rule.indexOf('-') >= 0) {
 | 
			
		||||
					this.dateArr[5] = this.getCycleArr(rule, year + 100, false)
 | 
			
		||||
				} else if (rule.indexOf('/') >= 0) {
 | 
			
		||||
					this.dateArr[5] = this.getAverageArr(rule, year + 100)
 | 
			
		||||
				} else if (rule !== '*') {
 | 
			
		||||
					this.dateArr[5] = this.getAssignArr(rule)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 获取"月"数组
 | 
			
		||||
		getMonthArr(rule) {
 | 
			
		||||
			this.dateArr[4] = this.getOrderArr(1, 12);
 | 
			
		||||
			if (rule.indexOf('-') >= 0) {
 | 
			
		||||
				this.dateArr[4] = this.getCycleArr(rule, 12, false)
 | 
			
		||||
			} else if (rule.indexOf('/') >= 0) {
 | 
			
		||||
				this.dateArr[4] = this.getAverageArr(rule, 12)
 | 
			
		||||
			} else if (rule !== '*') {
 | 
			
		||||
				this.dateArr[4] = this.getAssignArr(rule)
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 获取"日"数组-主要为日期规则
 | 
			
		||||
		getWeekArr(rule) {
 | 
			
		||||
			// 只有当日期规则的两个值均为“”时则表达日期是有选项的
 | 
			
		||||
			if (this.dayRule === '' && this.dayRuleSup === '') {
 | 
			
		||||
				if (rule.indexOf('-') >= 0) {
 | 
			
		||||
					this.dayRule = 'weekDay';
 | 
			
		||||
					this.dayRuleSup = this.getCycleArr(rule, 7, false)
 | 
			
		||||
				} else if (rule.indexOf('#') >= 0) {
 | 
			
		||||
					this.dayRule = 'assWeek';
 | 
			
		||||
					let matchRule = rule.match(/[0-9]/g);
 | 
			
		||||
					this.dayRuleSup = [Number(matchRule[1]), Number(matchRule[0])];
 | 
			
		||||
					this.dateArr[3] = [1];
 | 
			
		||||
					if (this.dayRuleSup[1] === 7) {
 | 
			
		||||
						this.dayRuleSup[1] = 0;
 | 
			
		||||
					}
 | 
			
		||||
				} else if (rule.indexOf('L') >= 0) {
 | 
			
		||||
					this.dayRule = 'lastWeek';
 | 
			
		||||
					this.dayRuleSup = Number(rule.match(/[0-9]{1,2}/g)[0]);
 | 
			
		||||
					this.dateArr[3] = [31];
 | 
			
		||||
					if (this.dayRuleSup === 7) {
 | 
			
		||||
						this.dayRuleSup = 0;
 | 
			
		||||
					}
 | 
			
		||||
				} else if (rule !== '*' && rule !== '?') {
 | 
			
		||||
					this.dayRule = 'weekDay';
 | 
			
		||||
					this.dayRuleSup = this.getAssignArr(rule)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 获取"日"数组-少量为日期规则
 | 
			
		||||
		getDayArr(rule) {
 | 
			
		||||
			this.dateArr[3] = this.getOrderArr(1, 31);
 | 
			
		||||
			this.dayRule = '';
 | 
			
		||||
			this.dayRuleSup = '';
 | 
			
		||||
			if (rule.indexOf('-') >= 0) {
 | 
			
		||||
				this.dateArr[3] = this.getCycleArr(rule, 31, false)
 | 
			
		||||
				this.dayRuleSup = 'null';
 | 
			
		||||
			} else if (rule.indexOf('/') >= 0) {
 | 
			
		||||
				this.dateArr[3] = this.getAverageArr(rule, 31)
 | 
			
		||||
				this.dayRuleSup = 'null';
 | 
			
		||||
			} else if (rule.indexOf('W') >= 0) {
 | 
			
		||||
				this.dayRule = 'workDay';
 | 
			
		||||
				this.dayRuleSup = Number(rule.match(/[0-9]{1,2}/g)[0]);
 | 
			
		||||
				this.dateArr[3] = [this.dayRuleSup];
 | 
			
		||||
			} else if (rule.indexOf('L') >= 0) {
 | 
			
		||||
				this.dayRule = 'lastDay';
 | 
			
		||||
				this.dayRuleSup = 'null';
 | 
			
		||||
				this.dateArr[3] = [31];
 | 
			
		||||
			} else if (rule !== '*' && rule !== '?') {
 | 
			
		||||
				this.dateArr[3] = this.getAssignArr(rule)
 | 
			
		||||
				this.dayRuleSup = 'null';
 | 
			
		||||
			} else if (rule === '*') {
 | 
			
		||||
				this.dayRuleSup = 'null';
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 获取"时"数组
 | 
			
		||||
		getHourArr(rule) {
 | 
			
		||||
			this.dateArr[2] = this.getOrderArr(0, 23);
 | 
			
		||||
			if (rule.indexOf('-') >= 0) {
 | 
			
		||||
				this.dateArr[2] = this.getCycleArr(rule, 24, true)
 | 
			
		||||
			} else if (rule.indexOf('/') >= 0) {
 | 
			
		||||
				this.dateArr[2] = this.getAverageArr(rule, 23)
 | 
			
		||||
			} else if (rule !== '*') {
 | 
			
		||||
				this.dateArr[2] = this.getAssignArr(rule)
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 获取"分"数组
 | 
			
		||||
		getMinArr(rule) {
 | 
			
		||||
			this.dateArr[1] = this.getOrderArr(0, 59);
 | 
			
		||||
			if (rule.indexOf('-') >= 0) {
 | 
			
		||||
				this.dateArr[1] = this.getCycleArr(rule, 60, true)
 | 
			
		||||
			} else if (rule.indexOf('/') >= 0) {
 | 
			
		||||
				this.dateArr[1] = this.getAverageArr(rule, 59)
 | 
			
		||||
			} else if (rule !== '*') {
 | 
			
		||||
				this.dateArr[1] = this.getAssignArr(rule)
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 获取"秒"数组
 | 
			
		||||
		getSecondArr(rule) {
 | 
			
		||||
			this.dateArr[0] = this.getOrderArr(0, 59);
 | 
			
		||||
			if (rule.indexOf('-') >= 0) {
 | 
			
		||||
				this.dateArr[0] = this.getCycleArr(rule, 60, true)
 | 
			
		||||
			} else if (rule.indexOf('/') >= 0) {
 | 
			
		||||
				this.dateArr[0] = this.getAverageArr(rule, 59)
 | 
			
		||||
			} else if (rule !== '*') {
 | 
			
		||||
				this.dateArr[0] = this.getAssignArr(rule)
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 根据传进来的min-max返回一个顺序的数组
 | 
			
		||||
		getOrderArr(min, max) {
 | 
			
		||||
			let arr = [];
 | 
			
		||||
			for (let i = min; i <= max; i++) {
 | 
			
		||||
				arr.push(i);
 | 
			
		||||
			}
 | 
			
		||||
			return arr;
 | 
			
		||||
		},
 | 
			
		||||
		// 根据规则中指定的零散值返回一个数组
 | 
			
		||||
		getAssignArr(rule) {
 | 
			
		||||
			let arr = [];
 | 
			
		||||
			let assiginArr = rule.split(',');
 | 
			
		||||
			for (let i = 0; i < assiginArr.length; i++) {
 | 
			
		||||
				arr[i] = Number(assiginArr[i])
 | 
			
		||||
			}
 | 
			
		||||
			arr.sort(this.compare)
 | 
			
		||||
			return arr;
 | 
			
		||||
		},
 | 
			
		||||
		// 根据一定算术规则计算返回一个数组
 | 
			
		||||
		getAverageArr(rule, limit) {
 | 
			
		||||
			let arr = [];
 | 
			
		||||
			let agArr = rule.split('/');
 | 
			
		||||
			let min = Number(agArr[0]);
 | 
			
		||||
			let step = Number(agArr[1]);
 | 
			
		||||
			while (min <= limit) {
 | 
			
		||||
				arr.push(min);
 | 
			
		||||
				min += step;
 | 
			
		||||
			}
 | 
			
		||||
			return arr;
 | 
			
		||||
		},
 | 
			
		||||
		// 根据规则返回一个具有周期性的数组
 | 
			
		||||
		getCycleArr(rule, limit, status) {
 | 
			
		||||
			// status--表示是否从0开始(则从1开始)
 | 
			
		||||
			let arr = [];
 | 
			
		||||
			let cycleArr = rule.split('-');
 | 
			
		||||
			let min = Number(cycleArr[0]);
 | 
			
		||||
			let max = Number(cycleArr[1]);
 | 
			
		||||
			if (min > max) {
 | 
			
		||||
				max += limit;
 | 
			
		||||
			}
 | 
			
		||||
			for (let i = min; i <= max; i++) {
 | 
			
		||||
				let add = 0;
 | 
			
		||||
				if (status === false && i % limit === 0) {
 | 
			
		||||
					add = limit;
 | 
			
		||||
				}
 | 
			
		||||
				arr.push(Math.round(i % limit + add))
 | 
			
		||||
			}
 | 
			
		||||
			arr.sort(this.compare)
 | 
			
		||||
			return arr;
 | 
			
		||||
		},
 | 
			
		||||
		// 比较数字大小(用于Array.sort)
 | 
			
		||||
		compare(value1, value2) {
 | 
			
		||||
			if (value2 - value1 > 0) {
 | 
			
		||||
				return -1;
 | 
			
		||||
			} else {
 | 
			
		||||
				return 1;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 格式化日期格式如:2017-9-19 18:04:33
 | 
			
		||||
		formatDate(value, type) {
 | 
			
		||||
			// 计算日期相关值
 | 
			
		||||
			let time = typeof value == 'number' ? new Date(value) : value;
 | 
			
		||||
			let Y = time.getFullYear();
 | 
			
		||||
			let M = time.getMonth() + 1;
 | 
			
		||||
			let D = time.getDate();
 | 
			
		||||
			let h = time.getHours();
 | 
			
		||||
			let m = time.getMinutes();
 | 
			
		||||
			let s = time.getSeconds();
 | 
			
		||||
			let week = time.getDay();
 | 
			
		||||
			// 如果传递了type的话
 | 
			
		||||
			if (type === undefined) {
 | 
			
		||||
				return Y + '-' + (M < 10 ? '0' + M : M) + '-' + (D < 10 ? '0' + D : D) + ' ' + (h < 10 ? '0' + h : h) + ':' + (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s);
 | 
			
		||||
			} else if (type === 'week') {
 | 
			
		||||
				// 在quartz中 1为星期日
 | 
			
		||||
				return week + 1;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 检查日期是否存在
 | 
			
		||||
		checkDate(value) {
 | 
			
		||||
			let time = new Date(value);
 | 
			
		||||
			let format = this.formatDate(time)
 | 
			
		||||
			return value === format;
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	watch: {
 | 
			
		||||
		'ex': 'expressionChange'
 | 
			
		||||
	},
 | 
			
		||||
	props: ['ex'],
 | 
			
		||||
	mounted: function () {
 | 
			
		||||
		// 初始化 获取一次结果
 | 
			
		||||
		this.expressionChange();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										117
									
								
								src/components/Crontab/second.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								src/components/Crontab/second.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,117 @@
 | 
			
		||||
<template>
 | 
			
		||||
	<el-form size="small">
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="1">
 | 
			
		||||
				秒,允许的通配符[, - * /]
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="2">
 | 
			
		||||
				周期从
 | 
			
		||||
				<el-input-number v-model='cycle01' :min="0" :max="58" /> -
 | 
			
		||||
				<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="59" /> 秒
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="3">
 | 
			
		||||
				从
 | 
			
		||||
				<el-input-number v-model='average01' :min="0" :max="58" /> 秒开始,每
 | 
			
		||||
				<el-input-number v-model='average02' :min="1" :max="59 - average01 || 0" /> 秒执行一次
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="4">
 | 
			
		||||
				指定
 | 
			
		||||
				<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
 | 
			
		||||
					<el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option>
 | 
			
		||||
				</el-select>
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
	</el-form>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			radioValue: 1,
 | 
			
		||||
			cycle01: 1,
 | 
			
		||||
			cycle02: 2,
 | 
			
		||||
			average01: 0,
 | 
			
		||||
			average02: 1,
 | 
			
		||||
			checkboxList: [],
 | 
			
		||||
			checkNum: this.$options.propsData.check
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	name: 'crontab-second',
 | 
			
		||||
	props: ['check', 'radioParent'],
 | 
			
		||||
	methods: {
 | 
			
		||||
		// 单选按钮值变化时
 | 
			
		||||
		radioChange() {
 | 
			
		||||
			switch (this.radioValue) {
 | 
			
		||||
				case 1:
 | 
			
		||||
					this.$emit('update', 'second', '*', 'second');
 | 
			
		||||
					break;
 | 
			
		||||
				case 2:
 | 
			
		||||
					this.$emit('update', 'second', this.cycleTotal);
 | 
			
		||||
					break;
 | 
			
		||||
				case 3:
 | 
			
		||||
					this.$emit('update', 'second', this.averageTotal);
 | 
			
		||||
					break;
 | 
			
		||||
				case 4:
 | 
			
		||||
					this.$emit('update', 'second', this.checkboxString);
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 周期两个值变化时
 | 
			
		||||
		cycleChange() {
 | 
			
		||||
			if (this.radioValue === '2') {
 | 
			
		||||
				this.$emit('update', 'second', this.cycleTotal);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 平均两个值变化时
 | 
			
		||||
		averageChange() {
 | 
			
		||||
			if (this.radioValue === '3') {
 | 
			
		||||
				this.$emit('update', 'second', this.averageTotal);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// checkbox值变化时
 | 
			
		||||
		checkboxChange() {
 | 
			
		||||
			if (this.radioValue === '4') {
 | 
			
		||||
				this.$emit('update', 'second', this.checkboxString);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	watch: {
 | 
			
		||||
		'radioValue': 'radioChange',
 | 
			
		||||
		'cycleTotal': 'cycleChange',
 | 
			
		||||
		'averageTotal': 'averageChange',
 | 
			
		||||
		'checkboxString': 'checkboxChange',
 | 
			
		||||
		radioParent() {
 | 
			
		||||
			this.radioValue = this.radioParent
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	computed: {
 | 
			
		||||
		// 计算两个周期值
 | 
			
		||||
		cycleTotal: function () {
 | 
			
		||||
			const cycle01 = this.checkNum(this.cycle01, 0, 58)
 | 
			
		||||
			const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 59)
 | 
			
		||||
			return cycle01 + '-' + cycle02;
 | 
			
		||||
		},
 | 
			
		||||
		// 计算平均用到的值
 | 
			
		||||
		averageTotal: function () {
 | 
			
		||||
			const average01 = this.checkNum(this.average01, 0, 58)
 | 
			
		||||
			const average02 = this.checkNum(this.average02, 1, 59 - average01 || 0)
 | 
			
		||||
			return average01 + '/' + average02;
 | 
			
		||||
		},
 | 
			
		||||
		// 计算勾选的checkbox值合集
 | 
			
		||||
		checkboxString: function () {
 | 
			
		||||
			let str = this.checkboxList.join();
 | 
			
		||||
			return str === '' ? '*' : str;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										202
									
								
								src/components/Crontab/week.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								src/components/Crontab/week.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,202 @@
 | 
			
		||||
<template>
 | 
			
		||||
	<el-form size='small'>
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="1">
 | 
			
		||||
				周,允许的通配符[, - * ? / L #]
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="2">
 | 
			
		||||
				不指定
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="3">
 | 
			
		||||
				周期从星期
 | 
			
		||||
				<el-select clearable v-model="cycle01">
 | 
			
		||||
					<el-option
 | 
			
		||||
						v-for="(item,index) of weekList"
 | 
			
		||||
						:key="index"
 | 
			
		||||
						:label="item.value"
 | 
			
		||||
						:value="item.key"
 | 
			
		||||
						:disabled="item.key === 1"
 | 
			
		||||
					>{{item.value}}</el-option>
 | 
			
		||||
				</el-select>
 | 
			
		||||
				-
 | 
			
		||||
				<el-select clearable v-model="cycle02">
 | 
			
		||||
					<el-option
 | 
			
		||||
						v-for="(item,index) of weekList"
 | 
			
		||||
						:key="index"
 | 
			
		||||
						:label="item.value"
 | 
			
		||||
						:value="item.key"
 | 
			
		||||
						:disabled="item.key < cycle01 && item.key !== 1"
 | 
			
		||||
					>{{item.value}}</el-option>
 | 
			
		||||
				</el-select>
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="4">
 | 
			
		||||
				第
 | 
			
		||||
				<el-input-number v-model='average01' :min="1" :max="4" /> 周的星期
 | 
			
		||||
				<el-select clearable v-model="average02">
 | 
			
		||||
					<el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="item.key">{{item.value}}</el-option>
 | 
			
		||||
				</el-select>
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="5">
 | 
			
		||||
				本月最后一个星期
 | 
			
		||||
				<el-select clearable v-model="weekday">
 | 
			
		||||
					<el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="item.key">{{item.value}}</el-option>
 | 
			
		||||
				</el-select>
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio v-model='radioValue' :label="6">
 | 
			
		||||
				指定
 | 
			
		||||
				<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
 | 
			
		||||
					<el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="String(item.key)">{{item.value}}</el-option>
 | 
			
		||||
				</el-select>
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
	</el-form>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			radioValue: 2,
 | 
			
		||||
			weekday: 2,
 | 
			
		||||
			cycle01: 2,
 | 
			
		||||
			cycle02: 3,
 | 
			
		||||
			average01: 1,
 | 
			
		||||
			average02: 2,
 | 
			
		||||
			checkboxList: [],
 | 
			
		||||
			weekList: [
 | 
			
		||||
				{
 | 
			
		||||
					key: 2,
 | 
			
		||||
					value: '星期一'
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					key: 3,
 | 
			
		||||
					value: '星期二'
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					key: 4,
 | 
			
		||||
					value: '星期三'
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					key: 5,
 | 
			
		||||
					value: '星期四'
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					key: 6,
 | 
			
		||||
					value: '星期五'
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					key: 7,
 | 
			
		||||
					value: '星期六'
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					key: 1,
 | 
			
		||||
					value: '星期日'
 | 
			
		||||
				}
 | 
			
		||||
			],
 | 
			
		||||
			checkNum: this.$options.propsData.check
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	name: 'crontab-week',
 | 
			
		||||
	props: ['check', 'cron'],
 | 
			
		||||
	methods: {
 | 
			
		||||
		// 单选按钮值变化时
 | 
			
		||||
		radioChange() {
 | 
			
		||||
			if (this.radioValue !== 2 && this.cron.day !== '?') {
 | 
			
		||||
				this.$emit('update', 'day', '?', 'week');
 | 
			
		||||
			}
 | 
			
		||||
			switch (this.radioValue) {
 | 
			
		||||
				case 1:
 | 
			
		||||
					this.$emit('update', 'week', '*');
 | 
			
		||||
					break;
 | 
			
		||||
				case 2:
 | 
			
		||||
					this.$emit('update', 'week', '?');
 | 
			
		||||
					break;
 | 
			
		||||
				case 3:
 | 
			
		||||
					this.$emit('update', 'week', this.cycleTotal);
 | 
			
		||||
					break;
 | 
			
		||||
				case 4:
 | 
			
		||||
					this.$emit('update', 'week', this.averageTotal);
 | 
			
		||||
					break;
 | 
			
		||||
				case 5:
 | 
			
		||||
					this.$emit('update', 'week', this.weekdayCheck + 'L');
 | 
			
		||||
					break;
 | 
			
		||||
				case 6:
 | 
			
		||||
					this.$emit('update', 'week', this.checkboxString);
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		// 周期两个值变化时
 | 
			
		||||
		cycleChange() {
 | 
			
		||||
			if (this.radioValue === '3') {
 | 
			
		||||
				this.$emit('update', 'week', this.cycleTotal);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 平均两个值变化时
 | 
			
		||||
		averageChange() {
 | 
			
		||||
			if (this.radioValue === '4') {
 | 
			
		||||
				this.$emit('update', 'week', this.averageTotal);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 最近工作日值变化时
 | 
			
		||||
		weekdayChange() {
 | 
			
		||||
			if (this.radioValue === '5') {
 | 
			
		||||
				this.$emit('update', 'week', this.weekday + 'L');
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// checkbox值变化时
 | 
			
		||||
		checkboxChange() {
 | 
			
		||||
			if (this.radioValue === '6') {
 | 
			
		||||
				this.$emit('update', 'week', this.checkboxString);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	watch: {
 | 
			
		||||
		'radioValue': 'radioChange',
 | 
			
		||||
		'cycleTotal': 'cycleChange',
 | 
			
		||||
		'averageTotal': 'averageChange',
 | 
			
		||||
		'weekdayCheck': 'weekdayChange',
 | 
			
		||||
		'checkboxString': 'checkboxChange',
 | 
			
		||||
	},
 | 
			
		||||
	computed: {
 | 
			
		||||
		// 计算两个周期值
 | 
			
		||||
		cycleTotal: function () {
 | 
			
		||||
			this.cycle01 = this.checkNum(this.cycle01, 1, 7)
 | 
			
		||||
			this.cycle02 = this.checkNum(this.cycle02, 1, 7)
 | 
			
		||||
			return this.cycle01 + '-' + this.cycle02;
 | 
			
		||||
		},
 | 
			
		||||
		// 计算平均用到的值
 | 
			
		||||
		averageTotal: function () {
 | 
			
		||||
			this.average01 = this.checkNum(this.average01, 1, 4)
 | 
			
		||||
			this.average02 = this.checkNum(this.average02, 1, 7)
 | 
			
		||||
			return this.average02 + '#' + this.average01;
 | 
			
		||||
		},
 | 
			
		||||
		// 最近的工作日(格式)
 | 
			
		||||
		weekdayCheck: function () {
 | 
			
		||||
			this.weekday = this.checkNum(this.weekday, 1, 7)
 | 
			
		||||
			return this.weekday;
 | 
			
		||||
		},
 | 
			
		||||
		// 计算勾选的checkbox值合集
 | 
			
		||||
		checkboxString: function () {
 | 
			
		||||
			let str = this.checkboxList.join();
 | 
			
		||||
			return str === '' ? '*' : str;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										131
									
								
								src/components/Crontab/year.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								src/components/Crontab/year.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,131 @@
 | 
			
		||||
<template>
 | 
			
		||||
	<el-form size="small">
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio :label="1" v-model='radioValue'>
 | 
			
		||||
				不填,允许的通配符[, - * /]
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio :label="2" v-model='radioValue'>
 | 
			
		||||
				每年
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio :label="3" v-model='radioValue'>
 | 
			
		||||
				周期从
 | 
			
		||||
				<el-input-number v-model='cycle01' :min='fullYear' :max="2098" /> -
 | 
			
		||||
				<el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : fullYear + 1" :max="2099" />
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio :label="4" v-model='radioValue'>
 | 
			
		||||
				从
 | 
			
		||||
				<el-input-number v-model='average01' :min='fullYear' :max="2098"/> 年开始,每
 | 
			
		||||
				<el-input-number v-model='average02' :min="1" :max="2099 - average01 || fullYear" /> 年执行一次
 | 
			
		||||
			</el-radio>
 | 
			
		||||
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
 | 
			
		||||
		<el-form-item>
 | 
			
		||||
			<el-radio :label="5" v-model='radioValue'>
 | 
			
		||||
				指定
 | 
			
		||||
				<el-select clearable v-model="checkboxList" placeholder="可多选" multiple>
 | 
			
		||||
					<el-option v-for="item in 9" :key="item" :value="item - 1 + fullYear" :label="item -1 + fullYear" />
 | 
			
		||||
				</el-select>
 | 
			
		||||
			</el-radio>
 | 
			
		||||
		</el-form-item>
 | 
			
		||||
	</el-form>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
export default {
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			fullYear: 0,
 | 
			
		||||
			radioValue: 1,
 | 
			
		||||
			cycle01: 0,
 | 
			
		||||
			cycle02: 0,
 | 
			
		||||
			average01: 0,
 | 
			
		||||
			average02: 1,
 | 
			
		||||
			checkboxList: [],
 | 
			
		||||
			checkNum: this.$options.propsData.check
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	name: 'crontab-year',
 | 
			
		||||
	props: ['check', 'month', 'cron'],
 | 
			
		||||
	methods: {
 | 
			
		||||
		// 单选按钮值变化时
 | 
			
		||||
		radioChange() {
 | 
			
		||||
			switch (this.radioValue) {
 | 
			
		||||
				case 1:
 | 
			
		||||
					this.$emit('update', 'year', '');
 | 
			
		||||
					break;
 | 
			
		||||
				case 2:
 | 
			
		||||
					this.$emit('update', 'year', '*');
 | 
			
		||||
					break;
 | 
			
		||||
				case 3:
 | 
			
		||||
					this.$emit('update', 'year', this.cycleTotal);
 | 
			
		||||
					break;
 | 
			
		||||
				case 4:
 | 
			
		||||
					this.$emit('update', 'year', this.averageTotal);
 | 
			
		||||
					break;
 | 
			
		||||
				case 5:
 | 
			
		||||
					this.$emit('update', 'year', this.checkboxString);
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 周期两个值变化时
 | 
			
		||||
		cycleChange() {
 | 
			
		||||
			if (this.radioValue === '3') {
 | 
			
		||||
				this.$emit('update', 'year', this.cycleTotal);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// 平均两个值变化时
 | 
			
		||||
		averageChange() {
 | 
			
		||||
			if (this.radioValue === '4') {
 | 
			
		||||
				this.$emit('update', 'year', this.averageTotal);
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		// checkbox值变化时
 | 
			
		||||
		checkboxChange() {
 | 
			
		||||
			if (this.radioValue === '5') {
 | 
			
		||||
				this.$emit('update', 'year', this.checkboxString);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	watch: {
 | 
			
		||||
		'radioValue': 'radioChange',
 | 
			
		||||
		'cycleTotal': 'cycleChange',
 | 
			
		||||
		'averageTotal': 'averageChange',
 | 
			
		||||
		'checkboxString': 'checkboxChange'
 | 
			
		||||
	},
 | 
			
		||||
	computed: {
 | 
			
		||||
		// 计算两个周期值
 | 
			
		||||
		cycleTotal: function () {
 | 
			
		||||
			const cycle01 = this.checkNum(this.cycle01, this.fullYear, 2098)
 | 
			
		||||
			const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : this.fullYear + 1, 2099)
 | 
			
		||||
			return cycle01 + '-' + cycle02;
 | 
			
		||||
		},
 | 
			
		||||
		// 计算平均用到的值
 | 
			
		||||
		averageTotal: function () {
 | 
			
		||||
			const average01 = this.checkNum(this.average01, this.fullYear, 2098)
 | 
			
		||||
			const average02 = this.checkNum(this.average02, 1, 2099 - average01 || this.fullYear)
 | 
			
		||||
			return average01 + '/' + average02;
 | 
			
		||||
		},
 | 
			
		||||
		// 计算勾选的checkbox值合集
 | 
			
		||||
		checkboxString: function () {
 | 
			
		||||
			let str = this.checkboxList.join();
 | 
			
		||||
			return str;
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	mounted: function () {
 | 
			
		||||
		// 仅获取当前年份
 | 
			
		||||
		this.fullYear = Number(new Date().getFullYear());
 | 
			
		||||
		this.cycle01 = this.fullYear
 | 
			
		||||
		this.average01 = this.fullYear
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
		:label-width="`${labelWidth}px`"
 | 
			
		||||
		:size="size"
 | 
			
		||||
		:label-position="labelPosition"
 | 
			
		||||
		v-loading="formLoading">
 | 
			
		||||
		v-loading="0 && formLoading">
 | 
			
		||||
		<el-row :gutter="20" v-for="(row, rindex) in rows" :key="rindex">
 | 
			
		||||
			<el-col v-for="col in row" :key="col.label" :span="24 / row.length">
 | 
			
		||||
				<el-form-item :label="col.label" :prop="col.prop" :rules="col.rules">
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										630
									
								
								src/components/generator/config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										630
									
								
								src/components/generator/config.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,630 @@
 | 
			
		||||
// 表单属性【右面板】
 | 
			
		||||
export const formConf = {
 | 
			
		||||
  formRef: 'elForm',
 | 
			
		||||
  formModel: 'formData',
 | 
			
		||||
  size: 'medium',
 | 
			
		||||
  labelPosition: 'right',
 | 
			
		||||
  labelWidth: 100,
 | 
			
		||||
  formRules: 'rules',
 | 
			
		||||
  gutter: 15,
 | 
			
		||||
  disabled: false,
 | 
			
		||||
  span: 24,
 | 
			
		||||
  formBtns: true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 输入型组件 【左面板】
 | 
			
		||||
export const inputComponents = [
 | 
			
		||||
  {
 | 
			
		||||
    // 组件的自定义配置
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '单行文本',
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      tag: 'el-input',
 | 
			
		||||
      tagIcon: 'input',
 | 
			
		||||
      defaultValue: undefined,
 | 
			
		||||
      required: true,
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      span: 24,
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/input',
 | 
			
		||||
      // 正则校验规则
 | 
			
		||||
      regList: []
 | 
			
		||||
    },
 | 
			
		||||
    // 组件的插槽属性
 | 
			
		||||
    __slot__: {
 | 
			
		||||
      prepend: '',
 | 
			
		||||
      append: ''
 | 
			
		||||
    },
 | 
			
		||||
    // 其余的为可直接写在组件标签上的属性
 | 
			
		||||
    placeholder: '请输入',
 | 
			
		||||
    style: { width: '100%' },
 | 
			
		||||
    clearable: true,
 | 
			
		||||
    'prefix-icon': '',
 | 
			
		||||
    'suffix-icon': '',
 | 
			
		||||
    maxlength: null,
 | 
			
		||||
    'show-word-limit': false,
 | 
			
		||||
    readonly: false,
 | 
			
		||||
    disabled: false
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '多行文本',
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      tag: 'el-input',
 | 
			
		||||
      tagIcon: 'textarea',
 | 
			
		||||
      defaultValue: undefined,
 | 
			
		||||
      required: true,
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      span: 24,
 | 
			
		||||
      regList: [],
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/input'
 | 
			
		||||
    },
 | 
			
		||||
    type: 'textarea',
 | 
			
		||||
    placeholder: '请输入',
 | 
			
		||||
    autosize: {
 | 
			
		||||
      minRows: 4,
 | 
			
		||||
      maxRows: 4
 | 
			
		||||
    },
 | 
			
		||||
    style: { width: '100%' },
 | 
			
		||||
    maxlength: null,
 | 
			
		||||
    'show-word-limit': false,
 | 
			
		||||
    readonly: false,
 | 
			
		||||
    disabled: false
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '密码',
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      tag: 'el-input',
 | 
			
		||||
      tagIcon: 'password',
 | 
			
		||||
      defaultValue: undefined,
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      span: 24,
 | 
			
		||||
      required: true,
 | 
			
		||||
      regList: [],
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/input'
 | 
			
		||||
    },
 | 
			
		||||
    __slot__: {
 | 
			
		||||
      prepend: '',
 | 
			
		||||
      append: ''
 | 
			
		||||
    },
 | 
			
		||||
    placeholder: '请输入',
 | 
			
		||||
    'show-password': true,
 | 
			
		||||
    style: { width: '100%' },
 | 
			
		||||
    clearable: true,
 | 
			
		||||
    'prefix-icon': '',
 | 
			
		||||
    'suffix-icon': '',
 | 
			
		||||
    maxlength: null,
 | 
			
		||||
    'show-word-limit': false,
 | 
			
		||||
    readonly: false,
 | 
			
		||||
    disabled: false
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '计数器',
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      tag: 'el-input-number',
 | 
			
		||||
      tagIcon: 'number',
 | 
			
		||||
      defaultValue: undefined,
 | 
			
		||||
      span: 24,
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      required: true,
 | 
			
		||||
      regList: [],
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/input-number'
 | 
			
		||||
    },
 | 
			
		||||
    placeholder: '',
 | 
			
		||||
    min: undefined,
 | 
			
		||||
    max: undefined,
 | 
			
		||||
    step: 1,
 | 
			
		||||
    'step-strictly': false,
 | 
			
		||||
    precision: undefined,
 | 
			
		||||
    'controls-position': '',
 | 
			
		||||
    disabled: false
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '编辑器',
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      tag: 'tinymce',
 | 
			
		||||
      tagIcon: 'rich-text',
 | 
			
		||||
      defaultValue: null,
 | 
			
		||||
      span: 24,
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      required: true,
 | 
			
		||||
      regList: [],
 | 
			
		||||
      document: 'http://tinymce.ax-z.cn'
 | 
			
		||||
    },
 | 
			
		||||
    placeholder: '请输入',
 | 
			
		||||
    height: 300, // 编辑器高度
 | 
			
		||||
    branding: false // 隐藏右下角品牌烙印
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
// 选择型组件 【左面板】
 | 
			
		||||
export const selectComponents = [
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '下拉选择',
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      tag: 'el-select',
 | 
			
		||||
      tagIcon: 'select',
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      span: 24,
 | 
			
		||||
      required: true,
 | 
			
		||||
      regList: [],
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/select'
 | 
			
		||||
    },
 | 
			
		||||
    __slot__: {
 | 
			
		||||
      options: [{
 | 
			
		||||
        label: '选项一',
 | 
			
		||||
        value: 1
 | 
			
		||||
      }, {
 | 
			
		||||
        label: '选项二',
 | 
			
		||||
        value: 2
 | 
			
		||||
      }]
 | 
			
		||||
    },
 | 
			
		||||
    placeholder: '请选择',
 | 
			
		||||
    style: { width: '100%' },
 | 
			
		||||
    clearable: true,
 | 
			
		||||
    disabled: false,
 | 
			
		||||
    filterable: false,
 | 
			
		||||
    multiple: false
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '级联选择',
 | 
			
		||||
      url: 'https://www.fastmock.site/mock/f8d7a54fb1e60561e2f720d5a810009d/fg/cascaderList',
 | 
			
		||||
      method: 'get',
 | 
			
		||||
      dataPath: 'list',
 | 
			
		||||
      dataConsumer: 'options',
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      tag: 'el-cascader',
 | 
			
		||||
      tagIcon: 'cascader',
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      defaultValue: [],
 | 
			
		||||
      dataType: 'dynamic',
 | 
			
		||||
      span: 24,
 | 
			
		||||
      required: true,
 | 
			
		||||
      regList: [],
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/cascader'
 | 
			
		||||
    },
 | 
			
		||||
    options: [{
 | 
			
		||||
      id: 1,
 | 
			
		||||
      value: 1,
 | 
			
		||||
      label: '选项1',
 | 
			
		||||
      children: [{
 | 
			
		||||
        id: 2,
 | 
			
		||||
        value: 2,
 | 
			
		||||
        label: '选项1-1'
 | 
			
		||||
      }]
 | 
			
		||||
    }],
 | 
			
		||||
    placeholder: '请选择',
 | 
			
		||||
    style: { width: '100%' },
 | 
			
		||||
    props: {
 | 
			
		||||
      props: {
 | 
			
		||||
        multiple: false,
 | 
			
		||||
        label: 'label',
 | 
			
		||||
        value: 'value',
 | 
			
		||||
        children: 'children'
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    'show-all-levels': true,
 | 
			
		||||
    disabled: false,
 | 
			
		||||
    clearable: true,
 | 
			
		||||
    filterable: false,
 | 
			
		||||
    separator: '/'
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '单选框组',
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      tag: 'el-radio-group',
 | 
			
		||||
      tagIcon: 'radio',
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      defaultValue: undefined,
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      span: 24,
 | 
			
		||||
      optionType: 'default',
 | 
			
		||||
      regList: [],
 | 
			
		||||
      required: true,
 | 
			
		||||
      border: false,
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/radio'
 | 
			
		||||
    },
 | 
			
		||||
    __slot__: {
 | 
			
		||||
      options: [{
 | 
			
		||||
        label: '选项一',
 | 
			
		||||
        value: 1
 | 
			
		||||
      }, {
 | 
			
		||||
        label: '选项二',
 | 
			
		||||
        value: 2
 | 
			
		||||
      }]
 | 
			
		||||
    },
 | 
			
		||||
    style: {},
 | 
			
		||||
    size: 'medium',
 | 
			
		||||
    disabled: false
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '多选框组',
 | 
			
		||||
      tag: 'el-checkbox-group',
 | 
			
		||||
      tagIcon: 'checkbox',
 | 
			
		||||
      defaultValue: [],
 | 
			
		||||
      span: 24,
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      optionType: 'default',
 | 
			
		||||
      required: true,
 | 
			
		||||
      regList: [],
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      border: false,
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/checkbox'
 | 
			
		||||
    },
 | 
			
		||||
    __slot__: {
 | 
			
		||||
      options: [{
 | 
			
		||||
        label: '选项一',
 | 
			
		||||
        value: 1
 | 
			
		||||
      }, {
 | 
			
		||||
        label: '选项二',
 | 
			
		||||
        value: 2
 | 
			
		||||
      }]
 | 
			
		||||
    },
 | 
			
		||||
    style: {},
 | 
			
		||||
    size: 'medium',
 | 
			
		||||
    min: null,
 | 
			
		||||
    max: null,
 | 
			
		||||
    disabled: false
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '开关',
 | 
			
		||||
      tag: 'el-switch',
 | 
			
		||||
      tagIcon: 'switch',
 | 
			
		||||
      defaultValue: false,
 | 
			
		||||
      span: 24,
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      required: true,
 | 
			
		||||
      regList: [],
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/switch'
 | 
			
		||||
    },
 | 
			
		||||
    style: {},
 | 
			
		||||
    disabled: false,
 | 
			
		||||
    'active-text': '',
 | 
			
		||||
    'inactive-text': '',
 | 
			
		||||
    'active-color': null,
 | 
			
		||||
    'inactive-color': null,
 | 
			
		||||
    'active-value': true,
 | 
			
		||||
    'inactive-value': false
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '滑块',
 | 
			
		||||
      tag: 'el-slider',
 | 
			
		||||
      tagIcon: 'slider',
 | 
			
		||||
      defaultValue: null,
 | 
			
		||||
      span: 24,
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      required: true,
 | 
			
		||||
      regList: [],
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/slider'
 | 
			
		||||
    },
 | 
			
		||||
    disabled: false,
 | 
			
		||||
    min: 0,
 | 
			
		||||
    max: 100,
 | 
			
		||||
    step: 1,
 | 
			
		||||
    'show-stops': false,
 | 
			
		||||
    range: false
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '时间选择',
 | 
			
		||||
      tag: 'el-time-picker',
 | 
			
		||||
      tagIcon: 'time',
 | 
			
		||||
      defaultValue: null,
 | 
			
		||||
      span: 24,
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      required: true,
 | 
			
		||||
      regList: [],
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/time-picker'
 | 
			
		||||
    },
 | 
			
		||||
    placeholder: '请选择',
 | 
			
		||||
    style: { width: '100%' },
 | 
			
		||||
    disabled: false,
 | 
			
		||||
    clearable: true,
 | 
			
		||||
    'picker-options': {
 | 
			
		||||
      selectableRange: '00:00:00-23:59:59'
 | 
			
		||||
    },
 | 
			
		||||
    format: 'HH:mm:ss',
 | 
			
		||||
    'value-format': 'HH:mm:ss'
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '时间范围',
 | 
			
		||||
      tag: 'el-time-picker',
 | 
			
		||||
      tagIcon: 'time-range',
 | 
			
		||||
      span: 24,
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      defaultValue: null,
 | 
			
		||||
      required: true,
 | 
			
		||||
      regList: [],
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/time-picker'
 | 
			
		||||
    },
 | 
			
		||||
    style: { width: '100%' },
 | 
			
		||||
    disabled: false,
 | 
			
		||||
    clearable: true,
 | 
			
		||||
    'is-range': true,
 | 
			
		||||
    'range-separator': '至',
 | 
			
		||||
    'start-placeholder': '开始时间',
 | 
			
		||||
    'end-placeholder': '结束时间',
 | 
			
		||||
    format: 'HH:mm:ss',
 | 
			
		||||
    'value-format': 'HH:mm:ss'
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '日期选择',
 | 
			
		||||
      tag: 'el-date-picker',
 | 
			
		||||
      tagIcon: 'date',
 | 
			
		||||
      defaultValue: null,
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      span: 24,
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      required: true,
 | 
			
		||||
      regList: [],
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/date-picker'
 | 
			
		||||
    },
 | 
			
		||||
    placeholder: '请选择',
 | 
			
		||||
    type: 'date',
 | 
			
		||||
    style: { width: '100%' },
 | 
			
		||||
    disabled: false,
 | 
			
		||||
    clearable: true,
 | 
			
		||||
    format: 'yyyy-MM-dd',
 | 
			
		||||
    'value-format': 'yyyy-MM-dd',
 | 
			
		||||
    readonly: false
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '日期范围',
 | 
			
		||||
      tag: 'el-date-picker',
 | 
			
		||||
      tagIcon: 'date-range',
 | 
			
		||||
      defaultValue: null,
 | 
			
		||||
      span: 24,
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      required: true,
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      regList: [],
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/date-picker'
 | 
			
		||||
    },
 | 
			
		||||
    style: { width: '100%' },
 | 
			
		||||
    type: 'daterange',
 | 
			
		||||
    'range-separator': '至',
 | 
			
		||||
    'start-placeholder': '开始日期',
 | 
			
		||||
    'end-placeholder': '结束日期',
 | 
			
		||||
    disabled: false,
 | 
			
		||||
    clearable: true,
 | 
			
		||||
    format: 'yyyy-MM-dd',
 | 
			
		||||
    'value-format': 'yyyy-MM-dd',
 | 
			
		||||
    readonly: false
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '评分',
 | 
			
		||||
      tag: 'el-rate',
 | 
			
		||||
      tagIcon: 'rate',
 | 
			
		||||
      defaultValue: 0,
 | 
			
		||||
      span: 24,
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      required: true,
 | 
			
		||||
      regList: [],
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/rate'
 | 
			
		||||
    },
 | 
			
		||||
    style: {},
 | 
			
		||||
    max: 5,
 | 
			
		||||
    'allow-half': false,
 | 
			
		||||
    'show-text': false,
 | 
			
		||||
    'show-score': false,
 | 
			
		||||
    disabled: false
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '颜色选择',
 | 
			
		||||
      tag: 'el-color-picker',
 | 
			
		||||
      tagIcon: 'color',
 | 
			
		||||
      span: 24,
 | 
			
		||||
      defaultValue: null,
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      required: true,
 | 
			
		||||
      regList: [],
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/color-picker'
 | 
			
		||||
    },
 | 
			
		||||
    'show-alpha': false,
 | 
			
		||||
    'color-format': '',
 | 
			
		||||
    disabled: false,
 | 
			
		||||
    size: 'medium'
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '上传',
 | 
			
		||||
      tag: 'el-upload',
 | 
			
		||||
      tagIcon: 'upload',
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      defaultValue: null,
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      required: true,
 | 
			
		||||
      span: 24,
 | 
			
		||||
      showTip: false,
 | 
			
		||||
      buttonText: '点击上传',
 | 
			
		||||
      regList: [],
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      fileSize: 2,
 | 
			
		||||
      sizeUnit: 'MB',
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/upload'
 | 
			
		||||
    },
 | 
			
		||||
    __slot__: {
 | 
			
		||||
      'list-type': true
 | 
			
		||||
    },
 | 
			
		||||
    // action: process.env.VUE_APP_BASE_API + "/admin-api/infra/file/upload", // 请求地址
 | 
			
		||||
    action: '/infra/file/upload', // 请求地址
 | 
			
		||||
    disabled: false,
 | 
			
		||||
    accept: '',
 | 
			
		||||
    name: 'file',
 | 
			
		||||
    'auto-upload': true,
 | 
			
		||||
    'list-type': 'text',
 | 
			
		||||
    multiple: false
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
// 布局型组件 【左面板】
 | 
			
		||||
export const layoutComponents = [
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      layout: 'rowFormItem',
 | 
			
		||||
      tagIcon: 'row',
 | 
			
		||||
      label: '行容器',
 | 
			
		||||
      layoutTree: true,
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/layout#row-attributes'
 | 
			
		||||
    },
 | 
			
		||||
    type: 'default',
 | 
			
		||||
    justify: 'start',
 | 
			
		||||
    align: 'top'
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '按钮',
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      tag: 'el-button',
 | 
			
		||||
      tagIcon: 'button',
 | 
			
		||||
      span: 24,
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/button'
 | 
			
		||||
    },
 | 
			
		||||
    __slot__: {
 | 
			
		||||
      default: '主要按钮'
 | 
			
		||||
    },
 | 
			
		||||
    type: 'primary',
 | 
			
		||||
    icon: 'el-icon-search',
 | 
			
		||||
    round: false,
 | 
			
		||||
    size: 'medium',
 | 
			
		||||
    plain: false,
 | 
			
		||||
    circle: false,
 | 
			
		||||
    disabled: false
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      tagIcon: 'table',
 | 
			
		||||
      tag: 'el-table',
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/table',
 | 
			
		||||
      span: 24,
 | 
			
		||||
      formId: 101,
 | 
			
		||||
      renderKey: 1595761764203,
 | 
			
		||||
      componentName: 'row101',
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      label: '表格[开发中]',
 | 
			
		||||
      dataType: 'dynamic',
 | 
			
		||||
      method: 'get',
 | 
			
		||||
      dataPath: 'list',
 | 
			
		||||
      dataConsumer: 'data',
 | 
			
		||||
      url: 'https://www.fastmock.site/mock/f8d7a54fb1e60561e2f720d5a810009d/fg/tableData',
 | 
			
		||||
      children: [{
 | 
			
		||||
        __config__: {
 | 
			
		||||
          layout: 'raw',
 | 
			
		||||
          tag: 'el-table-column',
 | 
			
		||||
          renderKey: 15957617660153
 | 
			
		||||
        },
 | 
			
		||||
        prop: 'date',
 | 
			
		||||
        label: '日期'
 | 
			
		||||
      }, {
 | 
			
		||||
        __config__: {
 | 
			
		||||
          layout: 'raw',
 | 
			
		||||
          tag: 'el-table-column',
 | 
			
		||||
          renderKey: 15957617660152
 | 
			
		||||
        },
 | 
			
		||||
        prop: 'address',
 | 
			
		||||
        label: '地址'
 | 
			
		||||
      }, {
 | 
			
		||||
        __config__: {
 | 
			
		||||
          layout: 'raw',
 | 
			
		||||
          tag: 'el-table-column',
 | 
			
		||||
          renderKey: 15957617660151
 | 
			
		||||
        },
 | 
			
		||||
        prop: 'name',
 | 
			
		||||
        label: '名称'
 | 
			
		||||
      }, {
 | 
			
		||||
        __config__: {
 | 
			
		||||
          layout: 'raw',
 | 
			
		||||
          tag: 'el-table-column',
 | 
			
		||||
          renderKey: 1595774496335,
 | 
			
		||||
          children: [
 | 
			
		||||
            {
 | 
			
		||||
              __config__: {
 | 
			
		||||
                label: '按钮',
 | 
			
		||||
                tag: 'el-button',
 | 
			
		||||
                tagIcon: 'button',
 | 
			
		||||
                layout: 'raw',
 | 
			
		||||
                renderKey: 1595779809901
 | 
			
		||||
              },
 | 
			
		||||
              __slot__: {
 | 
			
		||||
                default: '主要按钮'
 | 
			
		||||
              },
 | 
			
		||||
              type: 'primary',
 | 
			
		||||
              icon: 'el-icon-search',
 | 
			
		||||
              round: false,
 | 
			
		||||
              size: 'medium'
 | 
			
		||||
            }
 | 
			
		||||
          ]
 | 
			
		||||
        },
 | 
			
		||||
        label: '操作'
 | 
			
		||||
      }]
 | 
			
		||||
    },
 | 
			
		||||
    data: [],
 | 
			
		||||
    directives: [{
 | 
			
		||||
      name: 'loading',
 | 
			
		||||
      value: true
 | 
			
		||||
    }],
 | 
			
		||||
    border: true,
 | 
			
		||||
    type: 'default',
 | 
			
		||||
    justify: 'start',
 | 
			
		||||
    align: 'top'
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
							
								
								
									
										18
									
								
								src/components/generator/css.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/components/generator/css.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
const styles = {
 | 
			
		||||
  'el-rate': '.el-rate{display: inline-block; vertical-align: text-top;}',
 | 
			
		||||
  'el-upload': '.el-upload__tip{line-height: 1.2;}'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function addCss(cssList, el) {
 | 
			
		||||
  const css = styles[el.__config__.tag]
 | 
			
		||||
  css && cssList.indexOf(css) === -1 && cssList.push(css)
 | 
			
		||||
  if (el.__config__.children) {
 | 
			
		||||
    el.__config__.children.forEach(el2 => addCss(cssList, el2))
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function makeUpCss(conf) {
 | 
			
		||||
  const cssList = []
 | 
			
		||||
  conf.fields.forEach(el => addCss(cssList, el))
 | 
			
		||||
  return cssList.join('\n')
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								src/components/generator/drawingDefalut.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/components/generator/drawingDefalut.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
export default [
 | 
			
		||||
  {
 | 
			
		||||
    __config__: {
 | 
			
		||||
      label: '单行文本',
 | 
			
		||||
      labelWidth: null,
 | 
			
		||||
      showLabel: true,
 | 
			
		||||
      changeTag: true,
 | 
			
		||||
      tag: 'el-input',
 | 
			
		||||
      tagIcon: 'input',
 | 
			
		||||
      defaultValue: undefined,
 | 
			
		||||
      required: true,
 | 
			
		||||
      layout: 'colFormItem',
 | 
			
		||||
      span: 24,
 | 
			
		||||
      document: 'https://element.eleme.cn/#/zh-CN/component/input',
 | 
			
		||||
      // 正则校验规则
 | 
			
		||||
      regList: [{
 | 
			
		||||
        pattern: '/^1(3|4|5|7|8|9)\\d{9}$/',
 | 
			
		||||
        message: '手机号格式错误'
 | 
			
		||||
      }]
 | 
			
		||||
    },
 | 
			
		||||
    // 组件的插槽属性
 | 
			
		||||
    __slot__: {
 | 
			
		||||
      prepend: '',
 | 
			
		||||
      append: ''
 | 
			
		||||
    },
 | 
			
		||||
    __vModel__: 'mobile',
 | 
			
		||||
    placeholder: '请输入手机号',
 | 
			
		||||
    style: { width: '100%' },
 | 
			
		||||
    clearable: true,
 | 
			
		||||
    'prefix-icon': 'el-icon-mobile',
 | 
			
		||||
    'suffix-icon': '',
 | 
			
		||||
    maxlength: 11,
 | 
			
		||||
    'show-word-limit': true,
 | 
			
		||||
    readonly: false,
 | 
			
		||||
    disabled: false
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
							
								
								
									
										399
									
								
								src/components/generator/html.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										399
									
								
								src/components/generator/html.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,399 @@
 | 
			
		||||
/* eslint-disable max-len */
 | 
			
		||||
import ruleTrigger from './ruleTrigger'
 | 
			
		||||
 | 
			
		||||
let confGlobal
 | 
			
		||||
let someSpanIsNot24
 | 
			
		||||
 | 
			
		||||
export function dialogWrapper(str) {
 | 
			
		||||
  return `<el-dialog v-bind="$attrs" v-on="$listeners" @open="onOpen" @close="onClose" title="Dialog Titile">
 | 
			
		||||
    ${str}
 | 
			
		||||
    <div slot="footer">
 | 
			
		||||
      <el-button @click="close">取消</el-button>
 | 
			
		||||
      <el-button type="primary" @click="handelConfirm">确定</el-button>
 | 
			
		||||
    </div>
 | 
			
		||||
  </el-dialog>`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function vueTemplate(str) {
 | 
			
		||||
  return `<template>
 | 
			
		||||
    <div>
 | 
			
		||||
      ${str}
 | 
			
		||||
    </div>
 | 
			
		||||
  </template>`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function vueScript(str) {
 | 
			
		||||
  return `<script>
 | 
			
		||||
    ${str}
 | 
			
		||||
  </script>`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function cssStyle(cssStr) {
 | 
			
		||||
  return `<style>
 | 
			
		||||
    ${cssStr}
 | 
			
		||||
  </style>`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function buildFormTemplate(scheme, child, type) {
 | 
			
		||||
  let labelPosition = ''
 | 
			
		||||
  if (scheme.labelPosition !== 'right') {
 | 
			
		||||
    labelPosition = `label-position="${scheme.labelPosition}"`
 | 
			
		||||
  }
 | 
			
		||||
  const disabled = scheme.disabled ? `:disabled="${scheme.disabled}"` : ''
 | 
			
		||||
  let str = `<el-form ref="${scheme.formRef}" :model="${scheme.formModel}" :rules="${scheme.formRules}" size="${scheme.size}" ${disabled} label-width="${scheme.labelWidth}px" ${labelPosition}>
 | 
			
		||||
      ${child}
 | 
			
		||||
      ${buildFromBtns(scheme, type)}
 | 
			
		||||
    </el-form>`
 | 
			
		||||
  if (someSpanIsNot24) {
 | 
			
		||||
    str = `<el-row :gutter="${scheme.gutter}">
 | 
			
		||||
        ${str}
 | 
			
		||||
      </el-row>`
 | 
			
		||||
  }
 | 
			
		||||
  return str
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function buildFromBtns(scheme, type) {
 | 
			
		||||
  let str = ''
 | 
			
		||||
  if (scheme.formBtns && type === 'file') {
 | 
			
		||||
    str = `<el-form-item size="large">
 | 
			
		||||
          <el-button type="primary" @click="submitForm">提交</el-button>
 | 
			
		||||
          <el-button @click="resetForm">重置</el-button>
 | 
			
		||||
        </el-form-item>`
 | 
			
		||||
    if (someSpanIsNot24) {
 | 
			
		||||
      str = `<el-col :span="24">
 | 
			
		||||
          ${str}
 | 
			
		||||
        </el-col>`
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return str
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// span不为24的用el-col包裹
 | 
			
		||||
function colWrapper(scheme, str) {
 | 
			
		||||
  if (someSpanIsNot24 || scheme.__config__.span !== 24) {
 | 
			
		||||
    return `<el-col :span="${scheme.__config__.span}">
 | 
			
		||||
      ${str}
 | 
			
		||||
    </el-col>`
 | 
			
		||||
  }
 | 
			
		||||
  return str
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const layouts = {
 | 
			
		||||
  colFormItem(scheme) {
 | 
			
		||||
    const config = scheme.__config__
 | 
			
		||||
    let labelWidth = ''
 | 
			
		||||
    let label = `label="${config.label}"`
 | 
			
		||||
    if (config.labelWidth && config.labelWidth !== confGlobal.labelWidth) {
 | 
			
		||||
      labelWidth = `label-width="${config.labelWidth}px"`
 | 
			
		||||
    }
 | 
			
		||||
    if (config.showLabel === false) {
 | 
			
		||||
      labelWidth = 'label-width="0"'
 | 
			
		||||
      label = ''
 | 
			
		||||
    }
 | 
			
		||||
    const required = !ruleTrigger[config.tag] && config.required ? 'required' : ''
 | 
			
		||||
    const tagDom = tags[config.tag] ? tags[config.tag](scheme) : null
 | 
			
		||||
    let str = `<el-form-item ${labelWidth} ${label} prop="${scheme.__vModel__}" ${required}>
 | 
			
		||||
        ${tagDom}
 | 
			
		||||
      </el-form-item>`
 | 
			
		||||
    str = colWrapper(scheme, str)
 | 
			
		||||
    return str
 | 
			
		||||
  },
 | 
			
		||||
  rowFormItem(scheme) {
 | 
			
		||||
    const config = scheme.__config__
 | 
			
		||||
    const type = scheme.type === 'default' ? '' : `type="${scheme.type}"`
 | 
			
		||||
    const justify = scheme.type === 'default' ? '' : `justify="${scheme.justify}"`
 | 
			
		||||
    const align = scheme.type === 'default' ? '' : `align="${scheme.align}"`
 | 
			
		||||
    const gutter = scheme.gutter ? `:gutter="${scheme.gutter}"` : ''
 | 
			
		||||
    const children = config.children.map(el => layouts[el.__config__.layout](el))
 | 
			
		||||
    let str = `<el-row ${type} ${justify} ${align} ${gutter}>
 | 
			
		||||
      ${children.join('\n')}
 | 
			
		||||
    </el-row>`
 | 
			
		||||
    str = colWrapper(scheme, str)
 | 
			
		||||
    return str
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const tags = {
 | 
			
		||||
  'el-button': el => {
 | 
			
		||||
    const {
 | 
			
		||||
      tag, disabled
 | 
			
		||||
    } = attrBuilder(el)
 | 
			
		||||
    const type = el.type ? `type="${el.type}"` : ''
 | 
			
		||||
    const icon = el.icon ? `icon="${el.icon}"` : ''
 | 
			
		||||
    const round = el.round ? 'round' : ''
 | 
			
		||||
    const size = el.size ? `size="${el.size}"` : ''
 | 
			
		||||
    const plain = el.plain ? 'plain' : ''
 | 
			
		||||
    const circle = el.circle ? 'circle' : ''
 | 
			
		||||
    let child = buildElButtonChild(el)
 | 
			
		||||
 | 
			
		||||
    if (child) child = `\n${child}\n` // 换行
 | 
			
		||||
    return `<${tag} ${type} ${icon} ${round} ${size} ${plain} ${disabled} ${circle}>${child}</${tag}>`
 | 
			
		||||
  },
 | 
			
		||||
  'el-input': el => {
 | 
			
		||||
    const {
 | 
			
		||||
      tag, disabled, vModel, clearable, placeholder, width
 | 
			
		||||
    } = attrBuilder(el)
 | 
			
		||||
    const maxlength = el.maxlength ? `:maxlength="${el.maxlength}"` : ''
 | 
			
		||||
    const showWordLimit = el['show-word-limit'] ? 'show-word-limit' : ''
 | 
			
		||||
    const readonly = el.readonly ? 'readonly' : ''
 | 
			
		||||
    const prefixIcon = el['prefix-icon'] ? `prefix-icon='${el['prefix-icon']}'` : ''
 | 
			
		||||
    const suffixIcon = el['suffix-icon'] ? `suffix-icon='${el['suffix-icon']}'` : ''
 | 
			
		||||
    const showPassword = el['show-password'] ? 'show-password' : ''
 | 
			
		||||
    const type = el.type ? `type="${el.type}"` : ''
 | 
			
		||||
    const autosize = el.autosize && el.autosize.minRows
 | 
			
		||||
      ? `:autosize="{minRows: ${el.autosize.minRows}, maxRows: ${el.autosize.maxRows}}"`
 | 
			
		||||
      : ''
 | 
			
		||||
    let child = buildElInputChild(el)
 | 
			
		||||
 | 
			
		||||
    if (child) child = `\n${child}\n` // 换行
 | 
			
		||||
    return `<${tag} ${vModel} ${type} ${placeholder} ${maxlength} ${showWordLimit} ${readonly} ${disabled} ${clearable} ${prefixIcon} ${suffixIcon} ${showPassword} ${autosize} ${width}>${child}</${tag}>`
 | 
			
		||||
  },
 | 
			
		||||
  'el-input-number': el => {
 | 
			
		||||
    const {
 | 
			
		||||
      tag, disabled, vModel, placeholder
 | 
			
		||||
    } = attrBuilder(el)
 | 
			
		||||
    const controlsPosition = el['controls-position'] ? `controls-position=${el['controls-position']}` : ''
 | 
			
		||||
    const min = el.min ? `:min='${el.min}'` : ''
 | 
			
		||||
    const max = el.max ? `:max='${el.max}'` : ''
 | 
			
		||||
    const step = el.step ? `:step='${el.step}'` : ''
 | 
			
		||||
    const stepStrictly = el['step-strictly'] ? 'step-strictly' : ''
 | 
			
		||||
    const precision = el.precision ? `:precision='${el.precision}'` : ''
 | 
			
		||||
 | 
			
		||||
    return `<${tag} ${vModel} ${placeholder} ${step} ${stepStrictly} ${precision} ${controlsPosition} ${min} ${max} ${disabled}></${tag}>`
 | 
			
		||||
  },
 | 
			
		||||
  'el-select': el => {
 | 
			
		||||
    const {
 | 
			
		||||
      tag, disabled, vModel, clearable, placeholder, width
 | 
			
		||||
    } = attrBuilder(el)
 | 
			
		||||
    const filterable = el.filterable ? 'filterable' : ''
 | 
			
		||||
    const multiple = el.multiple ? 'multiple' : ''
 | 
			
		||||
    let child = buildElSelectChild(el)
 | 
			
		||||
 | 
			
		||||
    if (child) child = `\n${child}\n` // 换行
 | 
			
		||||
    return `<${tag} ${vModel} ${placeholder} ${disabled} ${multiple} ${filterable} ${clearable} ${width}>${child}</${tag}>`
 | 
			
		||||
  },
 | 
			
		||||
  'el-radio-group': el => {
 | 
			
		||||
    const { tag, disabled, vModel } = attrBuilder(el)
 | 
			
		||||
    const size = `size="${el.size}"`
 | 
			
		||||
    let child = buildElRadioGroupChild(el)
 | 
			
		||||
 | 
			
		||||
    if (child) child = `\n${child}\n` // 换行
 | 
			
		||||
    return `<${tag} ${vModel} ${size} ${disabled}>${child}</${tag}>`
 | 
			
		||||
  },
 | 
			
		||||
  'el-checkbox-group': el => {
 | 
			
		||||
    const { tag, disabled, vModel } = attrBuilder(el)
 | 
			
		||||
    const size = `size="${el.size}"`
 | 
			
		||||
    const min = el.min ? `:min="${el.min}"` : ''
 | 
			
		||||
    const max = el.max ? `:max="${el.max}"` : ''
 | 
			
		||||
    let child = buildElCheckboxGroupChild(el)
 | 
			
		||||
 | 
			
		||||
    if (child) child = `\n${child}\n` // 换行
 | 
			
		||||
    return `<${tag} ${vModel} ${min} ${max} ${size} ${disabled}>${child}</${tag}>`
 | 
			
		||||
  },
 | 
			
		||||
  'el-switch': el => {
 | 
			
		||||
    const { tag, disabled, vModel } = attrBuilder(el)
 | 
			
		||||
    const activeText = el['active-text'] ? `active-text="${el['active-text']}"` : ''
 | 
			
		||||
    const inactiveText = el['inactive-text'] ? `inactive-text="${el['inactive-text']}"` : ''
 | 
			
		||||
    const activeColor = el['active-color'] ? `active-color="${el['active-color']}"` : ''
 | 
			
		||||
    const inactiveColor = el['inactive-color'] ? `inactive-color="${el['inactive-color']}"` : ''
 | 
			
		||||
    const activeValue = el['active-value'] !== true ? `:active-value='${JSON.stringify(el['active-value'])}'` : ''
 | 
			
		||||
    const inactiveValue = el['inactive-value'] !== false ? `:inactive-value='${JSON.stringify(el['inactive-value'])}'` : ''
 | 
			
		||||
 | 
			
		||||
    return `<${tag} ${vModel} ${activeText} ${inactiveText} ${activeColor} ${inactiveColor} ${activeValue} ${inactiveValue} ${disabled}></${tag}>`
 | 
			
		||||
  },
 | 
			
		||||
  'el-cascader': el => {
 | 
			
		||||
    const {
 | 
			
		||||
      tag, disabled, vModel, clearable, placeholder, width
 | 
			
		||||
    } = attrBuilder(el)
 | 
			
		||||
    const options = el.options ? `:options="${el.__vModel__}Options"` : ''
 | 
			
		||||
    const props = el.props ? `:props="${el.__vModel__}Props"` : ''
 | 
			
		||||
    const showAllLevels = el['show-all-levels'] ? '' : ':show-all-levels="false"'
 | 
			
		||||
    const filterable = el.filterable ? 'filterable' : ''
 | 
			
		||||
    const separator = el.separator === '/' ? '' : `separator="${el.separator}"`
 | 
			
		||||
 | 
			
		||||
    return `<${tag} ${vModel} ${options} ${props} ${width} ${showAllLevels} ${placeholder} ${separator} ${filterable} ${clearable} ${disabled}></${tag}>`
 | 
			
		||||
  },
 | 
			
		||||
  'el-slider': el => {
 | 
			
		||||
    const { tag, disabled, vModel } = attrBuilder(el)
 | 
			
		||||
    const min = el.min ? `:min='${el.min}'` : ''
 | 
			
		||||
    const max = el.max ? `:max='${el.max}'` : ''
 | 
			
		||||
    const step = el.step ? `:step='${el.step}'` : ''
 | 
			
		||||
    const range = el.range ? 'range' : ''
 | 
			
		||||
    const showStops = el['show-stops'] ? `:show-stops="${el['show-stops']}"` : ''
 | 
			
		||||
 | 
			
		||||
    return `<${tag} ${min} ${max} ${step} ${vModel} ${range} ${showStops} ${disabled}></${tag}>`
 | 
			
		||||
  },
 | 
			
		||||
  'el-time-picker': el => {
 | 
			
		||||
    const {
 | 
			
		||||
      tag, disabled, vModel, clearable, placeholder, width
 | 
			
		||||
    } = attrBuilder(el)
 | 
			
		||||
    const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : ''
 | 
			
		||||
    const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : ''
 | 
			
		||||
    const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : ''
 | 
			
		||||
    const isRange = el['is-range'] ? 'is-range' : ''
 | 
			
		||||
    const format = el.format ? `format="${el.format}"` : ''
 | 
			
		||||
    const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : ''
 | 
			
		||||
    const pickerOptions = el['picker-options'] ? `:picker-options='${JSON.stringify(el['picker-options'])}'` : ''
 | 
			
		||||
 | 
			
		||||
    return `<${tag} ${vModel} ${isRange} ${format} ${valueFormat} ${pickerOptions} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${disabled}></${tag}>`
 | 
			
		||||
  },
 | 
			
		||||
  'el-date-picker': el => {
 | 
			
		||||
    const {
 | 
			
		||||
      tag, disabled, vModel, clearable, placeholder, width
 | 
			
		||||
    } = attrBuilder(el)
 | 
			
		||||
    const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : ''
 | 
			
		||||
    const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : ''
 | 
			
		||||
    const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : ''
 | 
			
		||||
    const format = el.format ? `format="${el.format}"` : ''
 | 
			
		||||
    const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : ''
 | 
			
		||||
    const type = el.type === 'date' ? '' : `type="${el.type}"`
 | 
			
		||||
    const readonly = el.readonly ? 'readonly' : ''
 | 
			
		||||
 | 
			
		||||
    return `<${tag} ${type} ${vModel} ${format} ${valueFormat} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${readonly} ${disabled}></${tag}>`
 | 
			
		||||
  },
 | 
			
		||||
  'el-rate': el => {
 | 
			
		||||
    const { tag, disabled, vModel } = attrBuilder(el)
 | 
			
		||||
    const max = el.max ? `:max='${el.max}'` : ''
 | 
			
		||||
    const allowHalf = el['allow-half'] ? 'allow-half' : ''
 | 
			
		||||
    const showText = el['show-text'] ? 'show-text' : ''
 | 
			
		||||
    const showScore = el['show-score'] ? 'show-score' : ''
 | 
			
		||||
 | 
			
		||||
    return `<${tag} ${vModel} ${max} ${allowHalf} ${showText} ${showScore} ${disabled}></${tag}>`
 | 
			
		||||
  },
 | 
			
		||||
  'el-color-picker': el => {
 | 
			
		||||
    const { tag, disabled, vModel } = attrBuilder(el)
 | 
			
		||||
    const size = `size="${el.size}"`
 | 
			
		||||
    const showAlpha = el['show-alpha'] ? 'show-alpha' : ''
 | 
			
		||||
    const colorFormat = el['color-format'] ? `color-format="${el['color-format']}"` : ''
 | 
			
		||||
 | 
			
		||||
    return `<${tag} ${vModel} ${size} ${showAlpha} ${colorFormat} ${disabled}></${tag}>`
 | 
			
		||||
  },
 | 
			
		||||
  'el-upload': el => {
 | 
			
		||||
    const { tag } = el.__config__
 | 
			
		||||
    const disabled = el.disabled ? ':disabled=\'true\'' : ''
 | 
			
		||||
    const action = el.action ? `:action="${el.__vModel__}Action"` : ''
 | 
			
		||||
    const multiple = el.multiple ? 'multiple' : ''
 | 
			
		||||
    const listType = el['list-type'] !== 'text' ? `list-type="${el['list-type']}"` : ''
 | 
			
		||||
    const accept = el.accept ? `accept="${el.accept}"` : ''
 | 
			
		||||
    const name = el.name !== 'file' ? `name="${el.name}"` : ''
 | 
			
		||||
    const autoUpload = el['auto-upload'] === false ? ':auto-upload="false"' : ''
 | 
			
		||||
    const beforeUpload = `:before-upload="${el.__vModel__}BeforeUpload"`
 | 
			
		||||
    const fileList = `:file-list="${el.__vModel__}fileList"`
 | 
			
		||||
    const ref = `ref="${el.__vModel__}"`
 | 
			
		||||
    let child = buildElUploadChild(el)
 | 
			
		||||
 | 
			
		||||
    if (child) child = `\n${child}\n` // 换行
 | 
			
		||||
    return `<${tag} ${ref} ${fileList} ${action} ${autoUpload} ${multiple} ${beforeUpload} ${listType} ${accept} ${name} ${disabled}>${child}</${tag}>`
 | 
			
		||||
  },
 | 
			
		||||
  tinymce: el => {
 | 
			
		||||
    const { tag, vModel, placeholder } = attrBuilder(el)
 | 
			
		||||
    const height = el.height ? `:height="${el.height}"` : ''
 | 
			
		||||
    const branding = el.branding ? `:branding="${el.branding}"` : ''
 | 
			
		||||
    return `<${tag} ${vModel} ${placeholder} ${height} ${branding}></${tag}>`
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function attrBuilder(el) {
 | 
			
		||||
  return {
 | 
			
		||||
    tag: el.__config__.tag,
 | 
			
		||||
    vModel: `v-model="${confGlobal.formModel}.${el.__vModel__}"`,
 | 
			
		||||
    clearable: el.clearable ? 'clearable' : '',
 | 
			
		||||
    placeholder: el.placeholder ? `placeholder="${el.placeholder}"` : '',
 | 
			
		||||
    width: el.style && el.style.width ? ':style="{width: \'100%\'}"' : '',
 | 
			
		||||
    disabled: el.disabled ? ':disabled=\'true\'' : ''
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// el-buttin 子级
 | 
			
		||||
function buildElButtonChild(scheme) {
 | 
			
		||||
  const children = []
 | 
			
		||||
  const slot = scheme.__slot__ || {}
 | 
			
		||||
  if (slot.default) {
 | 
			
		||||
    children.push(slot.default)
 | 
			
		||||
  }
 | 
			
		||||
  return children.join('\n')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// el-input 子级
 | 
			
		||||
function buildElInputChild(scheme) {
 | 
			
		||||
  const children = []
 | 
			
		||||
  const slot = scheme.__slot__
 | 
			
		||||
  if (slot && slot.prepend) {
 | 
			
		||||
    children.push(`<template slot="prepend">${slot.prepend}</template>`)
 | 
			
		||||
  }
 | 
			
		||||
  if (slot && slot.append) {
 | 
			
		||||
    children.push(`<template slot="append">${slot.append}</template>`)
 | 
			
		||||
  }
 | 
			
		||||
  return children.join('\n')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// el-select 子级
 | 
			
		||||
function buildElSelectChild(scheme) {
 | 
			
		||||
  const children = []
 | 
			
		||||
  const slot = scheme.__slot__
 | 
			
		||||
  if (slot && slot.options && slot.options.length) {
 | 
			
		||||
    children.push(`<el-option v-for="(item, index) in ${scheme.__vModel__}Options" :key="index" :label="item.label" :value="item.value" :disabled="item.disabled"></el-option>`)
 | 
			
		||||
  }
 | 
			
		||||
  return children.join('\n')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// el-radio-group 子级
 | 
			
		||||
function buildElRadioGroupChild(scheme) {
 | 
			
		||||
  const children = []
 | 
			
		||||
  const slot = scheme.__slot__
 | 
			
		||||
  const config = scheme.__config__
 | 
			
		||||
  if (slot && slot.options && slot.options.length) {
 | 
			
		||||
    const tag = config.optionType === 'button' ? 'el-radio-button' : 'el-radio'
 | 
			
		||||
    const border = config.border ? 'border' : ''
 | 
			
		||||
    children.push(`<${tag} v-for="(item, index) in ${scheme.__vModel__}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}</${tag}>`)
 | 
			
		||||
  }
 | 
			
		||||
  return children.join('\n')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// el-checkbox-group 子级
 | 
			
		||||
function buildElCheckboxGroupChild(scheme) {
 | 
			
		||||
  const children = []
 | 
			
		||||
  const slot = scheme.__slot__
 | 
			
		||||
  const config = scheme.__config__
 | 
			
		||||
  if (slot && slot.options && slot.options.length) {
 | 
			
		||||
    const tag = config.optionType === 'button' ? 'el-checkbox-button' : 'el-checkbox'
 | 
			
		||||
    const border = config.border ? 'border' : ''
 | 
			
		||||
    children.push(`<${tag} v-for="(item, index) in ${scheme.__vModel__}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}</${tag}>`)
 | 
			
		||||
  }
 | 
			
		||||
  return children.join('\n')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// el-upload 子级
 | 
			
		||||
function buildElUploadChild(scheme) {
 | 
			
		||||
  const list = []
 | 
			
		||||
  const config = scheme.__config__
 | 
			
		||||
  if (scheme['list-type'] === 'picture-card') list.push('<i class="el-icon-plus"></i>')
 | 
			
		||||
  else list.push(`<el-button size="small" type="primary" icon="el-icon-upload">${config.buttonText}</el-button>`)
 | 
			
		||||
  if (config.showTip) list.push(`<div slot="tip" class="el-upload__tip">只能上传不超过 ${config.fileSize}${config.sizeUnit} 的${scheme.accept}文件</div>`)
 | 
			
		||||
  return list.join('\n')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 组装html代码。【入口函数】
 | 
			
		||||
 * @param {Object} formConfig 整个表单配置
 | 
			
		||||
 * @param {String} type 生成类型,文件或弹窗等
 | 
			
		||||
 */
 | 
			
		||||
export function makeUpHtml(formConfig, type) {
 | 
			
		||||
  const htmlList = []
 | 
			
		||||
  confGlobal = formConfig
 | 
			
		||||
  // 判断布局是否都沾满了24个栅格,以备后续简化代码结构
 | 
			
		||||
  someSpanIsNot24 = formConfig.fields.some(item => item.__config__.span !== 24)
 | 
			
		||||
  // 遍历渲染每个组件成html
 | 
			
		||||
  formConfig.fields.forEach(el => {
 | 
			
		||||
    htmlList.push(layouts[el.__config__.layout](el))
 | 
			
		||||
  })
 | 
			
		||||
  const htmlStr = htmlList.join('\n')
 | 
			
		||||
  // 将组件代码放进form标签
 | 
			
		||||
  let temp = buildFormTemplate(formConfig, htmlStr, type)
 | 
			
		||||
  // dialog标签包裹代码
 | 
			
		||||
  if (type === 'dialog') {
 | 
			
		||||
    temp = dialogWrapper(temp)
 | 
			
		||||
  }
 | 
			
		||||
  confGlobal = null
 | 
			
		||||
  return temp
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										271
									
								
								src/components/generator/js.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										271
									
								
								src/components/generator/js.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,271 @@
 | 
			
		||||
import { isArray } from 'util'
 | 
			
		||||
import { exportDefault, titleCase, deepClone } from '@/utils'
 | 
			
		||||
import ruleTrigger from './ruleTrigger'
 | 
			
		||||
 | 
			
		||||
const units = {
 | 
			
		||||
  KB: '1024',
 | 
			
		||||
  MB: '1024 / 1024',
 | 
			
		||||
  GB: '1024 / 1024 / 1024'
 | 
			
		||||
}
 | 
			
		||||
let confGlobal
 | 
			
		||||
const inheritAttrs = {
 | 
			
		||||
  file: '',
 | 
			
		||||
  dialog: 'inheritAttrs: false,'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 组装js 【入口函数】
 | 
			
		||||
 * @param {Object} formConfig 整个表单配置
 | 
			
		||||
 * @param {String} type 生成类型,文件或弹窗等
 | 
			
		||||
 */
 | 
			
		||||
export function makeUpJs(formConfig, type) {
 | 
			
		||||
  confGlobal = formConfig = deepClone(formConfig)
 | 
			
		||||
  const dataList = []
 | 
			
		||||
  const ruleList = []
 | 
			
		||||
  const optionsList = []
 | 
			
		||||
  const propsList = []
 | 
			
		||||
  const methodList = mixinMethod(type)
 | 
			
		||||
  const uploadVarList = []
 | 
			
		||||
  const created = []
 | 
			
		||||
 | 
			
		||||
  formConfig.fields.forEach(el => {
 | 
			
		||||
    buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  const script = buildexport(
 | 
			
		||||
    formConfig,
 | 
			
		||||
    type,
 | 
			
		||||
    dataList.join('\n'),
 | 
			
		||||
    ruleList.join('\n'),
 | 
			
		||||
    optionsList.join('\n'),
 | 
			
		||||
    uploadVarList.join('\n'),
 | 
			
		||||
    propsList.join('\n'),
 | 
			
		||||
    methodList.join('\n'),
 | 
			
		||||
    created.join('\n')
 | 
			
		||||
  )
 | 
			
		||||
  confGlobal = null
 | 
			
		||||
  return script
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 构建组件属性
 | 
			
		||||
function buildAttributes(scheme, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created) {
 | 
			
		||||
  const config = scheme.__config__
 | 
			
		||||
  const slot = scheme.__slot__
 | 
			
		||||
  buildData(scheme, dataList)
 | 
			
		||||
  buildRules(scheme, ruleList)
 | 
			
		||||
 | 
			
		||||
  // 特殊处理options属性
 | 
			
		||||
  if (scheme.options || (slot && slot.options && slot.options.length)) {
 | 
			
		||||
    buildOptions(scheme, optionsList)
 | 
			
		||||
    if (config.dataType === 'dynamic') {
 | 
			
		||||
      const model = `${scheme.__vModel__}Options`
 | 
			
		||||
      const options = titleCase(model)
 | 
			
		||||
      const methodName = `get${options}`
 | 
			
		||||
      buildOptionMethod(methodName, model, methodList, scheme)
 | 
			
		||||
      callInCreated(methodName, created)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 处理props
 | 
			
		||||
  if (scheme.props && scheme.props.props) {
 | 
			
		||||
    buildProps(scheme, propsList)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 处理el-upload的action
 | 
			
		||||
  if (scheme.action && config.tag === 'el-upload') {
 | 
			
		||||
    uploadVarList.push(
 | 
			
		||||
      `${scheme.__vModel__}Action: '${scheme.action}',
 | 
			
		||||
      ${scheme.__vModel__}fileList: [],`
 | 
			
		||||
    )
 | 
			
		||||
    methodList.push(buildBeforeUpload(scheme))
 | 
			
		||||
    // 非自动上传时,生成手动上传的函数
 | 
			
		||||
    if (!scheme['auto-upload']) {
 | 
			
		||||
      methodList.push(buildSubmitUpload(scheme))
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 构建子级组件属性
 | 
			
		||||
  if (config.children) {
 | 
			
		||||
    config.children.forEach(item => {
 | 
			
		||||
      buildAttributes(item, dataList, ruleList, optionsList, methodList, propsList, uploadVarList, created)
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 在Created调用函数
 | 
			
		||||
function callInCreated(methodName, created) {
 | 
			
		||||
  created.push(`this.${methodName}()`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 混入处理函数
 | 
			
		||||
function mixinMethod(type) {
 | 
			
		||||
  const list = []; const
 | 
			
		||||
    minxins = {
 | 
			
		||||
      file: confGlobal.formBtns ? {
 | 
			
		||||
        submitForm: `submitForm() {
 | 
			
		||||
        this.$refs['${confGlobal.formRef}'].validate(valid => {
 | 
			
		||||
          if(!valid) return
 | 
			
		||||
          // TODO 提交表单
 | 
			
		||||
        })
 | 
			
		||||
      },`,
 | 
			
		||||
        resetForm: `resetForm() {
 | 
			
		||||
        this.$refs['${confGlobal.formRef}'].resetFields()
 | 
			
		||||
      },`
 | 
			
		||||
      } : null,
 | 
			
		||||
      dialog: {
 | 
			
		||||
        onOpen: 'onOpen() {},',
 | 
			
		||||
        onClose: `onClose() {
 | 
			
		||||
        this.$refs['${confGlobal.formRef}'].resetFields()
 | 
			
		||||
      },`,
 | 
			
		||||
        close: `close() {
 | 
			
		||||
        this.$emit('update:visible', false)
 | 
			
		||||
      },`,
 | 
			
		||||
        handelConfirm: `handelConfirm() {
 | 
			
		||||
        this.$refs['${confGlobal.formRef}'].validate(valid => {
 | 
			
		||||
          if(!valid) return
 | 
			
		||||
          this.close()
 | 
			
		||||
        })
 | 
			
		||||
      },`
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  const methods = minxins[type]
 | 
			
		||||
  if (methods) {
 | 
			
		||||
    Object.keys(methods).forEach(key => {
 | 
			
		||||
      list.push(methods[key])
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return list
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 构建data
 | 
			
		||||
function buildData(scheme, dataList) {
 | 
			
		||||
  const config = scheme.__config__
 | 
			
		||||
  if (scheme.__vModel__ === undefined) return
 | 
			
		||||
  const defaultValue = JSON.stringify(config.defaultValue)
 | 
			
		||||
  dataList.push(`${scheme.__vModel__}: ${defaultValue},`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 构建校验规则
 | 
			
		||||
function buildRules(scheme, ruleList) {
 | 
			
		||||
  const config = scheme.__config__
 | 
			
		||||
  if (scheme.__vModel__ === undefined) return
 | 
			
		||||
  const rules = []
 | 
			
		||||
  if (ruleTrigger[config.tag]) {
 | 
			
		||||
    if (config.required) {
 | 
			
		||||
      const type = isArray(config.defaultValue) ? 'type: \'array\',' : ''
 | 
			
		||||
      let message = isArray(config.defaultValue) ? `请至少选择一个${config.label}` : scheme.placeholder
 | 
			
		||||
      if (message === undefined) message = `${config.label}不能为空`
 | 
			
		||||
      rules.push(`{ required: true, ${type} message: '${message}', trigger: '${ruleTrigger[config.tag]}' }`)
 | 
			
		||||
    }
 | 
			
		||||
    if (config.regList && isArray(config.regList)) {
 | 
			
		||||
      config.regList.forEach(item => {
 | 
			
		||||
        if (item.pattern) {
 | 
			
		||||
          rules.push(
 | 
			
		||||
            `{ pattern: ${eval(item.pattern)}, message: '${item.message}', trigger: '${ruleTrigger[config.tag]}' }`
 | 
			
		||||
          )
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
    ruleList.push(`${scheme.__vModel__}: [${rules.join(',')}],`)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 构建options
 | 
			
		||||
function buildOptions(scheme, optionsList) {
 | 
			
		||||
  if (scheme.__vModel__ === undefined) return
 | 
			
		||||
  // el-cascader直接有options属性,其他组件都是定义在slot中,所以有两处判断
 | 
			
		||||
  let { options } = scheme
 | 
			
		||||
  if (!options) options = scheme.__slot__.options
 | 
			
		||||
  if (scheme.__config__.dataType === 'dynamic') { options = [] }
 | 
			
		||||
  const str = `${scheme.__vModel__}Options: ${JSON.stringify(options)},`
 | 
			
		||||
  optionsList.push(str)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function buildProps(scheme, propsList) {
 | 
			
		||||
  const str = `${scheme.__vModel__}Props: ${JSON.stringify(scheme.props.props)},`
 | 
			
		||||
  propsList.push(str)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// el-upload的BeforeUpload
 | 
			
		||||
function buildBeforeUpload(scheme) {
 | 
			
		||||
  const config = scheme.__config__
 | 
			
		||||
  const unitNum = units[config.sizeUnit]; let rightSizeCode = ''; let acceptCode = ''; const
 | 
			
		||||
    returnList = []
 | 
			
		||||
  if (config.fileSize) {
 | 
			
		||||
    rightSizeCode = `let isRightSize = file.size / ${unitNum} < ${config.fileSize}
 | 
			
		||||
    if(!isRightSize){
 | 
			
		||||
      this.$message.error('文件大小超过 ${config.fileSize}${config.sizeUnit}')
 | 
			
		||||
    }`
 | 
			
		||||
    returnList.push('isRightSize')
 | 
			
		||||
  }
 | 
			
		||||
  if (scheme.accept) {
 | 
			
		||||
    acceptCode = `let isAccept = new RegExp('${scheme.accept}').test(file.type)
 | 
			
		||||
    if(!isAccept){
 | 
			
		||||
      this.$message.error('应该选择${scheme.accept}类型的文件')
 | 
			
		||||
    }`
 | 
			
		||||
    returnList.push('isAccept')
 | 
			
		||||
  }
 | 
			
		||||
  const str = `${scheme.__vModel__}BeforeUpload(file) {
 | 
			
		||||
    ${rightSizeCode}
 | 
			
		||||
    ${acceptCode}
 | 
			
		||||
    return ${returnList.join('&&')}
 | 
			
		||||
  },`
 | 
			
		||||
  return returnList.length ? str : ''
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// el-upload的submit
 | 
			
		||||
function buildSubmitUpload(scheme) {
 | 
			
		||||
  const str = `submitUpload() {
 | 
			
		||||
    this.$refs['${scheme.__vModel__}'].submit()
 | 
			
		||||
  },`
 | 
			
		||||
  return str
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function buildOptionMethod(methodName, model, methodList, scheme) {
 | 
			
		||||
  const config = scheme.__config__
 | 
			
		||||
  const str = `${methodName}() {
 | 
			
		||||
    // 注意:this.$axios是通过Vue.prototype.$axios = axios挂载产生的
 | 
			
		||||
    this.$axios({
 | 
			
		||||
      method: '${config.method}',
 | 
			
		||||
      url: '${config.url}'
 | 
			
		||||
    }).then(resp => {
 | 
			
		||||
      var { data } = resp
 | 
			
		||||
      this.${model} = data.${config.dataPath}
 | 
			
		||||
    })
 | 
			
		||||
  },`
 | 
			
		||||
  methodList.push(str)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// js整体拼接
 | 
			
		||||
function buildexport(conf, type, data, rules, selectOptions, uploadVar, props, methods, created) {
 | 
			
		||||
  const str = `${exportDefault}{
 | 
			
		||||
  ${inheritAttrs[type]}
 | 
			
		||||
  components: {},
 | 
			
		||||
  props: [],
 | 
			
		||||
  data () {
 | 
			
		||||
    return {
 | 
			
		||||
      ${conf.formModel}: {
 | 
			
		||||
        ${data}
 | 
			
		||||
      },
 | 
			
		||||
      ${conf.formRules}: {
 | 
			
		||||
        ${rules}
 | 
			
		||||
      },
 | 
			
		||||
      ${uploadVar}
 | 
			
		||||
      ${selectOptions}
 | 
			
		||||
      ${props}
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  computed: {},
 | 
			
		||||
  watch: {},
 | 
			
		||||
  created () {
 | 
			
		||||
    ${created}
 | 
			
		||||
  },
 | 
			
		||||
  mounted () {},
 | 
			
		||||
  methods: {
 | 
			
		||||
    ${methods}
 | 
			
		||||
  }
 | 
			
		||||
}`
 | 
			
		||||
  return str
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										16
									
								
								src/components/generator/ruleTrigger.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/components/generator/ruleTrigger.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
/**
 | 
			
		||||
 * 用于生成表单校验,指定正则规则的触发方式。
 | 
			
		||||
 * 未在此处声明无触发方式的组件将不生成rule!!
 | 
			
		||||
 */
 | 
			
		||||
export default {
 | 
			
		||||
  'el-input': 'blur',
 | 
			
		||||
  'el-input-number': 'blur',
 | 
			
		||||
  'el-select': 'change',
 | 
			
		||||
  'el-radio-group': 'change',
 | 
			
		||||
  'el-checkbox-group': 'change',
 | 
			
		||||
  'el-cascader': 'change',
 | 
			
		||||
  'el-time-picker': 'change',
 | 
			
		||||
  'el-date-picker': 'change',
 | 
			
		||||
  'el-rate': 'change',
 | 
			
		||||
  tinymce: 'blur'
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								src/components/tinymce/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/components/tinymce/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
## 简介
 | 
			
		||||
富文本编辑器tinymce的一个vue版本封装。使用cdn动态脚本引入的方式加载。
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										8
									
								
								src/components/tinymce/config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/components/tinymce/config.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
/* eslint-disable max-len */
 | 
			
		||||
 | 
			
		||||
export const plugins = [
 | 
			
		||||
  'advlist anchor autolink autosave code codesample directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textpattern visualblocks visualchars wordcount'
 | 
			
		||||
]
 | 
			
		||||
export const toolbar = [
 | 
			
		||||
  'code searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote removeformat subscript superscript codesample hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen'
 | 
			
		||||
]
 | 
			
		||||
							
								
								
									
										38
									
								
								src/components/tinymce/example/Index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/components/tinymce/example/Index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <Tinymce v-model="defaultValue" :height="300" placeholder="在这里输入文字" />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import Tinymce from '../index.vue'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  components: {
 | 
			
		||||
    Tinymce
 | 
			
		||||
  },
 | 
			
		||||
  props: {
 | 
			
		||||
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      defaultValue: '<p>配置文档参阅:http://tinymce.ax-z.cn</p>'
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
 | 
			
		||||
  },
 | 
			
		||||
  watch: {
 | 
			
		||||
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
 | 
			
		||||
  },
 | 
			
		||||
  mounted() {
 | 
			
		||||
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										3
									
								
								src/components/tinymce/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/components/tinymce/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
import Index from './index.vue'
 | 
			
		||||
 | 
			
		||||
export default Index
 | 
			
		||||
							
								
								
									
										88
									
								
								src/components/tinymce/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/components/tinymce/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <textarea :id="tinymceId" style="visibility: hidden" />
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import loadTinymce from '@/utils/loadTinymce'
 | 
			
		||||
import { plugins, toolbar } from './config'
 | 
			
		||||
import { debounce } from 'throttle-debounce'
 | 
			
		||||
 | 
			
		||||
let num = 1
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  props: {
 | 
			
		||||
    id: {
 | 
			
		||||
      type: String,
 | 
			
		||||
      default: () => {
 | 
			
		||||
        num === 10000 && (num = 1)
 | 
			
		||||
        return `tinymce${+new Date()}${num++}`
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    value: {
 | 
			
		||||
      default: ''
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      tinymceId: this.id
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  mounted() {
 | 
			
		||||
    loadTinymce(tinymce => {
 | 
			
		||||
      // eslint-disable-next-line global-require
 | 
			
		||||
      require('./zh_CN')
 | 
			
		||||
      let conf = {
 | 
			
		||||
        selector: `#${this.tinymceId}`,
 | 
			
		||||
        language: 'zh_CN',
 | 
			
		||||
        menubar: 'file edit insert view format table',
 | 
			
		||||
        plugins,
 | 
			
		||||
        toolbar,
 | 
			
		||||
        height: 300,
 | 
			
		||||
        branding: false,
 | 
			
		||||
        object_resizing: false,
 | 
			
		||||
        end_container_on_empty_block: true,
 | 
			
		||||
        powerpaste_word_import: 'clean',
 | 
			
		||||
        code_dialog_height: 450,
 | 
			
		||||
        code_dialog_width: 1000,
 | 
			
		||||
        advlist_bullet_styles: 'square',
 | 
			
		||||
        advlist_number_styles: 'default',
 | 
			
		||||
        default_link_target: '_blank',
 | 
			
		||||
        link_title: false,
 | 
			
		||||
        nonbreaking_force_tab: true
 | 
			
		||||
      }
 | 
			
		||||
      conf = Object.assign(conf, this.$attrs)
 | 
			
		||||
      conf.init_instance_callback = editor => {
 | 
			
		||||
        if (this.value) editor.setContent(this.value)
 | 
			
		||||
        this.vModel(editor)
 | 
			
		||||
      }
 | 
			
		||||
      tinymce.init(conf)
 | 
			
		||||
    })
 | 
			
		||||
  },
 | 
			
		||||
  destroyed() {
 | 
			
		||||
    this.destroyTinymce()
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    vModel(editor) {
 | 
			
		||||
      // 控制连续写入时setContent的触发频率
 | 
			
		||||
      const debounceSetContent = debounce(250, editor.setContent)
 | 
			
		||||
      this.$watch('value', (val, prevVal) => {
 | 
			
		||||
        if (editor && val !== prevVal && val !== editor.getContent()) {
 | 
			
		||||
          if (typeof val !== 'string') val = val.toString()
 | 
			
		||||
          debounceSetContent.call(editor, val)
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      editor.on('change keyup undo redo', () => {
 | 
			
		||||
        this.$emit('input', editor.getContent())
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    destroyTinymce() {
 | 
			
		||||
      if (!window.tinymce) return
 | 
			
		||||
      const tinymce = window.tinymce.get(this.tinymceId)
 | 
			
		||||
      if (tinymce) {
 | 
			
		||||
        tinymce.destroy()
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
							
								
								
									
										28
									
								
								src/components/tinymce/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/components/tinymce/package.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "form-gen-tinymce",
 | 
			
		||||
  "version": "1.0.0",
 | 
			
		||||
  "description": "富文本编辑器tinymce的一个vue版本封装。使用cdn动态脚本引入的方式加载。",
 | 
			
		||||
  "main": "lib/form-gen-tinymce.umd.js",
 | 
			
		||||
  "directories": {
 | 
			
		||||
    "example": "example"
 | 
			
		||||
  },
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "test": "echo \"Error: no test specified\" && exit 1"
 | 
			
		||||
  },
 | 
			
		||||
  "repository": {
 | 
			
		||||
    "type": "git",
 | 
			
		||||
    "url": "git+https://github.com/JakHuang/form-generator.git"
 | 
			
		||||
  },
 | 
			
		||||
  "keywords": [
 | 
			
		||||
    "tinymce-vue"
 | 
			
		||||
  ],
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "throttle-debounce": "^2.1.0"
 | 
			
		||||
  },
 | 
			
		||||
  "author": "jakHuang",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "bugs": {
 | 
			
		||||
    "url": "https://github.com/JakHuang/form-generator/issues"
 | 
			
		||||
  },
 | 
			
		||||
  "homepage": "https://github.com/JakHuang/form-generator/blob/dev/src/components/tinymce"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										420
									
								
								src/components/tinymce/zh_CN.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										420
									
								
								src/components/tinymce/zh_CN.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,420 @@
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
tinymce.addI18n('zh_CN',{
 | 
			
		||||
"Redo": "\u91cd\u505a",
 | 
			
		||||
"Undo": "\u64a4\u9500",
 | 
			
		||||
"Cut": "\u526a\u5207",
 | 
			
		||||
"Copy": "\u590d\u5236",
 | 
			
		||||
"Paste": "\u7c98\u8d34",
 | 
			
		||||
"Select all": "\u5168\u9009",
 | 
			
		||||
"New document": "\u65b0\u6587\u4ef6",
 | 
			
		||||
"Ok": "\u786e\u5b9a",
 | 
			
		||||
"Cancel": "\u53d6\u6d88",
 | 
			
		||||
"Visual aids": "\u7f51\u683c\u7ebf",
 | 
			
		||||
"Bold": "\u7c97\u4f53",
 | 
			
		||||
"Italic": "\u659c\u4f53",
 | 
			
		||||
"Underline": "\u4e0b\u5212\u7ebf",
 | 
			
		||||
"Strikethrough": "\u5220\u9664\u7ebf",
 | 
			
		||||
"Superscript": "\u4e0a\u6807",
 | 
			
		||||
"Subscript": "\u4e0b\u6807",
 | 
			
		||||
"Clear formatting": "\u6e05\u9664\u683c\u5f0f",
 | 
			
		||||
"Align left": "\u5de6\u8fb9\u5bf9\u9f50",
 | 
			
		||||
"Align center": "\u4e2d\u95f4\u5bf9\u9f50",
 | 
			
		||||
"Align right": "\u53f3\u8fb9\u5bf9\u9f50",
 | 
			
		||||
"Justify": "\u4e24\u7aef\u5bf9\u9f50",
 | 
			
		||||
"Bullet list": "\u9879\u76ee\u7b26\u53f7",
 | 
			
		||||
"Numbered list": "\u7f16\u53f7\u5217\u8868",
 | 
			
		||||
"Decrease indent": "\u51cf\u5c11\u7f29\u8fdb",
 | 
			
		||||
"Increase indent": "\u589e\u52a0\u7f29\u8fdb",
 | 
			
		||||
"Close": "\u5173\u95ed",
 | 
			
		||||
"Formats": "\u683c\u5f0f",
 | 
			
		||||
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "\u4f60\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301\u6253\u5f00\u526a\u8d34\u677f\uff0c\u8bf7\u4f7f\u7528Ctrl+X\/C\/V\u7b49\u5feb\u6377\u952e\u3002",
 | 
			
		||||
"Headers": "\u6807\u9898",
 | 
			
		||||
"Header 1": "\u6807\u98981",
 | 
			
		||||
"Header 2": "\u6807\u98982",
 | 
			
		||||
"Header 3": "\u6807\u98983",
 | 
			
		||||
"Header 4": "\u6807\u98984",
 | 
			
		||||
"Header 5": "\u6807\u98985",
 | 
			
		||||
"Header 6": "\u6807\u98986",
 | 
			
		||||
"Headings": "\u6807\u9898",
 | 
			
		||||
"Heading 1": "\u6807\u98981",
 | 
			
		||||
"Heading 2": "\u6807\u98982",
 | 
			
		||||
"Heading 3": "\u6807\u98983",
 | 
			
		||||
"Heading 4": "\u6807\u98984",
 | 
			
		||||
"Heading 5": "\u6807\u98985",
 | 
			
		||||
"Heading 6": "\u6807\u98986",
 | 
			
		||||
"Preformatted": "\u9884\u5148\u683c\u5f0f\u5316\u7684",
 | 
			
		||||
"Div": "Div",
 | 
			
		||||
"Pre": "Pre",
 | 
			
		||||
"Code": "\u4ee3\u7801",
 | 
			
		||||
"Paragraph": "\u6bb5\u843d",
 | 
			
		||||
"Blockquote": "\u5f15\u6587\u533a\u5757",
 | 
			
		||||
"Inline": "\u6587\u672c",
 | 
			
		||||
"Blocks": "\u57fa\u5757",
 | 
			
		||||
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\u5f53\u524d\u4e3a\u7eaf\u6587\u672c\u7c98\u8d34\u6a21\u5f0f\uff0c\u518d\u6b21\u70b9\u51fb\u53ef\u4ee5\u56de\u5230\u666e\u901a\u7c98\u8d34\u6a21\u5f0f\u3002",
 | 
			
		||||
"Fonts": "\u5b57\u4f53",
 | 
			
		||||
"Font Sizes": "\u5b57\u53f7",
 | 
			
		||||
"Class": "\u7c7b\u578b",
 | 
			
		||||
"Browse for an image": "\u6d4f\u89c8\u56fe\u50cf",
 | 
			
		||||
"OR": "\u6216",
 | 
			
		||||
"Drop an image here": "\u62d6\u653e\u4e00\u5f20\u56fe\u50cf\u81f3\u6b64",
 | 
			
		||||
"Upload": "\u4e0a\u4f20",
 | 
			
		||||
"Block": "\u5757",
 | 
			
		||||
"Align": "\u5bf9\u9f50",
 | 
			
		||||
"Default": "\u9ed8\u8ba4",
 | 
			
		||||
"Circle": "\u7a7a\u5fc3\u5706",
 | 
			
		||||
"Disc": "\u5b9e\u5fc3\u5706",
 | 
			
		||||
"Square": "\u65b9\u5757",
 | 
			
		||||
"Lower Alpha": "\u5c0f\u5199\u82f1\u6587\u5b57\u6bcd",
 | 
			
		||||
"Lower Greek": "\u5c0f\u5199\u5e0c\u814a\u5b57\u6bcd",
 | 
			
		||||
"Lower Roman": "\u5c0f\u5199\u7f57\u9a6c\u5b57\u6bcd",
 | 
			
		||||
"Upper Alpha": "\u5927\u5199\u82f1\u6587\u5b57\u6bcd",
 | 
			
		||||
"Upper Roman": "\u5927\u5199\u7f57\u9a6c\u5b57\u6bcd",
 | 
			
		||||
"Anchor...": "\u951a\u70b9...",
 | 
			
		||||
"Name": "\u540d\u79f0",
 | 
			
		||||
"Id": "\u6807\u8bc6\u7b26",
 | 
			
		||||
"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "\u6807\u8bc6\u7b26\u5e94\u8be5\u4ee5\u5b57\u6bcd\u5f00\u5934\uff0c\u540e\u8ddf\u5b57\u6bcd\u3001\u6570\u5b57\u3001\u7834\u6298\u53f7\u3001\u70b9\u3001\u5192\u53f7\u6216\u4e0b\u5212\u7ebf\u3002",
 | 
			
		||||
"You have unsaved changes are you sure you want to navigate away?": "\u4f60\u8fd8\u6709\u6587\u6863\u5c1a\u672a\u4fdd\u5b58\uff0c\u786e\u5b9a\u8981\u79bb\u5f00\uff1f",
 | 
			
		||||
"Restore last draft": "\u6062\u590d\u4e0a\u6b21\u7684\u8349\u7a3f",
 | 
			
		||||
"Special character...": "\u7279\u6b8a\u5b57\u7b26...",
 | 
			
		||||
"Source code": "\u6e90\u4ee3\u7801",
 | 
			
		||||
"Insert\/Edit code sample": "\u63d2\u5165\/\u7f16\u8f91\u4ee3\u7801\u793a\u4f8b",
 | 
			
		||||
"Language": "\u8bed\u8a00",
 | 
			
		||||
"Code sample...": "\u793a\u4f8b\u4ee3\u7801...",
 | 
			
		||||
"Color Picker": "\u9009\u8272\u5668",
 | 
			
		||||
"R": "R",
 | 
			
		||||
"G": "G",
 | 
			
		||||
"B": "B",
 | 
			
		||||
"Left to right": "\u4ece\u5de6\u5230\u53f3",
 | 
			
		||||
"Right to left": "\u4ece\u53f3\u5230\u5de6",
 | 
			
		||||
"Emoticons...": "\u8868\u60c5\u7b26\u53f7...",
 | 
			
		||||
"Metadata and Document Properties": "\u5143\u6570\u636e\u548c\u6587\u6863\u5c5e\u6027",
 | 
			
		||||
"Title": "\u6807\u9898",
 | 
			
		||||
"Keywords": "\u5173\u952e\u8bcd",
 | 
			
		||||
"Description": "\u63cf\u8ff0",
 | 
			
		||||
"Robots": "\u673a\u5668\u4eba",
 | 
			
		||||
"Author": "\u4f5c\u8005",
 | 
			
		||||
"Encoding": "\u7f16\u7801",
 | 
			
		||||
"Fullscreen": "\u5168\u5c4f",
 | 
			
		||||
"Action": "\u64cd\u4f5c",
 | 
			
		||||
"Shortcut": "\u5feb\u6377\u952e",
 | 
			
		||||
"Help": "\u5e2e\u52a9",
 | 
			
		||||
"Address": "\u5730\u5740",
 | 
			
		||||
"Focus to menubar": "\u79fb\u52a8\u7126\u70b9\u5230\u83dc\u5355\u680f",
 | 
			
		||||
"Focus to toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u5de5\u5177\u680f",
 | 
			
		||||
"Focus to element path": "\u79fb\u52a8\u7126\u70b9\u5230\u5143\u7d20\u8def\u5f84",
 | 
			
		||||
"Focus to contextual toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u4e0a\u4e0b\u6587\u83dc\u5355",
 | 
			
		||||
"Insert link (if link plugin activated)": "\u63d2\u5165\u94fe\u63a5 (\u5982\u679c\u94fe\u63a5\u63d2\u4ef6\u5df2\u6fc0\u6d3b)",
 | 
			
		||||
"Save (if save plugin activated)": "\u4fdd\u5b58(\u5982\u679c\u4fdd\u5b58\u63d2\u4ef6\u5df2\u6fc0\u6d3b)",
 | 
			
		||||
"Find (if searchreplace plugin activated)": "\u67e5\u627e(\u5982\u679c\u67e5\u627e\u66ff\u6362\u63d2\u4ef6\u5df2\u6fc0\u6d3b)",
 | 
			
		||||
"Plugins installed ({0}):": "\u5df2\u5b89\u88c5\u63d2\u4ef6 ({0}):",
 | 
			
		||||
"Premium plugins:": "\u4f18\u79c0\u63d2\u4ef6\uff1a",
 | 
			
		||||
"Learn more...": "\u4e86\u89e3\u66f4\u591a...",
 | 
			
		||||
"You are using {0}": "\u4f60\u6b63\u5728\u4f7f\u7528 {0}",
 | 
			
		||||
"Plugins": "\u63d2\u4ef6",
 | 
			
		||||
"Handy Shortcuts": "\u5feb\u6377\u952e",
 | 
			
		||||
"Horizontal line": "\u6c34\u5e73\u5206\u5272\u7ebf",
 | 
			
		||||
"Insert\/edit image": "\u63d2\u5165\/\u7f16\u8f91\u56fe\u7247",
 | 
			
		||||
"Image description": "\u56fe\u7247\u63cf\u8ff0",
 | 
			
		||||
"Source": "\u5730\u5740",
 | 
			
		||||
"Dimensions": "\u5927\u5c0f",
 | 
			
		||||
"Constrain proportions": "\u4fdd\u6301\u7eb5\u6a2a\u6bd4",
 | 
			
		||||
"General": "\u666e\u901a",
 | 
			
		||||
"Advanced": "\u9ad8\u7ea7",
 | 
			
		||||
"Style": "\u6837\u5f0f",
 | 
			
		||||
"Vertical space": "\u5782\u76f4\u8fb9\u8ddd",
 | 
			
		||||
"Horizontal space": "\u6c34\u5e73\u8fb9\u8ddd",
 | 
			
		||||
"Border": "\u8fb9\u6846",
 | 
			
		||||
"Insert image": "\u63d2\u5165\u56fe\u7247",
 | 
			
		||||
"Image...": "\u56fe\u7247...",
 | 
			
		||||
"Image list": "\u56fe\u7247\u5217\u8868",
 | 
			
		||||
"Rotate counterclockwise": "\u9006\u65f6\u9488\u65cb\u8f6c",
 | 
			
		||||
"Rotate clockwise": "\u987a\u65f6\u9488\u65cb\u8f6c",
 | 
			
		||||
"Flip vertically": "\u5782\u76f4\u7ffb\u8f6c",
 | 
			
		||||
"Flip horizontally": "\u6c34\u5e73\u7ffb\u8f6c",
 | 
			
		||||
"Edit image": "\u7f16\u8f91\u56fe\u7247",
 | 
			
		||||
"Image options": "\u56fe\u7247\u9009\u9879",
 | 
			
		||||
"Zoom in": "\u653e\u5927",
 | 
			
		||||
"Zoom out": "\u7f29\u5c0f",
 | 
			
		||||
"Crop": "\u88c1\u526a",
 | 
			
		||||
"Resize": "\u8c03\u6574\u5927\u5c0f",
 | 
			
		||||
"Orientation": "\u65b9\u5411",
 | 
			
		||||
"Brightness": "\u4eae\u5ea6",
 | 
			
		||||
"Sharpen": "\u9510\u5316",
 | 
			
		||||
"Contrast": "\u5bf9\u6bd4\u5ea6",
 | 
			
		||||
"Color levels": "\u989c\u8272\u5c42\u6b21",
 | 
			
		||||
"Gamma": "\u4f3d\u9a6c\u503c",
 | 
			
		||||
"Invert": "\u53cd\u8f6c",
 | 
			
		||||
"Apply": "\u5e94\u7528",
 | 
			
		||||
"Back": "\u540e\u9000",
 | 
			
		||||
"Insert date\/time": "\u63d2\u5165\u65e5\u671f\/\u65f6\u95f4",
 | 
			
		||||
"Date\/time": "\u65e5\u671f\/\u65f6\u95f4",
 | 
			
		||||
"Insert\/Edit Link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5",
 | 
			
		||||
"Insert\/edit link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5",
 | 
			
		||||
"Text to display": "\u663e\u793a\u6587\u5b57",
 | 
			
		||||
"Url": "\u5730\u5740",
 | 
			
		||||
"Open link in...": "\u94fe\u63a5\u6253\u5f00\u4f4d\u7f6e...",
 | 
			
		||||
"Current window": "\u5f53\u524d\u7a97\u53e3",
 | 
			
		||||
"None": "\u65e0",
 | 
			
		||||
"New window": "\u5728\u65b0\u7a97\u53e3\u6253\u5f00",
 | 
			
		||||
"Remove link": "\u5220\u9664\u94fe\u63a5",
 | 
			
		||||
"Anchors": "\u951a\u70b9",
 | 
			
		||||
"Link...": "\u94fe\u63a5...",
 | 
			
		||||
"Paste or type a link": "\u7c98\u8d34\u6216\u8f93\u5165\u94fe\u63a5",
 | 
			
		||||
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u4e3a\u90ae\u4ef6\u5730\u5740\uff0c\u9700\u8981\u52a0\u4e0amailto:\u524d\u7f00\u5417\uff1f",
 | 
			
		||||
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u5c5e\u4e8e\u5916\u90e8\u94fe\u63a5\uff0c\u9700\u8981\u52a0\u4e0ahttp:\/\/:\u524d\u7f00\u5417\uff1f",
 | 
			
		||||
"Link list": "\u94fe\u63a5\u5217\u8868",
 | 
			
		||||
"Insert video": "\u63d2\u5165\u89c6\u9891",
 | 
			
		||||
"Insert\/edit video": "\u63d2\u5165\/\u7f16\u8f91\u89c6\u9891",
 | 
			
		||||
"Insert\/edit media": "\u63d2\u5165\/\u7f16\u8f91\u5a92\u4f53",
 | 
			
		||||
"Alternative source": "\u955c\u50cf",
 | 
			
		||||
"Alternative source URL": "\u66ff\u4ee3\u6765\u6e90\u7f51\u5740",
 | 
			
		||||
"Media poster (Image URL)": "\u5c01\u9762(\u56fe\u7247\u5730\u5740)",
 | 
			
		||||
"Paste your embed code below:": "\u5c06\u5185\u5d4c\u4ee3\u7801\u7c98\u8d34\u5728\u4e0b\u9762:",
 | 
			
		||||
"Embed": "\u5185\u5d4c",
 | 
			
		||||
"Media...": "\u591a\u5a92\u4f53...",
 | 
			
		||||
"Nonbreaking space": "\u4e0d\u95f4\u65ad\u7a7a\u683c",
 | 
			
		||||
"Page break": "\u5206\u9875\u7b26",
 | 
			
		||||
"Paste as text": "\u7c98\u8d34\u4e3a\u6587\u672c",
 | 
			
		||||
"Preview": "\u9884\u89c8",
 | 
			
		||||
"Print...": "\u6253\u5370...",
 | 
			
		||||
"Save": "\u4fdd\u5b58",
 | 
			
		||||
"Find": "\u67e5\u627e",
 | 
			
		||||
"Replace with": "\u66ff\u6362\u4e3a",
 | 
			
		||||
"Replace": "\u66ff\u6362",
 | 
			
		||||
"Replace all": "\u5168\u90e8\u66ff\u6362",
 | 
			
		||||
"Previous": "\u4e0a\u4e00\u4e2a",
 | 
			
		||||
"Next": "\u4e0b\u4e00\u4e2a",
 | 
			
		||||
"Find and replace...": "\u67e5\u627e\u5e76\u66ff\u6362...",
 | 
			
		||||
"Could not find the specified string.": "\u672a\u627e\u5230\u641c\u7d22\u5185\u5bb9.",
 | 
			
		||||
"Match case": "\u533a\u5206\u5927\u5c0f\u5199",
 | 
			
		||||
"Find whole words only": "\u5168\u5b57\u5339\u914d",
 | 
			
		||||
"Spell check": "\u62fc\u5199\u68c0\u67e5",
 | 
			
		||||
"Ignore": "\u5ffd\u7565",
 | 
			
		||||
"Ignore all": "\u5168\u90e8\u5ffd\u7565",
 | 
			
		||||
"Finish": "\u5b8c\u6210",
 | 
			
		||||
"Add to Dictionary": "\u6dfb\u52a0\u5230\u5b57\u5178",
 | 
			
		||||
"Insert table": "\u63d2\u5165\u8868\u683c",
 | 
			
		||||
"Table properties": "\u8868\u683c\u5c5e\u6027",
 | 
			
		||||
"Delete table": "\u5220\u9664\u8868\u683c",
 | 
			
		||||
"Cell": "\u5355\u5143\u683c",
 | 
			
		||||
"Row": "\u884c",
 | 
			
		||||
"Column": "\u5217",
 | 
			
		||||
"Cell properties": "\u5355\u5143\u683c\u5c5e\u6027",
 | 
			
		||||
"Merge cells": "\u5408\u5e76\u5355\u5143\u683c",
 | 
			
		||||
"Split cell": "\u62c6\u5206\u5355\u5143\u683c",
 | 
			
		||||
"Insert row before": "\u5728\u4e0a\u65b9\u63d2\u5165",
 | 
			
		||||
"Insert row after": "\u5728\u4e0b\u65b9\u63d2\u5165",
 | 
			
		||||
"Delete row": "\u5220\u9664\u884c",
 | 
			
		||||
"Row properties": "\u884c\u5c5e\u6027",
 | 
			
		||||
"Cut row": "\u526a\u5207\u884c",
 | 
			
		||||
"Copy row": "\u590d\u5236\u884c",
 | 
			
		||||
"Paste row before": "\u7c98\u8d34\u5230\u4e0a\u65b9",
 | 
			
		||||
"Paste row after": "\u7c98\u8d34\u5230\u4e0b\u65b9",
 | 
			
		||||
"Insert column before": "\u5728\u5de6\u4fa7\u63d2\u5165",
 | 
			
		||||
"Insert column after": "\u5728\u53f3\u4fa7\u63d2\u5165",
 | 
			
		||||
"Delete column": "\u5220\u9664\u5217",
 | 
			
		||||
"Cols": "\u5217",
 | 
			
		||||
"Rows": "\u884c",
 | 
			
		||||
"Width": "\u5bbd",
 | 
			
		||||
"Height": "\u9ad8",
 | 
			
		||||
"Cell spacing": "\u5355\u5143\u683c\u5916\u95f4\u8ddd",
 | 
			
		||||
"Cell padding": "\u5355\u5143\u683c\u5185\u8fb9\u8ddd",
 | 
			
		||||
"Show caption": "\u663e\u793a\u6807\u9898",
 | 
			
		||||
"Left": "\u5de6\u5bf9\u9f50",
 | 
			
		||||
"Center": "\u5c45\u4e2d",
 | 
			
		||||
"Right": "\u53f3\u5bf9\u9f50",
 | 
			
		||||
"Cell type": "\u5355\u5143\u683c\u7c7b\u578b",
 | 
			
		||||
"Scope": "\u8303\u56f4",
 | 
			
		||||
"Alignment": "\u5bf9\u9f50\u65b9\u5f0f",
 | 
			
		||||
"H Align": "\u6c34\u5e73\u5bf9\u9f50",
 | 
			
		||||
"V Align": "\u5782\u76f4\u5bf9\u9f50",
 | 
			
		||||
"Top": "\u9876\u90e8\u5bf9\u9f50",
 | 
			
		||||
"Middle": "\u5782\u76f4\u5c45\u4e2d",
 | 
			
		||||
"Bottom": "\u5e95\u90e8\u5bf9\u9f50",
 | 
			
		||||
"Header cell": "\u8868\u5934\u5355\u5143\u683c",
 | 
			
		||||
"Row group": "\u884c\u7ec4",
 | 
			
		||||
"Column group": "\u5217\u7ec4",
 | 
			
		||||
"Row type": "\u884c\u7c7b\u578b",
 | 
			
		||||
"Header": "\u8868\u5934",
 | 
			
		||||
"Body": "\u8868\u4f53",
 | 
			
		||||
"Footer": "\u8868\u5c3e",
 | 
			
		||||
"Border color": "\u8fb9\u6846\u989c\u8272",
 | 
			
		||||
"Insert template...": "\u63d2\u5165\u6a21\u677f...",
 | 
			
		||||
"Templates": "\u6a21\u677f",
 | 
			
		||||
"Template": "\u6a21\u677f",
 | 
			
		||||
"Text color": "\u6587\u5b57\u989c\u8272",
 | 
			
		||||
"Background color": "\u80cc\u666f\u8272",
 | 
			
		||||
"Custom...": "\u81ea\u5b9a\u4e49...",
 | 
			
		||||
"Custom color": "\u81ea\u5b9a\u4e49\u989c\u8272",
 | 
			
		||||
"No color": "\u65e0",
 | 
			
		||||
"Remove color": "\u79fb\u9664\u989c\u8272",
 | 
			
		||||
"Table of Contents": "\u5185\u5bb9\u5217\u8868",
 | 
			
		||||
"Show blocks": "\u663e\u793a\u533a\u5757\u8fb9\u6846",
 | 
			
		||||
"Show invisible characters": "\u663e\u793a\u4e0d\u53ef\u89c1\u5b57\u7b26",
 | 
			
		||||
"Word count": "\u5b57\u6570",
 | 
			
		||||
"Count": "\u8ba1\u6570",
 | 
			
		||||
"Document": "\u6587\u6863",
 | 
			
		||||
"Selection": "\u9009\u62e9",
 | 
			
		||||
"Words": "\u5355\u8bcd",
 | 
			
		||||
"Words: {0}": "\u5b57\u6570\uff1a{0}",
 | 
			
		||||
"{0} words": "{0} \u5b57",
 | 
			
		||||
"File": "\u6587\u4ef6",
 | 
			
		||||
"Edit": "\u7f16\u8f91",
 | 
			
		||||
"Insert": "\u63d2\u5165",
 | 
			
		||||
"View": "\u89c6\u56fe",
 | 
			
		||||
"Format": "\u683c\u5f0f",
 | 
			
		||||
"Table": "\u8868\u683c",
 | 
			
		||||
"Tools": "\u5de5\u5177",
 | 
			
		||||
"Powered by {0}": "\u7531{0}\u9a71\u52a8",
 | 
			
		||||
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\u5728\u7f16\u8f91\u533a\u6309ALT-F9\u6253\u5f00\u83dc\u5355\uff0c\u6309ALT-F10\u6253\u5f00\u5de5\u5177\u680f\uff0c\u6309ALT-0\u67e5\u770b\u5e2e\u52a9",
 | 
			
		||||
"Image title": "\u56fe\u7247\u6807\u9898",
 | 
			
		||||
"Border width": "\u8fb9\u6846\u5bbd\u5ea6",
 | 
			
		||||
"Border style": "\u8fb9\u6846\u6837\u5f0f",
 | 
			
		||||
"Error": "\u9519\u8bef",
 | 
			
		||||
"Warn": "\u8b66\u544a",
 | 
			
		||||
"Valid": "\u6709\u6548",
 | 
			
		||||
"To open the popup, press Shift+Enter": "\u6309Shitf+Enter\u952e\u6253\u5f00\u5bf9\u8bdd\u6846",
 | 
			
		||||
"Rich Text Area. Press ALT-0 for help.": "\u7f16\u8f91\u533a\u3002\u6309Alt+0\u952e\u6253\u5f00\u5e2e\u52a9\u3002",
 | 
			
		||||
"System Font": "\u7cfb\u7edf\u5b57\u4f53",
 | 
			
		||||
"Failed to upload image: {0}": "\u56fe\u7247\u4e0a\u4f20\u5931\u8d25: {0}",
 | 
			
		||||
"Failed to load plugin: {0} from url {1}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25: {0} \u6765\u81ea\u94fe\u63a5 {1}",
 | 
			
		||||
"Failed to load plugin url: {0}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25 \u94fe\u63a5: {0}",
 | 
			
		||||
"Failed to initialize plugin: {0}": "\u63d2\u4ef6\u521d\u59cb\u5316\u5931\u8d25: {0}",
 | 
			
		||||
"example": "\u793a\u4f8b",
 | 
			
		||||
"Search": "\u641c\u7d22",
 | 
			
		||||
"All": "\u5168\u90e8",
 | 
			
		||||
"Currency": "\u8d27\u5e01",
 | 
			
		||||
"Text": "\u6587\u5b57",
 | 
			
		||||
"Quotations": "\u5f15\u7528",
 | 
			
		||||
"Mathematical": "\u6570\u5b66",
 | 
			
		||||
"Extended Latin": "\u62c9\u4e01\u8bed\u6269\u5145",
 | 
			
		||||
"Symbols": "\u7b26\u53f7",
 | 
			
		||||
"Arrows": "\u7bad\u5934",
 | 
			
		||||
"User Defined": "\u81ea\u5b9a\u4e49",
 | 
			
		||||
"dollar sign": "\u7f8e\u5143\u7b26\u53f7",
 | 
			
		||||
"currency sign": "\u8d27\u5e01\u7b26\u53f7",
 | 
			
		||||
"euro-currency sign": "\u6b27\u5143\u7b26\u53f7",
 | 
			
		||||
"colon sign": "\u5192\u53f7",
 | 
			
		||||
"cruzeiro sign": "\u514b\u9c81\u8d5b\u7f57\u5e01\u7b26\u53f7",
 | 
			
		||||
"french franc sign": "\u6cd5\u90ce\u7b26\u53f7",
 | 
			
		||||
"lira sign": "\u91cc\u62c9\u7b26\u53f7",
 | 
			
		||||
"mill sign": "\u5bc6\u5c14\u7b26\u53f7",
 | 
			
		||||
"naira sign": "\u5948\u62c9\u7b26\u53f7",
 | 
			
		||||
"peseta sign": "\u6bd4\u585e\u5854\u7b26\u53f7",
 | 
			
		||||
"rupee sign": "\u5362\u6bd4\u7b26\u53f7",
 | 
			
		||||
"won sign": "\u97e9\u5143\u7b26\u53f7",
 | 
			
		||||
"new sheqel sign": "\u65b0\u8c22\u514b\u5c14\u7b26\u53f7",
 | 
			
		||||
"dong sign": "\u8d8a\u5357\u76fe\u7b26\u53f7",
 | 
			
		||||
"kip sign": "\u8001\u631d\u57fa\u666e\u7b26\u53f7",
 | 
			
		||||
"tugrik sign": "\u56fe\u683c\u91cc\u514b\u7b26\u53f7",
 | 
			
		||||
"drachma sign": "\u5fb7\u62c9\u514b\u9a6c\u7b26\u53f7",
 | 
			
		||||
"german penny symbol": "\u5fb7\u56fd\u4fbf\u58eb\u7b26\u53f7",
 | 
			
		||||
"peso sign": "\u6bd4\u7d22\u7b26\u53f7",
 | 
			
		||||
"guarani sign": "\u74dc\u62c9\u5c3c\u7b26\u53f7",
 | 
			
		||||
"austral sign": "\u6fb3\u5143\u7b26\u53f7",
 | 
			
		||||
"hryvnia sign": "\u683c\u91cc\u592b\u5c3c\u4e9a\u7b26\u53f7",
 | 
			
		||||
"cedi sign": "\u585e\u5730\u7b26\u53f7",
 | 
			
		||||
"livre tournois sign": "\u91cc\u5f17\u5f17\u5c14\u7b26\u53f7",
 | 
			
		||||
"spesmilo sign": "spesmilo\u7b26\u53f7",
 | 
			
		||||
"tenge sign": "\u575a\u6208\u7b26\u53f7",
 | 
			
		||||
"indian rupee sign": "\u5370\u5ea6\u5362\u6bd4",
 | 
			
		||||
"turkish lira sign": "\u571f\u8033\u5176\u91cc\u62c9",
 | 
			
		||||
"nordic mark sign": "\u5317\u6b27\u9a6c\u514b",
 | 
			
		||||
"manat sign": "\u9a6c\u7eb3\u7279\u7b26\u53f7",
 | 
			
		||||
"ruble sign": "\u5362\u5e03\u7b26\u53f7",
 | 
			
		||||
"yen character": "\u65e5\u5143\u5b57\u6837",
 | 
			
		||||
"yuan character": "\u4eba\u6c11\u5e01\u5143\u5b57\u6837",
 | 
			
		||||
"yuan character, in hong kong and taiwan": "\u5143\u5b57\u6837\uff08\u6e2f\u53f0\u5730\u533a\uff09",
 | 
			
		||||
"yen\/yuan character variant one": "\u5143\u5b57\u6837\uff08\u5927\u5199\uff09",
 | 
			
		||||
"Loading emoticons...": "\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7...",
 | 
			
		||||
"Could not load emoticons": "\u4e0d\u80fd\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7",
 | 
			
		||||
"People": "\u4eba\u7c7b",
 | 
			
		||||
"Animals and Nature": "\u52a8\u7269\u548c\u81ea\u7136",
 | 
			
		||||
"Food and Drink": "\u98df\u7269\u548c\u996e\u54c1",
 | 
			
		||||
"Activity": "\u6d3b\u52a8",
 | 
			
		||||
"Travel and Places": "\u65c5\u6e38\u548c\u5730\u70b9",
 | 
			
		||||
"Objects": "\u7269\u4ef6",
 | 
			
		||||
"Flags": "\u65d7\u5e1c",
 | 
			
		||||
"Characters": "\u5b57\u7b26",
 | 
			
		||||
"Characters (no spaces)": "\u5b57\u7b26(\u65e0\u7a7a\u683c)",
 | 
			
		||||
"{0} characters": "{0} \u4e2a\u5b57\u7b26",
 | 
			
		||||
"Error: Form submit field collision.": "\u9519\u8bef: \u8868\u5355\u63d0\u4ea4\u5b57\u6bb5\u51b2\u7a81\u3002",
 | 
			
		||||
"Error: No form element found.": "\u9519\u8bef: \u6ca1\u6709\u8868\u5355\u63a7\u4ef6\u3002",
 | 
			
		||||
"Update": "\u66f4\u65b0",
 | 
			
		||||
"Color swatch": "\u989c\u8272\u6837\u672c",
 | 
			
		||||
"Turquoise": "\u9752\u7eff\u8272",
 | 
			
		||||
"Green": "\u7eff\u8272",
 | 
			
		||||
"Blue": "\u84dd\u8272",
 | 
			
		||||
"Purple": "\u7d2b\u8272",
 | 
			
		||||
"Navy Blue": "\u6d77\u519b\u84dd",
 | 
			
		||||
"Dark Turquoise": "\u6df1\u84dd\u7eff\u8272",
 | 
			
		||||
"Dark Green": "\u6df1\u7eff\u8272",
 | 
			
		||||
"Medium Blue": "\u4e2d\u84dd\u8272",
 | 
			
		||||
"Medium Purple": "\u4e2d\u7d2b\u8272",
 | 
			
		||||
"Midnight Blue": "\u6df1\u84dd\u8272",
 | 
			
		||||
"Yellow": "\u9ec4\u8272",
 | 
			
		||||
"Orange": "\u6a59\u8272",
 | 
			
		||||
"Red": "\u7ea2\u8272",
 | 
			
		||||
"Light Gray": "\u6d45\u7070\u8272",
 | 
			
		||||
"Gray": "\u7070\u8272",
 | 
			
		||||
"Dark Yellow": "\u6697\u9ec4\u8272",
 | 
			
		||||
"Dark Orange": "\u6df1\u6a59\u8272",
 | 
			
		||||
"Dark Red": "\u6df1\u7ea2\u8272",
 | 
			
		||||
"Medium Gray": "\u4e2d\u7070\u8272",
 | 
			
		||||
"Dark Gray": "\u6df1\u7070\u8272",
 | 
			
		||||
"Light Green": "\u6d45\u7eff\u8272",
 | 
			
		||||
"Light Yellow": "\u6d45\u9ec4\u8272",
 | 
			
		||||
"Light Red": "\u6d45\u7ea2\u8272",
 | 
			
		||||
"Light Purple": "\u6d45\u7d2b\u8272",
 | 
			
		||||
"Light Blue": "\u6d45\u84dd\u8272",
 | 
			
		||||
"Dark Purple": "\u6df1\u7d2b\u8272",
 | 
			
		||||
"Dark Blue": "\u6df1\u84dd\u8272",
 | 
			
		||||
"Black": "\u9ed1\u8272",
 | 
			
		||||
"White": "\u767d\u8272",
 | 
			
		||||
"Switch to or from fullscreen mode": "\u5207\u6362\u5168\u5c4f\u6a21\u5f0f",
 | 
			
		||||
"Open help dialog": "\u6253\u5f00\u5e2e\u52a9\u5bf9\u8bdd\u6846",
 | 
			
		||||
"history": "\u5386\u53f2",
 | 
			
		||||
"styles": "\u6837\u5f0f",
 | 
			
		||||
"formatting": "\u683c\u5f0f\u5316",
 | 
			
		||||
"alignment": "\u5bf9\u9f50",
 | 
			
		||||
"indentation": "\u7f29\u8fdb",
 | 
			
		||||
"permanent pen": "\u8bb0\u53f7\u7b14",
 | 
			
		||||
"comments": "\u5907\u6ce8",
 | 
			
		||||
"Format Painter": "\u683c\u5f0f\u5237",
 | 
			
		||||
"Insert\/edit iframe": "\u63d2\u5165\/\u7f16\u8f91\u6846\u67b6",
 | 
			
		||||
"Capitalization": "\u5927\u5199",
 | 
			
		||||
"lowercase": "\u5c0f\u5199",
 | 
			
		||||
"UPPERCASE": "\u5927\u5199",
 | 
			
		||||
"Title Case": "\u9996\u5b57\u6bcd\u5927\u5199",
 | 
			
		||||
"Permanent Pen Properties": "\u6c38\u4e45\u7b14\u5c5e\u6027",
 | 
			
		||||
"Permanent pen properties...": "\u6c38\u4e45\u7b14\u5c5e\u6027...",
 | 
			
		||||
"Font": "\u5b57\u4f53",
 | 
			
		||||
"Size": "\u5b57\u53f7",
 | 
			
		||||
"More...": "\u66f4\u591a...",
 | 
			
		||||
"Spellcheck Language": "\u62fc\u5199\u68c0\u67e5\u8bed\u8a00",
 | 
			
		||||
"Select...": "\u9009\u62e9...",
 | 
			
		||||
"Preferences": "\u9996\u9009\u9879",
 | 
			
		||||
"Yes": "\u662f",
 | 
			
		||||
"No": "\u5426",
 | 
			
		||||
"Keyboard Navigation": "\u952e\u76d8\u6307\u5f15",
 | 
			
		||||
"Version": "\u7248\u672c",
 | 
			
		||||
"Anchor": "\u951a\u70b9",
 | 
			
		||||
"Special character": "\u7279\u6b8a\u7b26\u53f7",
 | 
			
		||||
"Code sample": "\u4ee3\u7801\u793a\u4f8b",
 | 
			
		||||
"Color": "\u989c\u8272",
 | 
			
		||||
"Emoticons": "\u8868\u60c5",
 | 
			
		||||
"Document properties": "\u6587\u6863\u5c5e\u6027",
 | 
			
		||||
"Image": "\u56fe\u7247",
 | 
			
		||||
"Insert link": "\u63d2\u5165\u94fe\u63a5",
 | 
			
		||||
"Target": "\u6253\u5f00\u65b9\u5f0f",
 | 
			
		||||
"Link": "\u94fe\u63a5",
 | 
			
		||||
"Poster": "\u5c01\u9762",
 | 
			
		||||
"Media": "\u5a92\u4f53",
 | 
			
		||||
"Print": "\u6253\u5370",
 | 
			
		||||
"Prev": "\u4e0a\u4e00\u4e2a",
 | 
			
		||||
"Find and replace": "\u67e5\u627e\u548c\u66ff\u6362",
 | 
			
		||||
"Whole words": "\u5168\u5b57\u5339\u914d",
 | 
			
		||||
"Spellcheck": "\u62fc\u5199\u68c0\u67e5",
 | 
			
		||||
"Caption": "\u6807\u9898",
 | 
			
		||||
"Insert template": "\u63d2\u5165\u6a21\u677f"
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										28
									
								
								src/utils/loadBeautifier.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/utils/loadBeautifier.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
import loadScript from './loadScript'
 | 
			
		||||
import ELEMENT from 'element-ui'
 | 
			
		||||
import pluginsConfig from './pluginsConfig'
 | 
			
		||||
 | 
			
		||||
let beautifierObj
 | 
			
		||||
 | 
			
		||||
export default function loadBeautifier(cb) {
 | 
			
		||||
  const { beautifierUrl } = pluginsConfig
 | 
			
		||||
  if (beautifierObj) {
 | 
			
		||||
    cb(beautifierObj)
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const loading = ELEMENT.Loading.service({
 | 
			
		||||
    fullscreen: true,
 | 
			
		||||
    lock: true,
 | 
			
		||||
    text: '格式化资源加载中...',
 | 
			
		||||
    spinner: 'el-icon-loading',
 | 
			
		||||
    background: 'rgba(255, 255, 255, 0.5)'
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  loadScript(beautifierUrl, () => {
 | 
			
		||||
    loading.close()
 | 
			
		||||
    // eslint-disable-next-line no-undef
 | 
			
		||||
    beautifierObj = beautifier
 | 
			
		||||
    cb(beautifierObj)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								src/utils/loadMonaco.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/utils/loadMonaco.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
import loadScript from './loadScript'
 | 
			
		||||
import ELEMENT from 'element-ui'
 | 
			
		||||
import pluginsConfig from './pluginsConfig'
 | 
			
		||||
 | 
			
		||||
// monaco-editor单例
 | 
			
		||||
let monacoEidtor
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 动态加载monaco-editor cdn资源
 | 
			
		||||
 * @param {Function} cb 回调,必填
 | 
			
		||||
 */
 | 
			
		||||
export default function loadMonaco(cb) {
 | 
			
		||||
  if (monacoEidtor) {
 | 
			
		||||
    cb(monacoEidtor)
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const { monacoEditorUrl: vs } = pluginsConfig
 | 
			
		||||
 | 
			
		||||
  // 使用element ui实现加载提示
 | 
			
		||||
  const loading = ELEMENT.Loading.service({
 | 
			
		||||
    fullscreen: true,
 | 
			
		||||
    lock: true,
 | 
			
		||||
    text: '编辑器资源初始化中...',
 | 
			
		||||
    spinner: 'el-icon-loading',
 | 
			
		||||
    background: 'rgba(255, 255, 255, 0.5)'
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  !window.require && (window.require = {})
 | 
			
		||||
  !window.require.paths && (window.require.paths = {})
 | 
			
		||||
  window.require.paths.vs = vs
 | 
			
		||||
 | 
			
		||||
  loadScript(`${vs}/loader.js`, () => {
 | 
			
		||||
    window.require(['vs/editor/editor.main'], () => {
 | 
			
		||||
      loading.close()
 | 
			
		||||
      monacoEidtor = window.monaco
 | 
			
		||||
      cb(monacoEidtor)
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										60
									
								
								src/utils/loadScript.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/utils/loadScript.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
			
		||||
const callbacks = {}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 加载一个远程脚本
 | 
			
		||||
 * @param {String} src 一个远程脚本
 | 
			
		||||
 * @param {Function} callback 回调
 | 
			
		||||
 */
 | 
			
		||||
function loadScript(src, callback) {
 | 
			
		||||
  const existingScript = document.getElementById(src)
 | 
			
		||||
  const cb = callback || (() => {})
 | 
			
		||||
  if (!existingScript) {
 | 
			
		||||
    callbacks[src] = []
 | 
			
		||||
    const $script = document.createElement('script')
 | 
			
		||||
    $script.src = src
 | 
			
		||||
    $script.id = src
 | 
			
		||||
    $script.async = 1
 | 
			
		||||
    document.body.appendChild($script)
 | 
			
		||||
    const onEnd = 'onload' in $script ? stdOnEnd.bind($script) : ieOnEnd.bind($script)
 | 
			
		||||
    onEnd($script)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  callbacks[src].push(cb)
 | 
			
		||||
 | 
			
		||||
  function stdOnEnd(script) {
 | 
			
		||||
    script.onload = () => {
 | 
			
		||||
      this.onerror = this.onload = null
 | 
			
		||||
      callbacks[src].forEach(item => {
 | 
			
		||||
        item(null, script)
 | 
			
		||||
      })
 | 
			
		||||
      delete callbacks[src]
 | 
			
		||||
    }
 | 
			
		||||
    script.onerror = () => {
 | 
			
		||||
      this.onerror = this.onload = null
 | 
			
		||||
      cb(new Error(`Failed to load ${src}`), script)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function ieOnEnd(script) {
 | 
			
		||||
    script.onreadystatechange = () => {
 | 
			
		||||
      if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
 | 
			
		||||
      this.onreadystatechange = null
 | 
			
		||||
      callbacks[src].forEach(item => {
 | 
			
		||||
        item(null, script)
 | 
			
		||||
      })
 | 
			
		||||
      delete callbacks[src]
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 顺序加载一组远程脚本
 | 
			
		||||
 * @param {Array} list 一组远程脚本
 | 
			
		||||
 * @param {Function} cb 回调
 | 
			
		||||
 */
 | 
			
		||||
export function loadScriptQueue(list, cb) {
 | 
			
		||||
  const first = list.shift()
 | 
			
		||||
  list.length ? loadScript(first, () => loadScriptQueue(list, cb)) : loadScript(first, cb)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default loadScript
 | 
			
		||||
							
								
								
									
										29
									
								
								src/utils/loadTinymce.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/utils/loadTinymce.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
import loadScript from './loadScript'
 | 
			
		||||
import ELEMENT from 'element-ui'
 | 
			
		||||
import pluginsConfig from './pluginsConfig'
 | 
			
		||||
 | 
			
		||||
let tinymceObj
 | 
			
		||||
 | 
			
		||||
export default function loadTinymce(cb) {
 | 
			
		||||
  const { tinymceUrl } = pluginsConfig
 | 
			
		||||
 | 
			
		||||
  if (tinymceObj) {
 | 
			
		||||
    cb(tinymceObj)
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const loading = ELEMENT.Loading.service({
 | 
			
		||||
    fullscreen: true,
 | 
			
		||||
    lock: true,
 | 
			
		||||
    text: '富文本资源加载中...',
 | 
			
		||||
    spinner: 'el-icon-loading',
 | 
			
		||||
    background: 'rgba(255, 255, 255, 0.5)'
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  loadScript(tinymceUrl, () => {
 | 
			
		||||
    loading.close()
 | 
			
		||||
    // eslint-disable-next-line no-undef
 | 
			
		||||
    tinymceObj = tinymce
 | 
			
		||||
    cb(tinymceObj)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								src/utils/pluginsConfig.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/utils/pluginsConfig.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
const CDN = 'https://lib.baomitu.com/' // CDN Homepage: https://cdn.baomitu.com/
 | 
			
		||||
const publicPath = process.env.BASE_URL
 | 
			
		||||
 | 
			
		||||
function splicingPluginUrl(PluginName, version, fileName) {
 | 
			
		||||
  return `${CDN}${PluginName}/${version}/${fileName}`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  beautifierUrl: splicingPluginUrl('js-beautify', '1.13.5', 'beautifier.min.js'),
 | 
			
		||||
  // monacoEditorUrl: splicingPluginUrl('monaco-editor', '0.19.3', 'min/vs'), // 使用 monaco-editor CDN 链接
 | 
			
		||||
  monacoEditorUrl: `${publicPath}libs/monaco-editor/vs`, // 使用 monaco-editor 本地代码
 | 
			
		||||
  tinymceUrl: splicingPluginUrl('tinymce', '5.7.0', 'tinymce.min.js')
 | 
			
		||||
}
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 * @Author: zwq
 | 
			
		||||
 * @Date: 2021-07-19 15:18:30
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @LastEditTime: 2024-03-28 15:28:07
 | 
			
		||||
 * @LastEditTime: 2024-03-29 16:49:00
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
<template>
 | 
			
		||||
@@ -16,11 +16,11 @@
 | 
			
		||||
      许昌安彩AGV原片周转看板
 | 
			
		||||
      <h3 class="unit">单位:河南汇融数字科技有限公司</h3>
 | 
			
		||||
      <h3 class="time">{{ times }}</h3>
 | 
			
		||||
      <el-button type="text" class="title-button" :style="{ right: 18 + 'px', top: 26 + 'px', fontSize: '32px' }"
 | 
			
		||||
      <!-- <el-button type="text" class="title-button" :style="{ right: 18 + 'px', top: 26 + 'px', fontSize: '32px' }"
 | 
			
		||||
        @click="changeFullScreen">
 | 
			
		||||
        <svg-icon width="32" height="32" v-if="isFullScreen" icon-class="unFullScreenView" />
 | 
			
		||||
        <svg-icon width="32" height="32" v-else icon-class="fullScreenView" />
 | 
			
		||||
      </el-button>
 | 
			
		||||
      </el-button> -->
 | 
			
		||||
    </el-row>
 | 
			
		||||
    <el-row class="container-main flex-col" type="flex">
 | 
			
		||||
      <el-row :style="{ padding: '0 ' + 9 + 'px' }" :gutter="15 * beilv" type="flex" class="flex-1">
 | 
			
		||||
@@ -35,13 +35,15 @@
 | 
			
		||||
          <base-container :beilv="1" :size="'eqStatus'" :title="'周转进度'" :title-icon="'order'" :back="'energy'">
 | 
			
		||||
            <div class="order" style="width:100%; overflow: hidden scroll;height: 350px;">
 | 
			
		||||
              <el-row v-for="op in orderProcessList" :key="op.id" style="margin-bottom: 1em">
 | 
			
		||||
                <p v-if="op.outRate === 1" class="now-secondary-title" style="color:#4679FD">
 | 
			
		||||
                <!-- <p v-if="op.outRate === 1" class="now-secondary-title"
 | 
			
		||||
                  style="font-size: 14px; opacity: calc(.6);color:#4679FD">
 | 
			
		||||
                  <i class="el-icon-check" />
 | 
			
		||||
                  {{ op.name }}
 | 
			
		||||
                </p>
 | 
			
		||||
                <p v-else class="now-secondary-title">{{ op.name }}</p>
 | 
			
		||||
                <el-progress :stroke-width="10" define-back-color="rgba(32, 57, 96, 1)" text-color="white"
 | 
			
		||||
                  :percentage="op.outRate * 100" class="custom-progress-bar" />
 | 
			
		||||
                </p> -->
 | 
			
		||||
                <!-- <p class="now-secondary-title">{{ op.name }}</p> -->
 | 
			
		||||
                <p  class="now-secondary-title" style="font-size: 14px;opacity: calc(.6);">{{ op.name }}</p>
 | 
			
		||||
                <el-progress style="width: 910px;" text-color="rgba(255, 255, 255, .6)" :stroke-width="10"
 | 
			
		||||
                  define-back-color="rgba(32, 57, 96, 1)" :percentage="op.outRate * 100" class="custom-progress-bar" />
 | 
			
		||||
              </el-row>
 | 
			
		||||
            </div>
 | 
			
		||||
          </base-container>
 | 
			
		||||
@@ -496,7 +498,7 @@ export default {
 | 
			
		||||
        seconds = "0" + seconds;
 | 
			
		||||
      }
 | 
			
		||||
      //拼接格式化当前时间
 | 
			
		||||
      this.times = year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds;
 | 
			
		||||
      this.times = year + "." + month + "." + day + " " + hours + ":" + minutes + ":" + seconds;
 | 
			
		||||
    },
 | 
			
		||||
    windowWidth(value) {
 | 
			
		||||
      this.clientWidth = value
 | 
			
		||||
@@ -530,11 +532,6 @@ export default {
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.visual-container {
 | 
			
		||||
  width: 1920px;
 | 
			
		||||
  height: 1080px;
 | 
			
		||||
@@ -556,7 +553,7 @@ export default {
 | 
			
		||||
          top: 25px;
 | 
			
		||||
          color: rgba(255, 255, 255, 0.80);
 | 
			
		||||
          font-size: 20px;
 | 
			
		||||
          letter-spacing: 0px;
 | 
			
		||||
          letter-spacing: 1px;
 | 
			
		||||
        }
 | 
			
		||||
        .time {
 | 
			
		||||
          position: absolute;
 | 
			
		||||
@@ -564,7 +561,7 @@ export default {
 | 
			
		||||
            top: 25px;
 | 
			
		||||
          color: rgba(255, 255, 255, 0.80);
 | 
			
		||||
          font-size: 20px;
 | 
			
		||||
          letter-spacing: 0px;
 | 
			
		||||
          letter-spacing: .72px;
 | 
			
		||||
        }
 | 
			
		||||
    .title-button {
 | 
			
		||||
      color: #00fff0;
 | 
			
		||||
@@ -607,6 +604,12 @@ export default {
 | 
			
		||||
::v-deep .el-progress-bar__inner {
 | 
			
		||||
  background-color: unset;
 | 
			
		||||
  background-image: linear-gradient(to right, #4573fe, #47f8dc);
 | 
			
		||||
}
 | 
			
		||||
::v-deep .el-progress__text {
 | 
			
		||||
  margin-top: -70px;
 | 
			
		||||
  margin-left: 820px;
 | 
			
		||||
  // background-color: unset;
 | 
			
		||||
  // background-image: linear-gradient(to right, #4573fe, #47f8dc);
 | 
			
		||||
}
 | 
			
		||||
 .visual-select {
 | 
			
		||||
   position: absolute;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
<!--
 | 
			
		||||
 * @Author: zhp
 | 
			
		||||
 * @Date: 2024-01-29 16:50:26
 | 
			
		||||
 * @LastEditTime: 2024-03-28 16:35:49
 | 
			
		||||
 * @LastEditTime: 2024-04-02 15:01:40
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
@@ -17,11 +17,11 @@
 | 
			
		||||
      许昌安彩冷端看板
 | 
			
		||||
      <h3 class="unit">单位:河南汇融数字科技有限公司</h3>
 | 
			
		||||
      <h3 class="time">{{ times }}</h3>
 | 
			
		||||
      <el-button type="text" class="title-button" :style="{ right: 18 + 'px', top: 26 + 'px',fontSize:'32px'}"
 | 
			
		||||
      <!-- <el-button type="text" class="title-button" :style="{ right: 18 + 'px', top: 26 + 'px',fontSize:'32px'}"
 | 
			
		||||
        @click="changeFullScreen">
 | 
			
		||||
        <svg-icon width="32" height="32" v-if="isFullScreen" icon-class="unFullScreenView" />
 | 
			
		||||
        <svg-icon width="32" height="32" v-else icon-class="fullScreenView" />
 | 
			
		||||
      </el-button>
 | 
			
		||||
      </el-button> -->
 | 
			
		||||
    </el-row>
 | 
			
		||||
    <el-row class="container-main flex-col" type="flex">
 | 
			
		||||
      <el-row :style="{ padding: '0 ' + 9 + 'px' }" :gutter="15" type="flex" class="flex-1">
 | 
			
		||||
@@ -40,6 +40,12 @@
 | 
			
		||||
              <top-radio-group />
 | 
			
		||||
            </div> -->
 | 
			
		||||
            <!-- 像下面这样表格里的limit值,也许可以用js动态计算出来 -->
 | 
			
		||||
            <div v-if="coldDetData" class="myLegend">
 | 
			
		||||
              <div class="barLegend"></div>
 | 
			
		||||
              <h4 class="barText">产线产量</h4>
 | 
			
		||||
              <div class="barCircle"></div>
 | 
			
		||||
              <h4 class="barCircleText">产线良品率</h4>
 | 
			
		||||
            </div>
 | 
			
		||||
            <double-y-chart ref="productChart" :id="'doubleYChart'" :name-list="cxNameList" :data-list="cxDataList"
 | 
			
		||||
              :height="359" :show-legend="true" />
 | 
			
		||||
          </base-container>
 | 
			
		||||
@@ -64,11 +70,11 @@
 | 
			
		||||
            </div> -->
 | 
			
		||||
            <!-- <el-row :gutter="9"> -->
 | 
			
		||||
            <!-- <el-col :style="{ margin: 8 + 'px' + ' 0' }" :span="24"> -->
 | 
			
		||||
            <pile-bar-chart style="margin-bottom: -15px" ref="firstPileChart" :height="90" />
 | 
			
		||||
            <second-pile-bar-chart style="margin-bottom: -15px" id=" 'second' " ref="secondPileChart" :height="90" />
 | 
			
		||||
            <third-pile-bar-chart style="margin-bottom: -15px" id=" 'third' " ref="thirdPileChart" :height="90" />
 | 
			
		||||
            <fourth-pile-bar-chart style="margin-bottom: -15px" id=" 'fourth' " ref="fourthPileChart" :height="90" />
 | 
			
		||||
            <fifth-pile-bar-chart style="margin-bottom: -15px" id=" 'fifth' " ref="fifthPileChart" :height="100" />
 | 
			
		||||
            <pile-bar-chart id=" 'one' " style="margin-top: -5px;" ref="firstPileChart" :height="80" />
 | 
			
		||||
            <second-pile-bar-chart id=" 'second' " ref="secondPileChart" :height="90" />
 | 
			
		||||
            <third-pile-bar-chart id=" 'third' " ref="thirdPileChart" :height="90" />
 | 
			
		||||
            <fourth-pile-bar-chart id=" 'fourth' " ref="fourthPileChart" :height="90" />
 | 
			
		||||
            <fifth-pile-bar-chart style="margin-top: -5px;" id=" 'fifth' " ref="fifthPileChart" :height="90" />
 | 
			
		||||
            <!-- <pile-bar-chart ref="secondPileChart"
 | 
			
		||||
              :height="90" />
 | 
			
		||||
            <pile-bar-chart ref="thirdPileChart"
 | 
			
		||||
@@ -244,6 +250,7 @@ export default {
 | 
			
		||||
      funWs: undefined,
 | 
			
		||||
      SJGws: undefined,
 | 
			
		||||
      funWsData: {},
 | 
			
		||||
      coldDetData:[],
 | 
			
		||||
      SJGWsData: {},
 | 
			
		||||
      cxNameList:[],
 | 
			
		||||
      cxDataList:[],
 | 
			
		||||
@@ -314,85 +321,7 @@ export default {
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  mounted() {
 | 
			
		||||
    let nameList = []
 | 
			
		||||
    let nameWasteList = []
 | 
			
		||||
    let topNameList = []
 | 
			
		||||
    let productList = []
 | 
			
		||||
    let wasteList = []
 | 
			
		||||
    let yieldList = []
 | 
			
		||||
    // let sumAreaList = []
 | 
			
		||||
    // let yieldList = []
 | 
			
		||||
    // this.cutTableDataList =
 | 
			
		||||
    let coldDetData = [
 | 
			
		||||
      {
 | 
			
		||||
        "first": 0.8834,
 | 
			
		||||
        "lineName": "Y61",
 | 
			
		||||
        "product": 0.8834,
 | 
			
		||||
        "productArea": 35069.28,
 | 
			
		||||
        "second": 0,
 | 
			
		||||
        'sumArea': 38400,
 | 
			
		||||
        'wastArea': 3330.72,
 | 
			
		||||
        "yield": 0.9133
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "first": 0.847,
 | 
			
		||||
        "lineName": "Y62",
 | 
			
		||||
        "product": 0.847,
 | 
			
		||||
        "productArea": 26765.46,
 | 
			
		||||
        "second": 0,
 | 
			
		||||
        'sumArea': 1111111,
 | 
			
		||||
        'wastArea': 22222,
 | 
			
		||||
        "yield": 0.9133
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "first": 0.8668,
 | 
			
		||||
        "lineName": "Y63",
 | 
			
		||||
        "product": 0.8668,
 | 
			
		||||
        "productArea": 26448.46,
 | 
			
		||||
        "second": 0,
 | 
			
		||||
        'sumArea': 1111111,
 | 
			
		||||
        'wastArea': 22222,
 | 
			
		||||
        "yield": 0.9133
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "first": 0.9064,
 | 
			
		||||
        "lineName": "Y64",
 | 
			
		||||
        "product": 0.9064,
 | 
			
		||||
        "productArea": 26667.32,
 | 
			
		||||
        "second": 0,
 | 
			
		||||
        'sumArea': 1111111,
 | 
			
		||||
        'wastArea': 22222,
 | 
			
		||||
        "yield": 0.9133
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        "first": 0.8838,
 | 
			
		||||
        "lineName": "Y65",
 | 
			
		||||
        "product": 0.8838,
 | 
			
		||||
        "productArea": 26554.32,
 | 
			
		||||
        "second": 0,
 | 
			
		||||
        'sumArea': 1111111,
 | 
			
		||||
        'wastArea': 22222,
 | 
			
		||||
        "yield": 0.9133
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
    coldDetData.forEach((ele, index) => {
 | 
			
		||||
      nameList.push(ele.lineName)
 | 
			
		||||
      topNameList.push('产线: ' + ele.lineName + '   ' + '总面积:' + ele.sumArea)
 | 
			
		||||
      productList.push(ele.productArea)
 | 
			
		||||
      wasteList.push(ele.wastArea)
 | 
			
		||||
      nameWasteList.push('缺陷面积:' + ele.wastArea)
 | 
			
		||||
      yieldList.push({
 | 
			
		||||
        name: '良品',
 | 
			
		||||
        yield:ele.yield
 | 
			
		||||
      })
 | 
			
		||||
      // sumAreaList.push(ele.sumArea)
 | 
			
		||||
      // yieldList.push((ele.yield * 100).toFixed(3))
 | 
			
		||||
    })
 | 
			
		||||
    this.$refs.firstPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
 | 
			
		||||
    this.$refs.secondPileChart.initChart(nameList, [topNameList[1]], [nameWasteList[1]], [productList[1]], [wasteList[1]])
 | 
			
		||||
    this.$refs.thirdPileChart.initChart(nameList, [topNameList[2]], [nameWasteList[2]], [productList[2]], [wasteList[2]])
 | 
			
		||||
    this.$refs.fourthPileChart.initChart(nameList, [topNameList[3]], [nameWasteList[3]], [productList[3]], [wasteList[3]])
 | 
			
		||||
    this.$refs.fifthPileChart.initChart(nameList, [topNameList[4]], [nameWasteList[4]], [productList[4]], [wasteList[4]])
 | 
			
		||||
    this.getProductData()
 | 
			
		||||
    // this.$refs.productChart.initChart(nameList, yieldList, sumAreaList)
 | 
			
		||||
    this.getTimes()
 | 
			
		||||
    // console.log(moment(this.logoutTime - 28800000).format('HH:mm:ss'));
 | 
			
		||||
@@ -414,39 +343,123 @@ export default {
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    // getData() {
 | 
			
		||||
    //   let detData = [
 | 
			
		||||
    //     {
 | 
			
		||||
    //       name: '1',
 | 
			
		||||
    //       run: '运行',
 | 
			
		||||
    //     },
 | 
			
		||||
    //     {
 | 
			
		||||
    //       name: '2',
 | 
			
		||||
    //       run: '未运行',
 | 
			
		||||
    //     },
 | 
			
		||||
    //     {
 | 
			
		||||
    //       name: '3',
 | 
			
		||||
    //       run: '运行',
 | 
			
		||||
    //     },
 | 
			
		||||
    //     {
 | 
			
		||||
    //       name: '4',
 | 
			
		||||
    //       run: '未运行',
 | 
			
		||||
    //     },
 | 
			
		||||
    //     {
 | 
			
		||||
    //       name: '1',
 | 
			
		||||
    //       run: '运行',
 | 
			
		||||
    //     },
 | 
			
		||||
    //   ]
 | 
			
		||||
    //   this.realEqList = detData.map((item, index) => [
 | 
			
		||||
    //     // console.log(item)
 | 
			
		||||
    //     `<span style="color:rgba(255,255,255,0.5)" >${index + 1 || ''}
 | 
			
		||||
    //         </span>`,
 | 
			
		||||
    //     `<span style="color:rgba(255,255,255,0.5)">${item.name || ''}</span>`,
 | 
			
		||||
    //     `<span style="color:rgba(255,255,255,0.5)"><div style="${item.run == '运行' ? 'box-shadow: 0px 0px 2px 1px #2760FF;width:6px;height:6px;border-radius: 50%;background-color: #2760FF;float:left;margin:10px 10px 0 0 ' : 'box-shadow: 0px 0px 2px 1px #FFBD02;width:6px;height:6px;border-radius: 50%;  background-color: #FFBD02;float:left;margin:10px 10px 0 0 '}"></div>  ${item.run || ''}</span>`,
 | 
			
		||||
    //   ])
 | 
			
		||||
    //     this.realEqConfig.data = this.realEqList
 | 
			
		||||
    //     this.$refs['realEqScrollBoard'].updateRows(this.realEqList)
 | 
			
		||||
    // },
 | 
			
		||||
    getProductData() {
 | 
			
		||||
      let nameList = []
 | 
			
		||||
      let nameWasteList = []
 | 
			
		||||
      let topNameList = []
 | 
			
		||||
      let productList = []
 | 
			
		||||
      let wasteList = []
 | 
			
		||||
      let yieldList = []
 | 
			
		||||
      let sumAreaList = []
 | 
			
		||||
      // let yieldList = []
 | 
			
		||||
      // this.cutTableDataList =
 | 
			
		||||
      this.coldDetData = [
 | 
			
		||||
        {
 | 
			
		||||
          "first": 0.8834,
 | 
			
		||||
          "lineName": "Y61",
 | 
			
		||||
          "product": 0.8834,
 | 
			
		||||
          "productArea": 35069.28,
 | 
			
		||||
          "second": 0,
 | 
			
		||||
          'sumArea': 38400,
 | 
			
		||||
          'wastArea': 3330.72,
 | 
			
		||||
          "yield": 0.9133
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "first": 0.847,
 | 
			
		||||
          "lineName": "Y62",
 | 
			
		||||
          "product": 0.847,
 | 
			
		||||
          "productArea": 26765.46,
 | 
			
		||||
          "second": 0,
 | 
			
		||||
          'sumArea': 1111111,
 | 
			
		||||
          'wastArea': 22222,
 | 
			
		||||
          "yield": 0.9133
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "first": 0.8668,
 | 
			
		||||
          "lineName": "Y63",
 | 
			
		||||
          "product": 0.8668,
 | 
			
		||||
          "productArea": 26448.46,
 | 
			
		||||
          "second": 0,
 | 
			
		||||
          'sumArea': 1111111,
 | 
			
		||||
          'wastArea': 22222,
 | 
			
		||||
          "yield": 0.9133
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "first": 0.9064,
 | 
			
		||||
          "lineName": "Y64",
 | 
			
		||||
          "product": 0.9064,
 | 
			
		||||
          "productArea": 26667.32,
 | 
			
		||||
          "second": 0,
 | 
			
		||||
          'sumArea': 1111111,
 | 
			
		||||
          'wastArea': 22222,
 | 
			
		||||
          "yield": 0.9133
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "first": 0.8838,
 | 
			
		||||
          "lineName": "Y65",
 | 
			
		||||
          "product": 0.8838,
 | 
			
		||||
          "productArea": 26554.32,
 | 
			
		||||
          "second": 0,
 | 
			
		||||
          'sumArea': 1111111,
 | 
			
		||||
          'wastArea': 22222,
 | 
			
		||||
          "yield": 0.9133
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
      this.coldDetData.forEach((ele, index) => {
 | 
			
		||||
        nameList.push(ele.lineName)
 | 
			
		||||
        topNameList.push('产线: ' + ele.lineName + '   ' + '总面积:' + ele.sumArea + '㎡')
 | 
			
		||||
        productList.push(ele.productArea)
 | 
			
		||||
        wasteList.push(ele.wastArea)
 | 
			
		||||
        nameWasteList.push('缺陷面积:' + ele.wastArea + '㎡')
 | 
			
		||||
        // yieldList.push({
 | 
			
		||||
        //   name: '良品',
 | 
			
		||||
        //   yield:ele.yield
 | 
			
		||||
        // })
 | 
			
		||||
        sumAreaList.push(ele.sumArea)
 | 
			
		||||
        yieldList.push((ele.yield * 100).toFixed(3))
 | 
			
		||||
      })
 | 
			
		||||
      this.$nextTick(() => {
 | 
			
		||||
        this.$refs.productChart.initChart(nameList, yieldList, sumAreaList)
 | 
			
		||||
        this.$refs.firstPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
 | 
			
		||||
        this.$refs.secondPileChart.initChart(nameList, [topNameList[1]], [nameWasteList[1]], [productList[1]], [wasteList[1]])
 | 
			
		||||
        this.$refs.thirdPileChart.initChart(nameList, [topNameList[2]], [nameWasteList[2]], [productList[2]], [wasteList[2]])
 | 
			
		||||
        this.$refs.fourthPileChart.initChart(nameList, [topNameList[3]], [nameWasteList[3]], [productList[3]], [wasteList[3]])
 | 
			
		||||
        this.$refs.fifthPileChart.initChart(nameList, [topNameList[4]], [nameWasteList[4]], [productList[4]], [wasteList[4]])
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    getData() {
 | 
			
		||||
      let detData = [
 | 
			
		||||
        {
 | 
			
		||||
          name: '1',
 | 
			
		||||
          run: '运行',
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          name: '2',
 | 
			
		||||
          run: '未运行',
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          name: '3',
 | 
			
		||||
          run: '运行',
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          name: '4',
 | 
			
		||||
          run: '未运行',
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          name: '1',
 | 
			
		||||
          run: '运行',
 | 
			
		||||
        },
 | 
			
		||||
      ]
 | 
			
		||||
      this.realEqList = detData.map((item, index) => [
 | 
			
		||||
        // console.log(item)
 | 
			
		||||
        `<span style="color:rgba(255,255,255,0.5)" >${index + 1 || ''}
 | 
			
		||||
            </span>`,
 | 
			
		||||
        `<span style="color:rgba(255,255,255,0.5)">${item.name || ''}</span>`,
 | 
			
		||||
        `<span style="color:rgba(255,255,255,0.5)"><div style="${item.run == '运行' ? 'box-shadow: 0px 0px 2px 1px #2760FF;width:6px;height:6px;border-radius: 50%;background-color: #2760FF;float:left;margin:10px 10px 0 0 ' : 'box-shadow: 0px 0px 2px 1px #FFBD02;width:6px;height:6px;border-radius: 50%;  background-color: #FFBD02;float:left;margin:10px 10px 0 0 '}"></div>  ${item.run || ''}</span>`,
 | 
			
		||||
      ])
 | 
			
		||||
        this.realEqConfig.data = this.realEqList
 | 
			
		||||
        this.$refs['realEqScrollBoard'].updateRows(this.realEqList)
 | 
			
		||||
    },
 | 
			
		||||
    CutWebsocketClose(e) {
 | 
			
		||||
      this.Cutws.ws.onclose = (event) => { console.log(event );}
 | 
			
		||||
    },
 | 
			
		||||
@@ -495,7 +508,7 @@ export default {
 | 
			
		||||
        seconds = "0" + seconds;
 | 
			
		||||
      }
 | 
			
		||||
      //拼接格式化当前时间
 | 
			
		||||
      this.times = year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds;
 | 
			
		||||
      this.times = year + "." + month + "." + day + " " + hours + ":" + minutes + ":" + seconds;
 | 
			
		||||
    },
 | 
			
		||||
    SJGInitWebSocket() {
 | 
			
		||||
      let date = new Date().valueOf()
 | 
			
		||||
@@ -525,10 +538,9 @@ export default {
 | 
			
		||||
          ])
 | 
			
		||||
        }
 | 
			
		||||
        this.realEqConfig.data = this.realEqList
 | 
			
		||||
        this.$nextTick(() => {
 | 
			
		||||
        // this.$nextTick(() => {
 | 
			
		||||
          this.$refs['realEqScrollBoard'].updateRows(this.realEqList)
 | 
			
		||||
 | 
			
		||||
        })
 | 
			
		||||
        // })
 | 
			
		||||
      };
 | 
			
		||||
      // if (typeof (WebSocket) === 'undefined') {
 | 
			
		||||
      //   alert('您的浏览器不支持WebSocket')
 | 
			
		||||
@@ -572,7 +584,11 @@ export default {
 | 
			
		||||
           <div style = "${(item.product * 100).toFixed(2) < 91 ? 'display:block; color:rgba(255, 209, 96, 1)' : 'display:none;'}">${(item.product * 100).toFixed(2) + '%' || ''}</div>`
 | 
			
		||||
          ])
 | 
			
		||||
          this.cutConfig.data = cutArr
 | 
			
		||||
          this.$refs['cutScrollBoard'].updateRows(cutArr)
 | 
			
		||||
          // this.$nextTick(() => {
 | 
			
		||||
            this.$refs['cutScrollBoard'].updateRows(cutArr)
 | 
			
		||||
          // })
 | 
			
		||||
          // this.cutConfig.data = cutArr
 | 
			
		||||
          // this.$refs['cutScrollBoard'].updateRows(cutArr)
 | 
			
		||||
        } else if (this.cutWsData.type === 'cutting' && this.cutWsData.name === 'chart' && this.cutWsData.dateType === 'day') {
 | 
			
		||||
          let nameList = []
 | 
			
		||||
          let nameWasteList = []
 | 
			
		||||
@@ -581,22 +597,25 @@ export default {
 | 
			
		||||
          let wasteList = []
 | 
			
		||||
          let sumAreaList = []
 | 
			
		||||
          let yieldList = []
 | 
			
		||||
          this.coldDetData = this.cutWsData.coldDetData
 | 
			
		||||
          // this.cutTableDataList =
 | 
			
		||||
          this.cutWsData.coldDetData.forEach((ele, index) => {
 | 
			
		||||
            nameList.push(ele.lineName)
 | 
			
		||||
            topNameList.push('产线: ' + ele.lineName + '   ' + '总面积:' + ele.sumArea)
 | 
			
		||||
            topNameList.push('产线: ' + ele.lineName + '   ' + '总面积:' + ele.sumArea + '㎡')
 | 
			
		||||
            productList.push(ele.productArea)
 | 
			
		||||
            wasteList.push(ele.wastArea)
 | 
			
		||||
            nameWasteList.push('缺陷面积:' + ele.wastArea)
 | 
			
		||||
            nameWasteList.push('缺陷面积:' + ele.wastArea + '㎡')
 | 
			
		||||
            sumAreaList.push(ele.sumArea)
 | 
			
		||||
            yieldList.push(parseFloat((ele.yield * 100).toFixed(3)))
 | 
			
		||||
          })
 | 
			
		||||
          this.$refs.firstPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
 | 
			
		||||
          this.$refs.secondPileChart.initChart(nameList, [topNameList[1]], [nameWasteList[1]], [productList[1]], [wasteList[1]])
 | 
			
		||||
          this.$refs.thirdPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
 | 
			
		||||
          this.$refs.fourthPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
 | 
			
		||||
          this.$refs.fifthPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
 | 
			
		||||
          this.$refs.productChart.initChart(nameList, yieldList, sumAreaList)
 | 
			
		||||
          this.$nextTick(() => {
 | 
			
		||||
            this.$refs.firstPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
 | 
			
		||||
            this.$refs.secondPileChart.initChart(nameList, [topNameList[1]], [nameWasteList[1]], [productList[1]], [wasteList[1]])
 | 
			
		||||
            this.$refs.thirdPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
 | 
			
		||||
            this.$refs.fourthPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
 | 
			
		||||
            this.$refs.fifthPileChart.initChart(nameList, [topNameList[0]], [nameWasteList[0]], [productList[0]], [wasteList[0]])
 | 
			
		||||
            this.$refs.productChart.initChart(nameList, yieldList, sumAreaList)
 | 
			
		||||
          })
 | 
			
		||||
        }
 | 
			
		||||
      };
 | 
			
		||||
      // if (typeof (WebSocket) === 'undefined') {
 | 
			
		||||
@@ -632,17 +651,18 @@ export default {
 | 
			
		||||
          for (let i in this.funWsData.data.annealFanInfo) {
 | 
			
		||||
            index++,
 | 
			
		||||
              arr.push([
 | 
			
		||||
                `
 | 
			
		||||
          <span style="color:rgba(255,255,255,0.5)" >${index || ''}
 | 
			
		||||
                `<span style="color:rgba(255,255,255,0.5)" >${index || ''}
 | 
			
		||||
            </span>`,
 | 
			
		||||
                `<span style="color:rgba(255,255,255,0.5)" >${i || ''}
 | 
			
		||||
            </span>`,
 | 
			
		||||
                `<span style="color:rgba(255,255,255,0.5)">${item.name || ''}</span>`,
 | 
			
		||||
                `<span style="color:rgba(255,255,255,0.5)"><div style="${item.run == '运行' ? 'box-shadow: 0px 0px 2px 1px #2760FF;width:6px;height:6px;border-radius: 50%;background-color: #2760FF;float:left;margin:10px 10px 0 0 ' : 'box-shadow: 0px 0px 2px 1px #FFBD02;width:6px;height:6px;border-radius: 50%;  background-color: #FFBD02;float:left;margin:10px 10px 0 0 '}"></div>  ${item.run || ''}</span>`,
 | 
			
		||||
                // `<span style="color:rgba(255,255,255,0.5)" >${i || ''}
 | 
			
		||||
                // </span>`,
 | 
			
		||||
                `<span style="color:rgba(255,255,255,0.5)">${i || ''}</span>`,
 | 
			
		||||
                `<span style="color:rgba(255,255,255,0.5)"><div style="${this.funWsData.data.annealFanInfo[i] == '运行' ? 'box-shadow: 0px 0px 2px 1px #2760FF;width:6px;height:6px;border-radius: 50%;background-color: #2760FF;float:left;margin:10px 10px 0 0 ' : 'box-shadow: 0px 0px 2px 1px #FFBD02;width:6px;height:6px;border-radius: 50%;  background-color: #FFBD02;float:left;margin:10px 10px 0 0 '}"></div>  ${this.funWsData.data.annealFanInfo[i] || ''}</span>`,
 | 
			
		||||
              ])
 | 
			
		||||
          }
 | 
			
		||||
          this.annealFunConfig.data = arr
 | 
			
		||||
          this.$refs['annealFunScrollBoard'].updateRows(arr)
 | 
			
		||||
          // this.$nextTick(() => {
 | 
			
		||||
            this.$refs['annealFunScrollBoard'].updateRows(arr)
 | 
			
		||||
          // })
 | 
			
		||||
        }
 | 
			
		||||
        if (this.funWsData.type === 'FanInfo') {
 | 
			
		||||
          let arr = []
 | 
			
		||||
@@ -650,14 +670,16 @@ export default {
 | 
			
		||||
          for (let i in this.funWsData.data.fanInfo) {
 | 
			
		||||
            index++,
 | 
			
		||||
              arr.push([
 | 
			
		||||
                `<span style="color:rgba(255,255,255,0.5)" >${index || ''}</span>`,
 | 
			
		||||
                `<span style="color:rgba(255,255,255,0.5)" >${i || ''}</span>`,
 | 
			
		||||
                `<span style="color:rgba(255,255,255,0.5)">${item.name || ''}</span>`,
 | 
			
		||||
                `<span style="color:rgba(255,255,255,0.5)"><div style="${item.run == '运行' ? 'box-shadow: 0px 0px 2px 1px #2760FF;width:6px;height:6px;border-radius: 50%;background-color: #2760FF;float:left;margin:10px 10px 0 0 ' : 'box-shadow: 0px 0px 2px 1px #FFBD02;width:6px;height:6px;border-radius: 50%;  background-color: #FFBD02;float:left;margin:10px 10px 0 0 '}"></div>  ${item.run || ''}</span>`,
 | 
			
		||||
                `<span style="color:rgba(255,255,255,0.5)" >${index || ''}
 | 
			
		||||
            </span>`,
 | 
			
		||||
                `<span style="color:rgba(255,255,255,0.5)">${i || ''}</span>`,
 | 
			
		||||
                `<span style="color:rgba(255,255,255,0.5)"><div style="${this.funWsData.data.fanInfo[i] == '运行' ? 'box-shadow: 0px 0px 2px 1px #2760FF;width:6px;height:6px;border-radius: 50%;background-color: #2760FF;float:left;margin:10px 10px 0 0 ' : 'box-shadow: 0px 0px 2px 1px #FFBD02;width:6px;height:6px;border-radius: 50%;  background-color: #FFBD02;float:left;margin:10px 10px 0 0 '}"></div>  ${this.funWsData.data.fanInfo[i] || ''}</span>`,
 | 
			
		||||
              ])
 | 
			
		||||
          }
 | 
			
		||||
          this.funConfig.data = arr
 | 
			
		||||
          this.$refs['funScrollBoard'].updateRows(arr)
 | 
			
		||||
          // this.$nextTick(() => {
 | 
			
		||||
            this.$refs['funScrollBoard'].updateRows(arr)
 | 
			
		||||
          // })
 | 
			
		||||
        }
 | 
			
		||||
      };
 | 
			
		||||
      // if (typeof (WebSocket) === 'undefined') {
 | 
			
		||||
@@ -772,7 +794,37 @@ export default {
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
 | 
			
		||||
.myLegend{
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  top: -20px;
 | 
			
		||||
  right: 50px;
 | 
			
		||||
  font-size: 12px;
 | 
			
		||||
  color: rgba(255,255,255,.6);
 | 
			
		||||
  .barLegend{
 | 
			
		||||
    // float: left;
 | 
			
		||||
    background: linear-gradient(#9DD5FF, #1295FF);
 | 
			
		||||
    width: 10px;
 | 
			
		||||
    height: 10px;
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    margin-right: 5px;
 | 
			
		||||
  }
 | 
			
		||||
  .barText{
 | 
			
		||||
    // float: right;
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    margin-right: 10px;
 | 
			
		||||
  }
 | 
			
		||||
  .barCircle{
 | 
			
		||||
    width: 7px;
 | 
			
		||||
    height: 7px;
 | 
			
		||||
    border-radius: 50%;
 | 
			
		||||
    background-color: rgba(255, 209, 96, 1);
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    margin-right: 5px;
 | 
			
		||||
  }
 | 
			
		||||
  .barCircleText{
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.visual-container {
 | 
			
		||||
  width: 1920px;
 | 
			
		||||
  height: 1080px;
 | 
			
		||||
@@ -794,7 +846,7 @@ export default {
 | 
			
		||||
      top: 25px;
 | 
			
		||||
      color: rgba(255, 255, 255, 0.80);
 | 
			
		||||
      font-size: 20px;
 | 
			
		||||
      letter-spacing: 0px;
 | 
			
		||||
      letter-spacing: 1px;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    .time {
 | 
			
		||||
@@ -803,7 +855,7 @@ export default {
 | 
			
		||||
      color: rgba(255, 255, 255, 0.80);
 | 
			
		||||
      top: 25px;
 | 
			
		||||
      font-size: 20px;
 | 
			
		||||
      letter-spacing: 0px;
 | 
			
		||||
      letter-spacing: .72px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .title-button {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 * @Author: zwq
 | 
			
		||||
 * @Date: 2022-01-21 14:43:06
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @LastEditTime: 2024-03-28 16:45:24
 | 
			
		||||
 * @LastEditTime: 2024-03-29 14:50:50
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
<template>
 | 
			
		||||
@@ -158,6 +158,9 @@ export default {
 | 
			
		||||
  methods: {
 | 
			
		||||
    initChart() {
 | 
			
		||||
      this.chart = echarts.init(document.getElementById(this.id))
 | 
			
		||||
      this.$nextTick(() => {
 | 
			
		||||
        this.chart.resize();
 | 
			
		||||
      });
 | 
			
		||||
      this.chart.setOption({
 | 
			
		||||
        title: this.showCenterTitle
 | 
			
		||||
          ? {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 * @Author: gtz
 | 
			
		||||
 * @Date: 2022-01-19 15:58:17
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @LastEditTime: 2024-03-27 10:26:35
 | 
			
		||||
 * @LastEditTime: 2024-03-29 14:47:29
 | 
			
		||||
 * @Description: file content
 | 
			
		||||
 * @FilePath: \mt-bus-fe\src\views\OperationalOverview\components\baseContainer\index.vue
 | 
			
		||||
-->
 | 
			
		||||
@@ -164,7 +164,7 @@ export default {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  // background-color: rgba($color: #061027, $alpha: 0.15);
 | 
			
		||||
  position: relative;
 | 
			
		||||
  opacity: calc(.8);
 | 
			
		||||
  // opacity: calc(.8);
 | 
			
		||||
  // border: 2px solid;
 | 
			
		||||
    // background: url('../../../../assets/img/energy.png') no-repeat;
 | 
			
		||||
    // background-size: 100% 100%;
 | 
			
		||||
@@ -274,6 +274,8 @@ export default {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    color: #ffffff;
 | 
			
		||||
    font-size: 24px;
 | 
			
		||||
    font-weight: normal;
 | 
			
		||||
    letter-spacing: .8px;
 | 
			
		||||
    padding: 0.67em 0.67em 0.3em 0.67em;
 | 
			
		||||
    display: flex;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -2,13 +2,13 @@
 | 
			
		||||
<!--
 | 
			
		||||
 * @Author: zhp
 | 
			
		||||
 * @Date: 2023-09-21 09:06:28
 | 
			
		||||
 * @LastEditTime: 2024-03-25 18:34:58
 | 
			
		||||
 * @LastEditTime: 2024-04-01 09:12:56
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <div :id="id" class="productChart" :style="{ height:   '390px', width: width }" />
 | 
			
		||||
    <div :id="id" class="coldProductChart" :style="{ height:   '390px', width: width }" />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@@ -71,9 +71,9 @@ export default {
 | 
			
		||||
  mounted() {
 | 
			
		||||
    console.log('mounted')
 | 
			
		||||
    console.log('borderRadius: ', this.borderRadius)
 | 
			
		||||
    // this.$nextTick(() => {
 | 
			
		||||
    //   this.initChart()
 | 
			
		||||
    // })
 | 
			
		||||
    this.$el.addEventListener('resize', () => {
 | 
			
		||||
      console.log('resziing.....');
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
  beforeDestroy() {
 | 
			
		||||
    if (!this.chart) {
 | 
			
		||||
@@ -114,6 +114,7 @@ export default {
 | 
			
		||||
          name: '产线良品率',
 | 
			
		||||
          symbol: 'circle', //变为实心圆
 | 
			
		||||
          type: 'line',
 | 
			
		||||
          // symbolSize: 7,
 | 
			
		||||
          yAxisIndex: 0,
 | 
			
		||||
          areaStyle: {
 | 
			
		||||
            opacity: 0.8,
 | 
			
		||||
@@ -141,6 +142,16 @@ export default {
 | 
			
		||||
      ]
 | 
			
		||||
      // const colors = ['#5470C6', '#91CC75', '#EE6666']
 | 
			
		||||
      this.chart = echarts.init(document.getElementById(this.id))
 | 
			
		||||
      let isFinished = false //标记 isFinished
 | 
			
		||||
      this.chart.on('finished', _ => {
 | 
			
		||||
        if (!isFinished) {
 | 
			
		||||
          console.log('我只执行一次')
 | 
			
		||||
          isFinished = true
 | 
			
		||||
          // this.isLoading = false //关闭loading
 | 
			
		||||
          this.chart.resize() //重新渲染charts大小
 | 
			
		||||
        }
 | 
			
		||||
        console.log(113, 'finished')
 | 
			
		||||
      })
 | 
			
		||||
      this.chart.setOption({
 | 
			
		||||
        // color: colors,
 | 
			
		||||
        tooltip: {
 | 
			
		||||
@@ -151,22 +162,33 @@ export default {
 | 
			
		||||
        },
 | 
			
		||||
        grid: {
 | 
			
		||||
          left: "3%",
 | 
			
		||||
          right: "5%",
 | 
			
		||||
          right: "10%",
 | 
			
		||||
          bottom: "3%",
 | 
			
		||||
          containLabel: true
 | 
			
		||||
        },
 | 
			
		||||
        legend: {
 | 
			
		||||
          itemWidth: 10,
 | 
			
		||||
          itemHeight: 10,
 | 
			
		||||
          top: '20',
 | 
			
		||||
          // right: '20px',
 | 
			
		||||
          data: ['产线产量', '产线良品率'],
 | 
			
		||||
          textStyle: {
 | 
			
		||||
            fontSize: 12 * this.beilv,
 | 
			
		||||
            color: '#ced1d5'
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        // legend: {
 | 
			
		||||
        //   itemWidth: 10,
 | 
			
		||||
        //   itemHeight: 10,
 | 
			
		||||
        //   top: '5',
 | 
			
		||||
        //   right: '20px',
 | 
			
		||||
        //   data: [
 | 
			
		||||
        //     // { icon: 'rect', name: '直接访问' },
 | 
			
		||||
        //     { icon: 'roundRect', name: '产线产量' },
 | 
			
		||||
        //     // {
 | 
			
		||||
        //     //   icon: 'circle', name: '产线良品率',
 | 
			
		||||
        //     //   itemWidth: 7,
 | 
			
		||||
        //     //   itemHeight: 7,
 | 
			
		||||
        //     //  },
 | 
			
		||||
        //   ],
 | 
			
		||||
        //   textStyle: {
 | 
			
		||||
        //     fontSize: 12 * this.beilv,
 | 
			
		||||
        //     color: '#ced1d5'
 | 
			
		||||
        //   }
 | 
			
		||||
        // },
 | 
			
		||||
        xAxis: {
 | 
			
		||||
          axisTick: {
 | 
			
		||||
            show: false
 | 
			
		||||
          },
 | 
			
		||||
          type: 'category',
 | 
			
		||||
          axisLine: {
 | 
			
		||||
            lineStyle: {
 | 
			
		||||
@@ -202,7 +224,7 @@ export default {
 | 
			
		||||
            type: 'value',
 | 
			
		||||
            name: '良品率/%',
 | 
			
		||||
            nameTextStyle: {// y轴上方单位的颜色
 | 
			
		||||
              color: '#fff',
 | 
			
		||||
              color: 'rgba(255,255,255,0.5)', // 坐标值得具体的颜色
 | 
			
		||||
              align: "left",
 | 
			
		||||
            },
 | 
			
		||||
            position: 'right',
 | 
			
		||||
@@ -245,7 +267,7 @@ export default {
 | 
			
		||||
            type: 'value',
 | 
			
		||||
            name: '产量/㎡', // y轴上方的单位
 | 
			
		||||
            nameTextStyle: {
 | 
			
		||||
              color: "#fff",
 | 
			
		||||
              color: 'rgba(255,255,255,0.5)', // 坐标值得具体的颜色
 | 
			
		||||
              // fontSize: 10,
 | 
			
		||||
              align: "right",
 | 
			
		||||
            },
 | 
			
		||||
@@ -286,7 +308,8 @@ export default {
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
<style>
 | 
			
		||||
.productChart{
 | 
			
		||||
 | 
			
		||||
.coldProductChart{
 | 
			
		||||
  top: -10px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
<!--
 | 
			
		||||
 * @Author: zhp
 | 
			
		||||
 * @Date: 2023-09-21 09:06:28
 | 
			
		||||
 * @LastEditTime: 2024-03-28 16:31:20
 | 
			
		||||
 * @LastEditTime: 2024-03-29 16:26:28
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
@@ -106,7 +106,8 @@ export default {
 | 
			
		||||
               position: 'top',	//在上方显示
 | 
			
		||||
               textStyle: {	    //数值样式
 | 
			
		||||
                 color: '#ced1d5',
 | 
			
		||||
                 fontSize: 12
 | 
			
		||||
                 fontSize: 12,
 | 
			
		||||
                 fontWight:'bolder'
 | 
			
		||||
               }
 | 
			
		||||
             },
 | 
			
		||||
            }
 | 
			
		||||
@@ -142,7 +143,7 @@ export default {
 | 
			
		||||
            }
 | 
			
		||||
          },
 | 
			
		||||
          // data: passRateList
 | 
			
		||||
          data: []
 | 
			
		||||
          data: passRateList
 | 
			
		||||
        }
 | 
			
		||||
      ]
 | 
			
		||||
      // const colors = ['#5470C6', '#91CC75', '#EE6666']
 | 
			
		||||
@@ -166,19 +167,23 @@ export default {
 | 
			
		||||
              type: 'cross'
 | 
			
		||||
            }
 | 
			
		||||
          },
 | 
			
		||||
          grid: { top: 90, right: 60, bottom: 20, left: 20, containLabel: true },
 | 
			
		||||
          grid: { top: 90, right: 70, bottom: 20, left: 20, containLabel: true },
 | 
			
		||||
          legend: {
 | 
			
		||||
            itemWidth: 10,
 | 
			
		||||
            itemHeight: 10,
 | 
			
		||||
            top: '0%',
 | 
			
		||||
            right: '20px',
 | 
			
		||||
            data: ['产线产量', '产线良品率'],
 | 
			
		||||
            data: ['产线良品率', '产线产量'],
 | 
			
		||||
            textStyle: {
 | 
			
		||||
              fontSize: 12 * this.beilv,
 | 
			
		||||
              color: '#ced1d5'
 | 
			
		||||
              color: '#ced1d5',
 | 
			
		||||
              fontWight: 'bolder'
 | 
			
		||||
            }
 | 
			
		||||
          },
 | 
			
		||||
          xAxis: {
 | 
			
		||||
            axisTick: {
 | 
			
		||||
              show: false
 | 
			
		||||
            },
 | 
			
		||||
            type: 'category',
 | 
			
		||||
            axisLine: {
 | 
			
		||||
              lineStyle: {
 | 
			
		||||
@@ -187,8 +192,11 @@ export default {
 | 
			
		||||
                width: '1' // 坐标线的宽度
 | 
			
		||||
              }
 | 
			
		||||
            },
 | 
			
		||||
            textStyle: {
 | 
			
		||||
              fontWight: 'bolder'
 | 
			
		||||
            },
 | 
			
		||||
            axisLabel: {
 | 
			
		||||
              color: "#fff",
 | 
			
		||||
              color: 'rgba(255,255,255,0.5)', // 坐标值得具体的颜色
 | 
			
		||||
              fontSize: 12,
 | 
			
		||||
              // formatter: '{value}'
 | 
			
		||||
              // textStyle: {
 | 
			
		||||
@@ -217,7 +225,7 @@ export default {
 | 
			
		||||
              type: 'value',
 | 
			
		||||
              name: '良品率/%',
 | 
			
		||||
              nameTextStyle: {// y轴上方单位的颜色
 | 
			
		||||
                color: '#fff',
 | 
			
		||||
                color: 'rgba(255,255,255,0.5)', // 坐标值得具体的颜色
 | 
			
		||||
                align: "left",
 | 
			
		||||
              },
 | 
			
		||||
              position: 'right',
 | 
			
		||||
@@ -231,7 +239,7 @@ export default {
 | 
			
		||||
                }
 | 
			
		||||
              },
 | 
			
		||||
              axisLabel: {
 | 
			
		||||
                color: "#fff",
 | 
			
		||||
                color: 'rgba(255,255,255,0.5)', // 坐标值得具体的颜色
 | 
			
		||||
                fontSize: 12,
 | 
			
		||||
                // formatter: '{value}'
 | 
			
		||||
                formatter: '{value}%'
 | 
			
		||||
@@ -261,7 +269,7 @@ export default {
 | 
			
		||||
              type: 'value',
 | 
			
		||||
              name: '产量/片', // y轴上方的单位
 | 
			
		||||
              nameTextStyle: {
 | 
			
		||||
                color: "#fff",
 | 
			
		||||
                color: 'rgba(255,255,255,0.5)', // 坐标值得具体的颜色
 | 
			
		||||
                // fontSize: 10,
 | 
			
		||||
                align: "right",
 | 
			
		||||
              },
 | 
			
		||||
@@ -278,7 +286,7 @@ export default {
 | 
			
		||||
              axisLabel: {
 | 
			
		||||
                // textStyle: {
 | 
			
		||||
                // color: 'rgba(255,255,255,0.5)', // 坐标值得具体的颜色
 | 
			
		||||
                color: "#fff",
 | 
			
		||||
                color: 'rgba(255,255,255,0.5)', // 坐标值得具体的颜色
 | 
			
		||||
                // show: true,
 | 
			
		||||
                lineStyle: {
 | 
			
		||||
                  color: "#25528f",
 | 
			
		||||
 
 | 
			
		||||
@@ -111,8 +111,9 @@ export default {
 | 
			
		||||
                show: true,		//开启显示
 | 
			
		||||
                position: 'top',	//在上方显示
 | 
			
		||||
                textStyle: {	    //数值样式
 | 
			
		||||
                  color: '#ced1d5',
 | 
			
		||||
                  fontSize: 12
 | 
			
		||||
                  color: 'rgba(255,255,255,0.5)', // 坐标值得具体的颜色
 | 
			
		||||
                  fontSize: 12,
 | 
			
		||||
                  fontWeight: 'bolder'
 | 
			
		||||
                }
 | 
			
		||||
              },
 | 
			
		||||
            }
 | 
			
		||||
@@ -144,6 +145,9 @@ export default {
 | 
			
		||||
          //   }
 | 
			
		||||
          // },
 | 
			
		||||
          xAxis: {
 | 
			
		||||
            axisTick: {
 | 
			
		||||
              show: false
 | 
			
		||||
            },
 | 
			
		||||
            type: 'category',
 | 
			
		||||
            axisLine: {
 | 
			
		||||
              lineStyle: {
 | 
			
		||||
@@ -152,8 +156,11 @@ export default {
 | 
			
		||||
                width: '1' // 坐标线的宽度
 | 
			
		||||
              }
 | 
			
		||||
            },
 | 
			
		||||
            textStyle: {
 | 
			
		||||
              fontWeight: 'bolder'
 | 
			
		||||
            },
 | 
			
		||||
            axisLabel: {
 | 
			
		||||
              color: "#fff",
 | 
			
		||||
              color: 'rgba(255,255,255,0.5)', // 坐标值得具体的颜色
 | 
			
		||||
              fontSize: 12,
 | 
			
		||||
              // formatter: '{value}'
 | 
			
		||||
            },
 | 
			
		||||
@@ -167,13 +174,13 @@ export default {
 | 
			
		||||
          yAxis: {
 | 
			
		||||
            name: '单位kwh',
 | 
			
		||||
            nameTextStyle: {
 | 
			
		||||
              color: '#fff',
 | 
			
		||||
              color: 'rgba(255,255,255,0.5)', // 坐标值得具体的颜色
 | 
			
		||||
              fontSize: 10,
 | 
			
		||||
              align: 'right',
 | 
			
		||||
            },
 | 
			
		||||
            type: 'value',
 | 
			
		||||
            axisLabel: {
 | 
			
		||||
              color: "#fff",
 | 
			
		||||
              color: 'rgba(255,255,255,0.5)', // 坐标值得具体的颜色
 | 
			
		||||
              fontSize: 12,
 | 
			
		||||
              // formatter: '{value}/kwh'
 | 
			
		||||
            },
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,13 @@
 | 
			
		||||
<!--
 | 
			
		||||
 * @Author: zhp
 | 
			
		||||
 * @Date: 2023-12-27 13:54:52
 | 
			
		||||
 * @LastEditTime: 2024-03-28 16:30:14
 | 
			
		||||
 * @LastEditTime: 2024-04-01 09:14:45
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <div :id="id" class="productChart" :style="{ height: height + 'px', width: width }" />
 | 
			
		||||
    <div :id="id" :style="{ height:'75px', width: width }" />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@@ -71,7 +71,10 @@ export default {
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  mounted() {
 | 
			
		||||
    console.log('mounted')
 | 
			
		||||
    // console.log('mounted')
 | 
			
		||||
    window.addEventListener('resize', () => {
 | 
			
		||||
      this.resize()
 | 
			
		||||
    })
 | 
			
		||||
    // console.log('borderRadius: ', this.borderRadius)
 | 
			
		||||
    // console.log('33333', this.dataList)
 | 
			
		||||
    // let arr = []
 | 
			
		||||
@@ -91,6 +94,12 @@ export default {
 | 
			
		||||
    this.chart = null
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    resize() {
 | 
			
		||||
      this.chart.resize({
 | 
			
		||||
        width: 'auto',
 | 
			
		||||
        height: 90
 | 
			
		||||
      });;
 | 
			
		||||
    },
 | 
			
		||||
    initChart(nameList, topNameList, nameWasteList, passRateList, wasteList) {
 | 
			
		||||
      let rawData = []
 | 
			
		||||
      let colors = ['#0fdedb', '#2359ec']
 | 
			
		||||
@@ -106,7 +115,6 @@ export default {
 | 
			
		||||
        }
 | 
			
		||||
      // }
 | 
			
		||||
      console.log('total', totalData)
 | 
			
		||||
      this.chart = echarts.init(document.getElementById(this.id))
 | 
			
		||||
      const series = [
 | 
			
		||||
        '良品',
 | 
			
		||||
        '废品',
 | 
			
		||||
@@ -137,6 +145,17 @@ export default {
 | 
			
		||||
      //   width,
 | 
			
		||||
      //   height
 | 
			
		||||
      // })
 | 
			
		||||
      this.chart = echarts.init(document.getElementById(this.id))
 | 
			
		||||
      let isFinished = false //标记 isFinished
 | 
			
		||||
      this.chart.on('finished', _ => {
 | 
			
		||||
        if (!isFinished) {
 | 
			
		||||
          console.log('我只执行一次')
 | 
			
		||||
          isFinished = true
 | 
			
		||||
          // this.isLoading = false //关闭loading
 | 
			
		||||
          this.chart.resize() //重新渲染charts大小
 | 
			
		||||
        }
 | 
			
		||||
        console.log(113, 'finished')
 | 
			
		||||
      })
 | 
			
		||||
      this.chart.setOption({
 | 
			
		||||
        legend: {
 | 
			
		||||
          formatter: function (name) {
 | 
			
		||||
@@ -152,7 +171,8 @@ export default {
 | 
			
		||||
          left: '20',
 | 
			
		||||
          icon: 'rect',
 | 
			
		||||
          textStyle: {
 | 
			
		||||
            color: '#ffffff'
 | 
			
		||||
            color: 'rgba(255,255,255,.6)',
 | 
			
		||||
            fontSize:12,
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        grid: {
 | 
			
		||||
@@ -184,9 +204,9 @@ export default {
 | 
			
		||||
              splitNumber: 50,
 | 
			
		||||
              // boundaryGap: [20, 20],
 | 
			
		||||
              textStyle: {
 | 
			
		||||
                color: '#ffffff',
 | 
			
		||||
                color: 'rgba(255,255,255,.6)',
 | 
			
		||||
                verticalAlign: 'bottom',
 | 
			
		||||
                fontSize: 12,
 | 
			
		||||
                fontSize: 16,
 | 
			
		||||
                align: 'left',
 | 
			
		||||
                padding: [0, 0, 10, -5]
 | 
			
		||||
              }
 | 
			
		||||
@@ -212,9 +232,9 @@ export default {
 | 
			
		||||
              splitNumber: 50,
 | 
			
		||||
              // boundaryGap: [20, 20],
 | 
			
		||||
              textStyle: {
 | 
			
		||||
                color: '#ffffff',
 | 
			
		||||
                color: 'rgba(255,255,255,.6)',
 | 
			
		||||
                verticalAlign: 'bottom',
 | 
			
		||||
                fontSize: 12,
 | 
			
		||||
                fontSize: 16,
 | 
			
		||||
                align: 'right',
 | 
			
		||||
                padding: [0, 0, 10, -5]
 | 
			
		||||
              }
 | 
			
		||||
@@ -228,10 +248,15 @@ export default {
 | 
			
		||||
        },
 | 
			
		||||
        series:series
 | 
			
		||||
      })
 | 
			
		||||
      this.chart.resize({
 | 
			
		||||
        width: 'auto',
 | 
			
		||||
        height: 90
 | 
			
		||||
      });;
 | 
			
		||||
      this.$nextTick(() => {
 | 
			
		||||
        setTimeout(() => {
 | 
			
		||||
          this.resize()
 | 
			
		||||
        },1000);
 | 
			
		||||
      })
 | 
			
		||||
      // this.chart.resize({
 | 
			
		||||
      //   width: 'auto',
 | 
			
		||||
      //   height: 90
 | 
			
		||||
      // });;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,7 +1,7 @@
 | 
			
		||||
<!--
 | 
			
		||||
 * @Author: zhp
 | 
			
		||||
 * @Date: 2023-11-08 14:00:52
 | 
			
		||||
 * @LastEditTime: 2024-03-25 14:09:33
 | 
			
		||||
 * @LastEditTime: 2024-03-29 08:46:42
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
@@ -25,24 +25,24 @@ export default {
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // state: false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
    state() {
 | 
			
		||||
      return this.injectData.enabled === 1 ? true : false
 | 
			
		||||
      state: false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  // computed: {
 | 
			
		||||
  //   state() {
 | 
			
		||||
  //     return this.injectData.enabled === 1 ? true : false
 | 
			
		||||
  //   }
 | 
			
		||||
  // },
 | 
			
		||||
  mounted() {
 | 
			
		||||
    // this.mapToState()
 | 
			
		||||
    this.mapToState()
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  methods: {
 | 
			
		||||
    // mapToState() {
 | 
			
		||||
    //   if (this.injectData.prop === 'enabled') {
 | 
			
		||||
    //     this.state = this.injectData.enabled === 1 ? true : false
 | 
			
		||||
    //   }
 | 
			
		||||
    // },
 | 
			
		||||
    mapToState() {
 | 
			
		||||
      if (this.injectData.prop === 'enabled') {
 | 
			
		||||
        this.state = this.injectData.enabled === 1 ? true : false
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    changeHandler() {
 | 
			
		||||
      // let params = {}
 | 
			
		||||
      let payload = {}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										210
									
								
								src/views/infra/apiAccessLog/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								src/views/infra/apiAccessLog/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,210 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										228
									
								
								src/views/infra/apiErrorLog/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										228
									
								
								src/views/infra/apiErrorLog/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,228 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										22
									
								
								src/views/infra/build/App.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/views/infra/build/App.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										110
									
								
								src/views/infra/build/CodeTypeDialog.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								src/views/infra/build/CodeTypeDialog.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,110 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										120
									
								
								src/views/infra/build/DraggableItem.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								src/views/infra/build/DraggableItem.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,120 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										331
									
								
								src/views/infra/build/FormDrawer.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										331
									
								
								src/views/infra/build/FormDrawer.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,331 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										123
									
								
								src/views/infra/build/IconsDialog.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								src/views/infra/build/IconsDialog.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,123 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										144
									
								
								src/views/infra/build/JsonDrawer.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								src/views/infra/build/JsonDrawer.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,144 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										0
									
								
								src/views/infra/build/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/views/infra/build/README.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										116
									
								
								src/views/infra/build/ResourceDialog.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/views/infra/build/ResourceDialog.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										1050
									
								
								src/views/infra/build/RightPanel.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1050
									
								
								src/views/infra/build/RightPanel.vue
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										158
									
								
								src/views/infra/build/TreeNodeDialog.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								src/views/infra/build/TreeNodeDialog.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,158 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										470
									
								
								src/views/infra/build/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										470
									
								
								src/views/infra/build/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,470 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										19
									
								
								src/views/infra/build/main.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/views/infra/build/main.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
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')
 | 
			
		||||
							
								
								
									
										67
									
								
								src/views/infra/codegen/basicInfoForm.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								src/views/infra/codegen/basicInfoForm.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,67 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										235
									
								
								src/views/infra/codegen/editTable.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								src/views/infra/codegen/editTable.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,235 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										339
									
								
								src/views/infra/codegen/genInfoForm.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										339
									
								
								src/views/infra/codegen/genInfoForm.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,339 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										114
									
								
								src/views/infra/codegen/importTable.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								src/views/infra/codegen/importTable.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,114 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										317
									
								
								src/views/infra/codegen/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										317
									
								
								src/views/infra/codegen/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,317 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										262
									
								
								src/views/infra/config/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										262
									
								
								src/views/infra/config/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,262 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										166
									
								
								src/views/infra/dataSourceConfig/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								src/views/infra/dataSourceConfig/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,166 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										70
									
								
								src/views/infra/dbDoc/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/views/infra/dbDoc/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										32
									
								
								src/views/infra/druid/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/views/infra/druid/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										216
									
								
								src/views/infra/file/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								src/views/infra/file/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,216 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										305
									
								
								src/views/infra/fileConfig/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										305
									
								
								src/views/infra/fileConfig/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,305 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										378
									
								
								src/views/infra/job/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										378
									
								
								src/views/infra/job/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,378 @@
 | 
			
		||||
<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:"/system/job/log",
 | 
			
		||||
          query:{
 | 
			
		||||
            jobId: row.id
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      } else {
 | 
			
		||||
        this.$router.push("/system/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>
 | 
			
		||||
							
								
								
									
										178
									
								
								src/views/infra/job/log.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								src/views/infra/job/log.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,178 @@
 | 
			
		||||
<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="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>
 | 
			
		||||
							
								
								
									
										157
									
								
								src/views/infra/redis/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								src/views/infra/redis/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,157 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										30
									
								
								src/views/infra/server/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/views/infra/server/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										30
									
								
								src/views/infra/skywalking/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/views/infra/skywalking/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										31
									
								
								src/views/infra/swagger/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/views/infra/swagger/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										257
									
								
								src/views/infra/testDemo/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										257
									
								
								src/views/infra/testDemo/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,257 @@
 | 
			
		||||
<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>
 | 
			
		||||
							
								
								
									
										92
									
								
								src/views/infra/webSocket/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/views/infra/webSocket/index.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,92 @@
 | 
			
		||||
<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>
 | 
			
		||||
@@ -4,7 +4,8 @@
 | 
			
		||||
    <SearchBar :formConfigs="searchBarFormConfig" ref="search-bar" @headBtnClick="buttonClick" />
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <base-table :table-props="tableProps" :page="listQuery.pageNo" :limit="listQuery.pageSize" :table-data="tableData">
 | 
			
		||||
    <base-table :max-height="tableH" :table-props="tableProps" :page="listQuery.pageNo" :limit="listQuery.pageSize"
 | 
			
		||||
      :table-data="tableData">
 | 
			
		||||
      <method-btn v-if="tableBtn.length" slot="handleBtn" label="操作" :width="120" fixed="right" :method-list="tableBtn"
 | 
			
		||||
        @clickBtn="handleClick" />
 | 
			
		||||
    </base-table>
 | 
			
		||||
@@ -33,10 +34,10 @@ import {
 | 
			
		||||
import basicPage from '../../mixins/basic-page';
 | 
			
		||||
import moment from 'moment';
 | 
			
		||||
import addOrUpdate from './dialogForm.vue';
 | 
			
		||||
 | 
			
		||||
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'QualityInspectionBoxBtn',
 | 
			
		||||
  mixins: [basicPage],
 | 
			
		||||
  mixins: [basicPage, tableHeightMixin],
 | 
			
		||||
  components: { addOrUpdate },
 | 
			
		||||
	data() {
 | 
			
		||||
    return {
 | 
			
		||||
@@ -114,7 +115,7 @@ export default {
 | 
			
		||||
			// 查询参数
 | 
			
		||||
			listQuery: {
 | 
			
		||||
				pageNo: 1,
 | 
			
		||||
				pageSize: 10,
 | 
			
		||||
				pageSize: 20,
 | 
			
		||||
				inspectionDetContent: null,
 | 
			
		||||
      },
 | 
			
		||||
      addOrUpdateVisible: false,
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,8 @@
 | 
			
		||||
    <SearchBar :formConfigs="searchBarFormConfig" ref="search-bar" @headBtnClick="buttonClick" />
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <base-table :table-props="tableProps" :page="listQuery.pageNo" :limit="listQuery.pageSize" :table-data="tableData">
 | 
			
		||||
    <base-table :max-height="tableH" :table-props="tableProps" :page="listQuery.pageNo" :limit="listQuery.pageSize"
 | 
			
		||||
      :table-data="tableData">
 | 
			
		||||
      <method-btn v-if="tableBtn.length" slot="handleBtn" label="操作" :width="120" fixed="right" :method-list="tableBtn"
 | 
			
		||||
        @clickBtn="handleClick" />
 | 
			
		||||
    </base-table>
 | 
			
		||||
@@ -34,10 +35,11 @@ import basicPage from './basic-page';
 | 
			
		||||
import moment from 'moment';
 | 
			
		||||
import addOrUpdate from './dialogForm.vue';
 | 
			
		||||
import ProcessBomList from './ProcessBomList.vue';
 | 
			
		||||
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
 | 
			
		||||
import row from './row.vue';
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'QualityInspectionBoxBtn',
 | 
			
		||||
  mixins: [basicPage],
 | 
			
		||||
  mixins: [basicPage, tableHeightMixin],
 | 
			
		||||
  components: { addOrUpdate, ProcessBomList },
 | 
			
		||||
	data() {
 | 
			
		||||
    return {
 | 
			
		||||
@@ -123,7 +125,7 @@ export default {
 | 
			
		||||
			// 查询参数
 | 
			
		||||
			listQuery: {
 | 
			
		||||
				pageNo: 1,
 | 
			
		||||
				pageSize: 10,
 | 
			
		||||
				pageSize: 20,
 | 
			
		||||
        userName: null,
 | 
			
		||||
        nickName:null
 | 
			
		||||
      },
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
 | 
			
		||||
    <base-table v-loading="dataListLoading" :table-props="tableProps" :page="listQuery.pageNo"
 | 
			
		||||
    <base-table :max-height="tableH" v-loading="dataListLoading" :table-props="tableProps" :page="listQuery.pageNo"
 | 
			
		||||
      :limit="listQuery.pageSize" :table-data="tableData">
 | 
			
		||||
      <method-btn v-if="tableBtn.length" slot="handleBtn" :width="120" label="操作" :method-list="tableBtn"
 | 
			
		||||
        @clickBtn="handleClick" />
 | 
			
		||||
@@ -29,6 +29,7 @@ import {
 | 
			
		||||
  deleteQualityHotMaterial,
 | 
			
		||||
  getHotMaterialAllList
 | 
			
		||||
} from '@/api/base/qualityHotMaterial';
 | 
			
		||||
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
 | 
			
		||||
// import { getList, } from "@/api/base/qualityScrapType";
 | 
			
		||||
const tableProps = [
 | 
			
		||||
	{
 | 
			
		||||
@@ -74,7 +75,7 @@ const tableProps = [
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	mixins: [basicPage],
 | 
			
		||||
  mixins: [basicPage, tableHeightMixin],
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			urlOptions: {
 | 
			
		||||
@@ -207,7 +208,7 @@ export default {
 | 
			
		||||
			switch (val.btnName) {
 | 
			
		||||
				case 'search':
 | 
			
		||||
					this.listQuery.pageNo = 1;
 | 
			
		||||
					this.listQuery.pageSize = 10;
 | 
			
		||||
					this.listQuery.pageSize = 20;
 | 
			
		||||
          this.listQuery.materialId = val.materialId ? val.materialId : undefined;
 | 
			
		||||
          this.listQuery.checkTime = val.checkTime ? val.checkTime : undefined;
 | 
			
		||||
					this.getDataList();
 | 
			
		||||
@@ -215,7 +216,7 @@ export default {
 | 
			
		||||
				case 'reset':
 | 
			
		||||
					this.$refs.searchBarForm.resetForm();
 | 
			
		||||
					this.listQuery = {
 | 
			
		||||
						pageSize: 10,
 | 
			
		||||
						pageSize: 20,
 | 
			
		||||
						pageNo: 1,
 | 
			
		||||
						total: 1,
 | 
			
		||||
					};
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
    <SearchBar :formConfigs="searchBarFormConfig" ref="search-bar" @headBtnClick="handleSearchBarBtnClick" />
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <base-table :table-props="tableProps" :page="queryParams.pageNo" :limit="queryParams.pageSize" :table-data="list"
 | 
			
		||||
    <base-table :max-height="tableH" :table-props="tableProps" :page="queryParams.pageNo" :limit="queryParams.pageSize" :table-data="list"
 | 
			
		||||
      @emitFun="handleEmitFun">
 | 
			
		||||
      <method-btn v-if="tableBtn.length" slot="handleBtn" label="操作" :width="120" fixed="right" :method-list="tableBtn"
 | 
			
		||||
        @clickBtn="handleTableBtnClick" />
 | 
			
		||||
@@ -59,14 +59,14 @@ import {
 | 
			
		||||
	getQualityInspectionDetPage,
 | 
			
		||||
	exportQualityInspectionDetExcel,
 | 
			
		||||
} from '@/api/base/qualityInspectionDet';
 | 
			
		||||
 | 
			
		||||
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
 | 
			
		||||
import moment from 'moment';
 | 
			
		||||
 | 
			
		||||
import basicPageMixin from '@/mixins/lb/basicPageMixin';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'QualityInspectionDet',
 | 
			
		||||
	mixins: [basicPageMixin],
 | 
			
		||||
  mixins: [basicPageMixin, tableHeightMixin],
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			typeList: [], // 检测类型列表
 | 
			
		||||
@@ -153,7 +153,7 @@ export default {
 | 
			
		||||
			// 查询参数
 | 
			
		||||
			queryParams: {
 | 
			
		||||
				pageNo: 1,
 | 
			
		||||
				pageSize: 10,
 | 
			
		||||
				pageSize: 20,
 | 
			
		||||
				content: null,
 | 
			
		||||
				createTime: [],
 | 
			
		||||
			},
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,8 @@
 | 
			
		||||
    <SearchBar :formConfigs="searchBarFormConfig" ref="search-bar" @headBtnClick="handleSearchBarBtnClick" />
 | 
			
		||||
 | 
			
		||||
    <!-- 列表 -->
 | 
			
		||||
    <base-table :table-props="tableProps" :page="queryParams.pageNo" :limit="queryParams.pageSize" :table-data="list"
 | 
			
		||||
      @emitFun="handleEmitFun">
 | 
			
		||||
    <base-table :max-height="tableH" :table-props="tableProps" :page="queryParams.pageNo" :limit="queryParams.pageSize"
 | 
			
		||||
      :table-data="list" @emitFun="handleEmitFun">
 | 
			
		||||
      <method-btn v-if="tableBtn.length" slot="handleBtn" label="操作" :width="120" :method-list="tableBtn"
 | 
			
		||||
        @clickBtn="handleTableBtnClick" />
 | 
			
		||||
    </base-table>
 | 
			
		||||
@@ -61,10 +61,10 @@ import {
 | 
			
		||||
	exportQualityInspectionTypeExcel,
 | 
			
		||||
} from '@/api/base/qualityInspectionType';
 | 
			
		||||
import basicPageMixin from '@/mixins/lb/basicPageMixin';
 | 
			
		||||
 | 
			
		||||
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
 | 
			
		||||
export default {
 | 
			
		||||
	name: 'QualityInspectionType',
 | 
			
		||||
	mixins: [basicPageMixin],
 | 
			
		||||
  mixins: [basicPageMixin, tableHeightMixin],
 | 
			
		||||
	data() {
 | 
			
		||||
		return {
 | 
			
		||||
			tableBtn: [
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 * @Author: zwq
 | 
			
		||||
 * @Date: 2023-08-01 14:55:51
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @LastEditTime: 2024-03-25 16:07:07
 | 
			
		||||
 * @LastEditTime: 2024-03-29 14:08:18
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
<template>
 | 
			
		||||
@@ -24,12 +24,12 @@
 | 
			
		||||
// import unitDict from './unitDict';
 | 
			
		||||
// import basicPage from '../mixins/basic-page';
 | 
			
		||||
import { parseTime } from '../mixins/code-filter';
 | 
			
		||||
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
 | 
			
		||||
import {
 | 
			
		||||
  getMaterialUseLogPage,
 | 
			
		||||
  getWorkOrderList,
 | 
			
		||||
  exportEnergyPlcExcel
 | 
			
		||||
} from '@/api/quality/materialTraceability';
 | 
			
		||||
 | 
			
		||||
const tableProps = [
 | 
			
		||||
  {
 | 
			
		||||
    prop: 'materialName',
 | 
			
		||||
@@ -73,6 +73,7 @@ const tableProps = [
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  mixins: [tableHeightMixin],
 | 
			
		||||
  // mixins: [basicPage],
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
@@ -82,7 +83,7 @@ export default {
 | 
			
		||||
      //   // exportURL: exportPackingExcel,
 | 
			
		||||
      // },
 | 
			
		||||
      tableProps,
 | 
			
		||||
      tableH: this.tableHeight(260),
 | 
			
		||||
      // tableH: this.tableHeight(260),
 | 
			
		||||
      tableBtn: [
 | 
			
		||||
        this.$auth.hasPermi(`base:packaging-print-log:update`)
 | 
			
		||||
          ? {
 | 
			
		||||
@@ -174,9 +175,9 @@ export default {
 | 
			
		||||
    // AddOrUpdate,
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    window.addEventListener('resize', () => {
 | 
			
		||||
      this.tableH = this.tableHeight(260)
 | 
			
		||||
    })
 | 
			
		||||
    // window.addEventListener('resize', () => {
 | 
			
		||||
    //   this.tableH = this.tableHeight(260)
 | 
			
		||||
    // })
 | 
			
		||||
    this.getList()
 | 
			
		||||
    this.getDict()
 | 
			
		||||
  },
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 * @Author: zwq
 | 
			
		||||
 * @Date: 2023-08-01 14:55:51
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @LastEditTime: 2024-03-21 15:17:05
 | 
			
		||||
 * @LastEditTime: 2024-03-29 14:08:30
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
<template>
 | 
			
		||||
@@ -25,6 +25,8 @@
 | 
			
		||||
// import basicPage from '../mixins/basic-page';
 | 
			
		||||
import { publicFormatter } from '@/utils/dict';
 | 
			
		||||
import { parseTime } from '../mixins/code-filter';
 | 
			
		||||
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  getOriginalGlassRetrace,
 | 
			
		||||
  getWorkOrderList,
 | 
			
		||||
@@ -85,6 +87,7 @@ const tableProps = [
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  // mixins: [basicPage],
 | 
			
		||||
  mixins: [tableHeightMixin],
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // urlOptions: {
 | 
			
		||||
@@ -119,7 +122,7 @@ export default {
 | 
			
		||||
        startTime: undefined,
 | 
			
		||||
        endTime:undefined,
 | 
			
		||||
      },
 | 
			
		||||
      tableH: this.tableHeight(260),
 | 
			
		||||
      // tableH: this.tableHeight(260),
 | 
			
		||||
      formConfig: [
 | 
			
		||||
        {
 | 
			
		||||
          type: 'select',
 | 
			
		||||
@@ -184,9 +187,9 @@ export default {
 | 
			
		||||
    // AddOrUpdate,
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
    window.addEventListener('resize', () => {
 | 
			
		||||
      this.tableH = this.tableHeight(260)
 | 
			
		||||
    })
 | 
			
		||||
    // window.addEventListener('resize', () => {
 | 
			
		||||
    //   this.tableH = this.tableHeight(260)
 | 
			
		||||
    // })
 | 
			
		||||
    this.getList()
 | 
			
		||||
    this.getDict()
 | 
			
		||||
  },
 | 
			
		||||
 
 | 
			
		||||
@@ -2,13 +2,14 @@
 | 
			
		||||
 * @Author: zwq
 | 
			
		||||
 * @Date: 2023-08-01 14:55:51
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @LastEditTime: 2024-03-20 09:25:40
 | 
			
		||||
 * @LastEditTime: 2024-03-29 15:32:33
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="app-container">
 | 
			
		||||
    <search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
 | 
			
		||||
    <base-table :table-props="tableProps" :page="listQuery.pageNo" :limit="listQuery.pageSize" :table-data="list">
 | 
			
		||||
    <base-table :max-height="tableH" :table-props="tableProps" :page="listQuery.pageNo" :limit="listQuery.pageSize"
 | 
			
		||||
      :table-data="list">
 | 
			
		||||
      <method-btn v-if="tableBtn.length" slot="handleBtn" :width="120" label="操作" :method-list="tableBtn"
 | 
			
		||||
        @clickBtn="handleClick" />
 | 
			
		||||
    </base-table>
 | 
			
		||||
@@ -30,6 +31,7 @@ import {
 | 
			
		||||
  // exportEnergyPlcExcel
 | 
			
		||||
} from '@/api/quality/processTraceability';
 | 
			
		||||
import { publicFormatter } from '@/utils/dict';
 | 
			
		||||
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
 | 
			
		||||
const tableProps = [
 | 
			
		||||
  {
 | 
			
		||||
    prop: 'name',
 | 
			
		||||
@@ -78,7 +80,7 @@ const tableProps = [
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  // mixins: [basicPage],
 | 
			
		||||
  mixins: [tableHeightMixin],
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      // urlOptions: {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,7 @@
 | 
			
		||||
<!--
 | 
			
		||||
 * @Author: zhp
 | 
			
		||||
 * @Date: 2023-11-09 16:32:21
 | 
			
		||||
 * @LastEditTime: 2023-11-09 16:32:21
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
<!--
 | 
			
		||||
 * @Author: zhp
 | 
			
		||||
 * @Date: 2023-11-07 19:28:13
 | 
			
		||||
 * @LastEditTime: 2023-11-08 14:11:43
 | 
			
		||||
 * @LastEditTime: 2024-03-29 14:21:52
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,10 @@
 | 
			
		||||
<!--
 | 
			
		||||
 * @Author: zhp
 | 
			
		||||
 * @Date: 2023-11-28 10:41:50
 | 
			
		||||
 * @LastEditTime: 2023-11-28 10:49:43
 | 
			
		||||
 * @LastEditTime: 2024-03-29 14:14:13
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
<!--
 | 
			
		||||
    filename: index.vue
 | 
			
		||||
    author: liubin
 | 
			
		||||
    date: 2023-10-18 12:25:46
 | 
			
		||||
    description:
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
	<div class="app-container process-flow-view">
 | 
			
		||||
		<ProcessInfo />
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
<!--
 | 
			
		||||
 * @Author: Do not edit
 | 
			
		||||
 * @Date: 2023-12-13 14:10:04
 | 
			
		||||
 * @LastEditTime: 2024-03-27 09:22:51
 | 
			
		||||
 * @LastEditTime: 2024-03-29 09:43:52
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <el-row style="float: right; margin-bottom: 5px">
 | 
			
		||||
      <el-button v-if="!edit" size="small" @click="edit = true">编辑</el-button>
 | 
			
		||||
      <el-button v-if="!edit" :disabled="noData" size="small" @click="edit = true">编辑</el-button>
 | 
			
		||||
      <el-button v-if="edit" size="small" @click="handleReturn()">返回</el-button>
 | 
			
		||||
      <el-button v-if="edit" size="small" @click="updateData">保存</el-button>
 | 
			
		||||
    </el-row>
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
          <el-table-column v-for="(y, index2) in it.children" :key="index2" :prop="y.prop" :label="y.label">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <span v-if="!edit">{{ scope.row[y.prop] }}</span>
 | 
			
		||||
              <el-input @change="handleChange" :disabled="y.prop == 'dailyOutputTrend' || y.prop === 'originalGlassStatisticsTrend'
 | 
			
		||||
              <el-input type="number" @change="handleChange" :disabled="y.prop == 'dailyOutputTrend' || y.prop === 'originalGlassStatisticsTrend'
 | 
			
		||||
                 || y.prop === 'actualProductTrend' || y.prop === 'originalGlassPassTrend' || y.prop === 'originalGlassPassNow' || y.prop === 'originalGlassPassHis'
 | 
			
		||||
              " v-else v-model="scope.row[y.prop]"></el-input>
 | 
			
		||||
            </template>
 | 
			
		||||
@@ -158,9 +158,19 @@ const cols = [
 | 
			
		||||
        cols,
 | 
			
		||||
        remark:null,
 | 
			
		||||
        edit: false,
 | 
			
		||||
        noData:false,
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
    watch: {
 | 
			
		||||
  watch: {
 | 
			
		||||
    data: {
 | 
			
		||||
      handler(newv, oldv) {
 | 
			
		||||
        if (newv.length != 0) {
 | 
			
		||||
          this.noData = false
 | 
			
		||||
        } else {
 | 
			
		||||
          this.noData = true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      },
 | 
			
		||||
      time: {
 | 
			
		||||
        immediate: true,
 | 
			
		||||
        handler(newv, oldv) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
<!--
 | 
			
		||||
 * @Author: zhp
 | 
			
		||||
 * @Date: 2023-12-12 13:45:25
 | 
			
		||||
 * @LastEditTime: 2024-03-27 09:21:00
 | 
			
		||||
 * @LastEditTime: 2024-03-29 09:48:24
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
@@ -17,7 +17,7 @@
 | 
			
		||||
        @click="handleExport">导出</el-button>
 | 
			
		||||
    </el-form>
 | 
			
		||||
    <el-row style="float: right; margin-bottom: 5px">
 | 
			
		||||
      <el-button v-if="!isSave" size="small" @click="editDataList()">编辑</el-button>
 | 
			
		||||
      <el-button v-if="!isSave" :disabled="noData" size="small" @click="editDataList()">编辑</el-button>
 | 
			
		||||
      <el-button v-if="isSave" size="small" @click="handleReturn()">返回</el-button>
 | 
			
		||||
      <el-button size="small" v-if="isSave" @click="saveDataList()">保存</el-button>
 | 
			
		||||
    </el-row>
 | 
			
		||||
@@ -28,59 +28,61 @@
 | 
			
		||||
      <el-table-column :label="'许昌安彩日成品生产汇总' + '(' + timeTips + ')'" align="center">
 | 
			
		||||
        <el-table-column prop="lineName" label="生产线" align="center">
 | 
			
		||||
          <template slot-scope="scope">
 | 
			
		||||
            <el-input v-if="!disabled" v-model="scope.row.lineName" :disabled="disabled"></el-input>
 | 
			
		||||
            <el-input  v-if="!disabled"  type="number" v-model="scope.row.lineName" :disabled="disabled"></el-input>
 | 
			
		||||
            <span v-else>{{ scope.row.lineName }} </span>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="投入数㎡" align="center">
 | 
			
		||||
          <el-table-column prop="inputNow" label="今日" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.inputNow" :disabled="disabled"></el-input>
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.inputNow" :disabled="disabled"></el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.inputNow }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="inputHis" label="昨日" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.inputHis" :disabled="disabled"></el-input>
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.inputHis" :disabled="disabled"></el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.inputHis }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="inputTrend" label="增减" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.inputTrend" :disabled="!disabled"></el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.inputTrend ? parseFloat((scope.row.inputTrend * 100).toFixed(2)) + '%' :
 | 
			
		||||
              null}} </span>
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.inputTrend" :disabled="!disabled"></el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.inputTrend && scope.row.inputTrend != 0 ? parseFloat((scope.row.inputTrend *
 | 
			
		||||
              100).toFixed(2)) + '%' : scope.row.inputTrend == 0 ? 0 : null }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="完成良品产量" align="center">
 | 
			
		||||
          <el-table-column prop="goodProductNow" label="今日" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.goodProductNow" :disabled="disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.goodProductNow" :disabled="disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductNow }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="goodProductHis" label="昨日" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.goodProductHis" :disabled="disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.goodProductHis" :disabled="disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductHis }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="goodProductTrend" label="增减" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.goodProductTrend" :disabled="!disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.goodProductTrend" :disabled="!disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductTrend ? parseFloat((scope.row.goodProductTrend * 100).toFixed(2)) +
 | 
			
		||||
              '%' : null }} </span>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductTrend && scope.row.goodProductTrend != 0 ?
 | 
			
		||||
                parseFloat((scope.row.goodProductTrend * 100).toFixed(2)) + '%' : scope.row.goodProductTrend == 0 ? 0 :
 | 
			
		||||
              null
 | 
			
		||||
              }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="原片漏检率" align="center">
 | 
			
		||||
          <el-table-column prop="missCheckNow" label="今日" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.missCheckNow" :disabled="disabled"></el-input>
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.missCheckNow" :disabled="disabled"></el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.missCheckNow ? parseFloat((scope.row.missCheckNow *
 | 
			
		||||
              100).toFixed(2)) +
 | 
			
		||||
              '%' : null }}
 | 
			
		||||
@@ -89,7 +91,7 @@
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="missCheckHis" label="昨日" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.missCheckHis" :disabled="disabled"></el-input>
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.missCheckHis" :disabled="disabled"></el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.missCheckHis ? parseFloat((scope.row.missCheckHis *
 | 
			
		||||
              100).toFixed(2)) +
 | 
			
		||||
              '%' : null }}
 | 
			
		||||
@@ -98,19 +100,18 @@
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="missCheckTrend" label="增减" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.missCheckTrend" :disabled="!disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.missCheckTrend" :disabled="!disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.missCheckTrend ? parseFloat((scope.row.missCheckTrend *
 | 
			
		||||
              100).toFixed(2)) +
 | 
			
		||||
              '%' : null }}
 | 
			
		||||
              </span>
 | 
			
		||||
              <span v-else>{{ scope.row.missCheckTrend && scope.row.missCheckTrend != 0 ?
 | 
			
		||||
              parseFloat((scope.row.missCheckTrend * 100).toFixed(2)) + '%' : scope.row.missCheckTrend == 0 ? 0 : null
 | 
			
		||||
              }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="综合良品率" align="center">
 | 
			
		||||
          <el-table-column prop="goodProductPassNow" label="今日" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.goodProductPassNow" :disabled="!disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.goodProductPassNow" :disabled="!disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductPassNow ? parseFloat((scope.row.goodProductPassNow *
 | 
			
		||||
              100).toFixed(2)) +
 | 
			
		||||
@@ -120,7 +121,7 @@
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="goodProductPassHis" label="昨日" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.goodProductPassHis" :disabled="!disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.goodProductPassHis" :disabled="!disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductPassHis ? parseFloat((scope.row.goodProductPassHis *
 | 
			
		||||
              100).toFixed(2)) +
 | 
			
		||||
@@ -130,12 +131,13 @@
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="goodProductPassTrend" label="增减" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.goodProductPassTrend" :disabled="!disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.goodProductPassTrend" :disabled="!disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductPassTrend ? parseFloat((scope.row.goodProductPassTrend *
 | 
			
		||||
                            100).toFixed(2)) +
 | 
			
		||||
              '%' : null }}
 | 
			
		||||
              </span>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductPassTrend && scope.row.goodProductPassTrend != 0 ?
 | 
			
		||||
              parseFloat((scope.row.goodProductPassTrend * 100).toFixed(2)) + '%' : scope.row.goodProductPassTrend ==
 | 
			
		||||
              0 ? 0 :
 | 
			
		||||
              null
 | 
			
		||||
              }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
@@ -284,6 +286,7 @@ export default {
 | 
			
		||||
      urlOptions: {
 | 
			
		||||
        exportURL: exportProductExcel
 | 
			
		||||
      },
 | 
			
		||||
      noData:false,
 | 
			
		||||
      isSave:false,
 | 
			
		||||
      disabled: true,
 | 
			
		||||
      sumArr: [],
 | 
			
		||||
@@ -631,6 +634,11 @@ export default {
 | 
			
		||||
        params: this.listQuery
 | 
			
		||||
      })
 | 
			
		||||
      console.log(res)
 | 
			
		||||
      if (res.data.list.length == 0) {
 | 
			
		||||
        this.noData = true
 | 
			
		||||
      } else {
 | 
			
		||||
        this.noData = false
 | 
			
		||||
      }
 | 
			
		||||
      // let sum = undefined
 | 
			
		||||
      // res.data.list.forEach((ele, index) => {
 | 
			
		||||
      //   if (ele.det === false) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
<!--
 | 
			
		||||
 * @Author: zhp
 | 
			
		||||
 * @Date: 2023-12-12 13:45:25
 | 
			
		||||
 * @LastEditTime: 2024-03-26 09:41:33
 | 
			
		||||
 * @LastEditTime: 2024-03-29 09:48:32
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
@@ -17,7 +17,7 @@
 | 
			
		||||
        @click="handleExport">导出</el-button>
 | 
			
		||||
    </el-form>
 | 
			
		||||
    <el-row style="float: right; margin-bottom: 5px">
 | 
			
		||||
      <el-button v-if="!isSave" size="small" @click="editDataList()">编辑</el-button>
 | 
			
		||||
      <el-button v-if="!isSave" :disabled="noData" size="small" @click="editDataList()">编辑</el-button>
 | 
			
		||||
      <el-button v-if="isSave" size="small" @click="handleReturn()">返回</el-button>
 | 
			
		||||
      <el-button size="small" v-if="isSave" @click="saveDataList()">保存</el-button>
 | 
			
		||||
    </el-row>
 | 
			
		||||
@@ -28,114 +28,122 @@
 | 
			
		||||
      <el-table-column :label="'许昌安彩月成品生产汇总' + '(' + timeTips + ')'" align="center">
 | 
			
		||||
        <el-table-column prop="lineId" label="生产线" align="center">
 | 
			
		||||
          <template slot-scope="scope">
 | 
			
		||||
            <el-input v-if="!disabled" v-model="scope.row.lineName" :disabled="disabled"></el-input>
 | 
			
		||||
            <el-input  v-if="!disabled"  type="number" v-model="scope.row.lineName" :disabled="disabled"></el-input>
 | 
			
		||||
            <span v-else>{{ scope.row.lineName }} </span>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="投入数㎡" align="center">
 | 
			
		||||
          <el-table-column prop="inputNow" label="本月" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.inputNow" :disabled="disabled"></el-input>
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.inputNow" :disabled="disabled"></el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.inputNow }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="inputHis" label="上月" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.inputHis" :disabled="disabled"></el-input>
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.inputHis" :disabled="disabled"></el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.inputHis }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="inputTrend" label="增减" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.inputTrend" :disabled="!disabled"></el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.inputTrend ? parseFloat((scope.row.inputTrend *
 | 
			
		||||
                100).toFixed(2)) + '%' : undefined }} </span>
 | 
			
		||||
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.inputTrend" :disabled="!disabled"></el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.inputTrend && scope.row.inputTrend != 0 ?
 | 
			
		||||
              parseFloat((scope.row.inputTrend * 100).toFixed(2)) + '%' : scope.row.inputTrend == 0 ? 0 :
 | 
			
		||||
              null
 | 
			
		||||
              }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="完成良品产量" align="center">
 | 
			
		||||
          <el-table-column prop="goodProductNow" label="本月" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.goodProductNow" :disabled="disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.goodProductNow" :disabled="disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductNow }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="goodProductHis" label="上月" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.goodProductHis" :disabled="disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.goodProductHis" :disabled="disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductHis }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="goodProductTrend" label="增减" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.goodProductTrend" :disabled="!disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.goodProductTrend" :disabled="!disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductTrend ? parseFloat((scope.row.goodProductTrend *
 | 
			
		||||
                100).toFixed(2)) + '%' : undefined }} </span>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductTrend && scope.row.goodProductTrend != 0 ?
 | 
			
		||||
              parseFloat((scope.row.goodProductTrend * 100).toFixed(2)) + '%' : scope.row.goodProductTrend == 0 ? 0 :
 | 
			
		||||
              null
 | 
			
		||||
              }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="原片漏检率" align="center">
 | 
			
		||||
          <el-table-column prop="missCheckNow" label="本月" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.missCheckNow" :disabled="disabled"></el-input>
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.missCheckNow" :disabled="disabled"></el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.missCheckNow ? parseFloat((scope.row.missCheckNow *
 | 
			
		||||
                100).toFixed(2)) +
 | 
			
		||||
                '%' : undefined }}
 | 
			
		||||
              100).toFixed(2)) +
 | 
			
		||||
              '%' : null }}
 | 
			
		||||
              </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="missCheckHis" label="上月" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.missCheckHis" :disabled="disabled"></el-input>
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.missCheckHis" :disabled="disabled"></el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.missCheckHis ? parseFloat((scope.row.missCheckHis *
 | 
			
		||||
                100).toFixed(2)) +
 | 
			
		||||
                '%' : undefined }}
 | 
			
		||||
              100).toFixed(2)) +
 | 
			
		||||
              '%' : null }}
 | 
			
		||||
              </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="missCheckTrend" label="增减" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.missCheckTrend" :disabled="!disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.missCheckTrend" :disabled="!disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.missCheckTrend ? parseFloat((scope.row.missCheckTrend *
 | 
			
		||||
                100).toFixed(2)) +
 | 
			
		||||
                '%' : undefined }}
 | 
			
		||||
              </span>
 | 
			
		||||
              <span v-else>{{ scope.row.missCheckTrend && scope.row.missCheckTrend != 0 ?
 | 
			
		||||
              parseFloat((scope.row.missCheckTrend * 100).toFixed(2)) + '%' : scope.row.missCheckTrend == 0 ?
 | 
			
		||||
              0 :
 | 
			
		||||
              null
 | 
			
		||||
              }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="综合良品率" align="center">
 | 
			
		||||
          <el-table-column prop="goodProductPassNow" label="本月" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.goodProductPassNow" :disabled="!disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.goodProductPassNow" :disabled="!disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductPassNow ? parseFloat((scope.row.goodProductPassNow *
 | 
			
		||||
                100).toFixed(2)) +
 | 
			
		||||
                '%' : undefined }}
 | 
			
		||||
              100).toFixed(2)) +
 | 
			
		||||
              '%' : null }}
 | 
			
		||||
              </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="goodProductPassHis" label="上月" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.goodProductPassHis" :disabled="!disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.goodProductPassHis" :disabled="!disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductPassHis ? parseFloat((scope.row.goodProductPassHis *
 | 
			
		||||
                100).toFixed(2)) +
 | 
			
		||||
                '%' : undefined }}
 | 
			
		||||
              100).toFixed(2)) +
 | 
			
		||||
              '%' : null }}
 | 
			
		||||
              </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="goodProductPassTrend" label="增减" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.goodProductPassTrend" :disabled="!disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.goodProductPassTrend" :disabled="!disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductPassTrend ? parseFloat((scope.row.goodProductPassTrend *
 | 
			
		||||
                100).toFixed(2)) +
 | 
			
		||||
                '%' : undefined }}
 | 
			
		||||
              </span>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductPassTrend && scope.row.goodProductPassTrend != 0 ?
 | 
			
		||||
                parseFloat((scope.row.goodProductPassTrend * 100).toFixed(2)) + '%' : scope.row.goodProductPassTrend ==
 | 
			
		||||
              0 ?
 | 
			
		||||
              0 :
 | 
			
		||||
              null
 | 
			
		||||
              }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
@@ -288,6 +296,7 @@ export default {
 | 
			
		||||
      isSave:false,
 | 
			
		||||
      disabled: true,
 | 
			
		||||
      sumArr: [],
 | 
			
		||||
      noData:false,
 | 
			
		||||
      timeTips:'',
 | 
			
		||||
      searchBarFormConfig: [
 | 
			
		||||
        // {
 | 
			
		||||
@@ -666,6 +675,11 @@ export default {
 | 
			
		||||
        params: this.dataForm
 | 
			
		||||
      })
 | 
			
		||||
      console.log(res)
 | 
			
		||||
      if (res.data.list.length == 0) {
 | 
			
		||||
        this.noData = true
 | 
			
		||||
      } else {
 | 
			
		||||
        this.noData = false
 | 
			
		||||
      }
 | 
			
		||||
      // let sum = undefined
 | 
			
		||||
      // res.data.list.forEach((ele, index) => {
 | 
			
		||||
      //   if (ele.det === false) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
<!--
 | 
			
		||||
 * @Author: zhp
 | 
			
		||||
 * @Date: 2023-12-12 13:45:25
 | 
			
		||||
 * @LastEditTime: 2024-03-18 15:26:52
 | 
			
		||||
 * @LastEditTime: 2024-03-29 08:51:46
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
@@ -25,7 +25,7 @@
 | 
			
		||||
      background: '#F2F4F9',
 | 
			
		||||
      color: '#606266'
 | 
			
		||||
    }">
 | 
			
		||||
      <el-table-column :label="'许昌安彩周成品发货及库存日报' + '(' + timeTips + ')'" align="center">
 | 
			
		||||
      <el-table-column :label="'许昌安彩成品发货及库存日报' + '(' + timeTips + ')'" align="center">
 | 
			
		||||
        <el-table-column prop="glassType" label="品种" align="center">
 | 
			
		||||
          <template slot-scope="scope">
 | 
			
		||||
            <el-input v-if="!disabled" v-model="scope.row.glassType" :disabled="disabled"></el-input>
 | 
			
		||||
@@ -39,7 +39,7 @@
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="规格" align="center">
 | 
			
		||||
          <el-table-column label="成品" align="center">
 | 
			
		||||
          <el-table-column width="180"  label="成品" align="center">
 | 
			
		||||
            <!-- <el-table-column :show-header="false"> -->
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.productionGlassSize" :disabled="disabled"></el-input>
 | 
			
		||||
@@ -59,7 +59,7 @@
 | 
			
		||||
              </template>
 | 
			
		||||
            </el-table-column> -->
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="originalGlassSize" label="原片" align="center">
 | 
			
		||||
          <el-table-column width="180" prop="originalGlassSize" label="原片" align="center">
 | 
			
		||||
            <!-- <el-table-column prop="originalGlassSize"> -->
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.originalGlassSize" :disabled="disabled">
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
<!--
 | 
			
		||||
 * @Author: zhp
 | 
			
		||||
 * @Date: 2023-12-12 13:45:25
 | 
			
		||||
 * @LastEditTime: 2024-03-26 09:41:51
 | 
			
		||||
 * @LastEditTime: 2024-03-29 09:48:41
 | 
			
		||||
 * @LastEditors: zhp
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
        @click="handleExport">导出</el-button>
 | 
			
		||||
    </el-form>
 | 
			
		||||
    <el-row style="float: right; margin-bottom: 5px">
 | 
			
		||||
      <el-button v-if="!isSave" size="small" @click="editDataList()">编辑</el-button>
 | 
			
		||||
      <el-button v-if="!isSave" :disabled="noData" size="small" @click="editDataList()">编辑</el-button>
 | 
			
		||||
      <el-button v-if="isSave" size="small" @click="handleReturn()">返回</el-button>
 | 
			
		||||
      <el-button size="small" v-if="isSave" @click="saveDataList()">保存</el-button>
 | 
			
		||||
    </el-row>
 | 
			
		||||
@@ -31,114 +31,126 @@
 | 
			
		||||
      <el-table-column :label="'许昌安彩周成品生产汇总' + '(' + timeTips + ')'" align="center">
 | 
			
		||||
        <el-table-column prop="lineId" label="生产线" align="center">
 | 
			
		||||
          <template slot-scope="scope">
 | 
			
		||||
            <el-input v-if="!disabled" v-model="scope.row.lineName" :disabled="disabled"></el-input>
 | 
			
		||||
            <el-input  v-if="!disabled"  type="number" v-model="scope.row.lineName" :disabled="disabled"></el-input>
 | 
			
		||||
            <span v-else>{{ scope.row.lineName }} </span>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="投入数㎡" align="center">
 | 
			
		||||
          <el-table-column prop="inputNow" label="本周" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.inputNow" :disabled="disabled"></el-input>
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.inputNow" :disabled="disabled"></el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.inputNow }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="inputHis" label="上周" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.inputHis" :disabled="disabled"></el-input>
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.inputHis" :disabled="disabled"></el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.inputHis }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="inputTrend" label="增减" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.inputTrend" :disabled="!disabled"></el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.inputTrend ? parseFloat((scope.row.inputTrend *
 | 
			
		||||
                100).toFixed(2)) + '%' : undefined }} </span>
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.inputTrend" :disabled="!disabled"></el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.inputTrend && scope.row.inputTrend != 0 ?
 | 
			
		||||
              parseFloat((scope.row.inputTrend * 100).toFixed(2)) + '%' : scope.row.inputTrend ==
 | 
			
		||||
              0 ?
 | 
			
		||||
              0 :
 | 
			
		||||
              null
 | 
			
		||||
              }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="完成良品产量" align="center">
 | 
			
		||||
          <el-table-column prop="goodProductNow" label="本周" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.goodProductNow" :disabled="disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.goodProductNow" :disabled="disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductNow }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="goodProductHis" label="上周" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.goodProductHis" :disabled="disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.goodProductHis" :disabled="disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductHis }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="goodProductTrend" label="增减" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.goodProductTrend" :disabled="!disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.goodProductTrend" :disabled="!disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductTrend ? parseFloat((scope.row.goodProductTrend *
 | 
			
		||||
                100).toFixed(2)) + '%' : undefined }} </span>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductTrend && scope.row.goodProductTrend != 0 ?
 | 
			
		||||
              parseFloat((scope.row.goodProductTrend * 100).toFixed(2)) + '%' : scope.row.goodProductTrend ==
 | 
			
		||||
              0 ?
 | 
			
		||||
              0 :
 | 
			
		||||
              null
 | 
			
		||||
              }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="原片漏检率" align="center">
 | 
			
		||||
          <el-table-column prop="missCheckNow" label="本周" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.missCheckNow" :disabled="disabled"></el-input>
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.missCheckNow" :disabled="disabled"></el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.missCheckNow ? parseFloat((scope.row.missCheckNow *
 | 
			
		||||
                100).toFixed(2)) +
 | 
			
		||||
                '%' : undefined }}
 | 
			
		||||
              100).toFixed(2)) +
 | 
			
		||||
              '%' : null }}
 | 
			
		||||
              </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="missCheckHis" label="上周" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.missCheckHis" :disabled="disabled"></el-input>
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.missCheckHis" :disabled="disabled"></el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.missCheckHis ? parseFloat((scope.row.missCheckHis *
 | 
			
		||||
                100).toFixed(2)) +
 | 
			
		||||
                '%' : undefined }}
 | 
			
		||||
              100).toFixed(2)) +
 | 
			
		||||
              '%' : null }}
 | 
			
		||||
              </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="missCheckTrend" label="增减" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.missCheckTrend" :disabled="!disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.missCheckTrend" :disabled="!disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.missCheckTrend ? parseFloat((scope.row.missCheckTrend *
 | 
			
		||||
                100).toFixed(2)) +
 | 
			
		||||
                '%' : undefined }}
 | 
			
		||||
              </span>
 | 
			
		||||
              <span v-else>{{ scope.row.missCheckTrend && scope.row.missCheckTrend != 0 ?
 | 
			
		||||
              parseFloat((scope.row.missCheckTrend * 100).toFixed(2)) + '%' : scope.row.missCheckTrend ==
 | 
			
		||||
              0 ?
 | 
			
		||||
              0 :
 | 
			
		||||
              null
 | 
			
		||||
              }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
        <el-table-column label="综合良品率" align="center">
 | 
			
		||||
          <el-table-column prop="goodProductPassNow" label="本周" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.goodProductPassNow" :disabled="!disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.goodProductPassNow" :disabled="!disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductPassNow ? parseFloat((scope.row.goodProductPassNow *
 | 
			
		||||
                100).toFixed(2)) +
 | 
			
		||||
                '%' : undefined }}
 | 
			
		||||
              100).toFixed(2)) +
 | 
			
		||||
              '%' : null }}
 | 
			
		||||
              </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="goodProductPassHis" label="上周" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.goodProductPassHis" :disabled="!disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.goodProductPassHis" :disabled="!disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductPassHis ? parseFloat((scope.row.goodProductPassHis *
 | 
			
		||||
                100).toFixed(2)) +
 | 
			
		||||
                '%' : undefined }}
 | 
			
		||||
              100).toFixed(2)) +
 | 
			
		||||
              '%' : null }}
 | 
			
		||||
              </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
          <el-table-column prop="goodProductPassTrend" label="增减" align="center">
 | 
			
		||||
            <template slot-scope="scope">
 | 
			
		||||
              <el-input v-if="!disabled" v-model="scope.row.goodProductPassTrend" :disabled="!disabled">
 | 
			
		||||
              <el-input  v-if="!disabled"  type="number" v-model="scope.row.goodProductPassTrend" :disabled="!disabled">
 | 
			
		||||
              </el-input>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductPassTrend ? parseFloat((scope.row.goodProductPassTrend *
 | 
			
		||||
                100).toFixed(2)) +
 | 
			
		||||
                '%' : undefined }}
 | 
			
		||||
              </span>
 | 
			
		||||
              <span v-else>{{ scope.row.goodProductPassTrend && scope.row.goodProductPassTrend != 0 ?
 | 
			
		||||
                parseFloat((scope.row.goodProductPassTrend * 100).toFixed(2)) + '%' : scope.row.goodProductPassTrend ==
 | 
			
		||||
              0 ?
 | 
			
		||||
              0 :
 | 
			
		||||
              null
 | 
			
		||||
              }} </span>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-table-column>
 | 
			
		||||
        </el-table-column>
 | 
			
		||||
@@ -296,6 +308,7 @@ export default {
 | 
			
		||||
      isSave:false,
 | 
			
		||||
      disabled: true,
 | 
			
		||||
      sumArr: [],
 | 
			
		||||
      noData:false,
 | 
			
		||||
      weekValue1: null,//最多24周
 | 
			
		||||
      weekValue2: null,
 | 
			
		||||
      searchBarFormConfig: [
 | 
			
		||||
@@ -629,6 +642,11 @@ export default {
 | 
			
		||||
      })
 | 
			
		||||
      // console.log(this.queryParams);
 | 
			
		||||
      console.log(res)
 | 
			
		||||
      if (res.data.list.length == 0) {
 | 
			
		||||
        this.noData = true
 | 
			
		||||
      } else {
 | 
			
		||||
        this.noData = false
 | 
			
		||||
      }
 | 
			
		||||
      // let sum = undefined
 | 
			
		||||
      // res.data.list.forEach((ele, index) => {
 | 
			
		||||
      //   if (ele.det === false) {
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user