From 8c65ac7d16f2ae50d2482bda43277fb4e6307128 Mon Sep 17 00:00:00 2001 From: Odboy Date: Mon, 24 Mar 2025 20:10:58 +0800 Subject: [PATCH] =?UTF-8?q?upd:=20=E7=BC=96=E7=A0=81=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cutejava-ui/package.json | 5 +- cutejava-ui/src/components/JavaEdit/index.vue | 2 +- cutejava-ui/src/main.js | 55 ++++++ cutejava-ui/src/store/modules/api.js | 6 +- cutejava-ui/src/utils/commands.js | 20 ++ cutejava-ui/src/utils/index.js | 31 +-- cutejava-ui/src/utils/myCmd.js | 20 ++ cutejava-ui/src/utils/myElement.js | 183 ++++++++++++++++++ cutejava-ui/src/utils/mySocket.js | 43 ++++ cutejava-ui/src/utils/myUtil.js | 83 ++++++++ cutejava-ui/src/utils/websocket.js | 42 ++++ .../src/views/components/ClipboardDemo.vue | 61 ++++++ .../src/views/components/CodemirrorDemo.vue | 18 ++ .../src/views/components/CountToDemo.vue | 40 ++++ .../src/views/components/DragTableDemo.vue | 71 +++++++ .../src/views/components/OneKeyCopy.vue | 44 +++++ .../src/views/components/SplitPaneDemo.vue | 67 +++++++ .../src/views/components/WebSocketDemo.vue | 80 ++++++++ cutejava-ui/src/views/devops/demo.vue | 26 +++ cutejava-ui/src/views/login.vue | 89 +++++---- .../src/views/monitor/online/index.vue | 1 - .../src/views/tools/storage/local/index.vue | 2 +- .../src/views/tools/storage/qiniu/form.vue | 2 +- 23 files changed, 920 insertions(+), 71 deletions(-) create mode 100644 cutejava-ui/src/utils/commands.js create mode 100644 cutejava-ui/src/utils/myCmd.js create mode 100644 cutejava-ui/src/utils/myElement.js create mode 100644 cutejava-ui/src/utils/mySocket.js create mode 100644 cutejava-ui/src/utils/myUtil.js create mode 100644 cutejava-ui/src/utils/websocket.js create mode 100644 cutejava-ui/src/views/components/ClipboardDemo.vue create mode 100644 cutejava-ui/src/views/components/CodemirrorDemo.vue create mode 100644 cutejava-ui/src/views/components/CountToDemo.vue create mode 100644 cutejava-ui/src/views/components/DragTableDemo.vue create mode 100644 cutejava-ui/src/views/components/OneKeyCopy.vue create mode 100644 cutejava-ui/src/views/components/SplitPaneDemo.vue create mode 100644 cutejava-ui/src/views/components/WebSocketDemo.vue create mode 100644 cutejava-ui/src/views/devops/demo.vue diff --git a/cutejava-ui/package.json b/cutejava-ui/package.json index 9736d352..3f986738 100644 --- a/cutejava-ui/package.json +++ b/cutejava-ui/package.json @@ -56,7 +56,8 @@ "qs": "^6.10.1", "screenfull": "4.2.0", "sortablejs": "1.8.4", - "vue": "^2.6.14", + "vue": "2.7.16", + "vue-clipboard2": "^0.3.3", "vue-count-to": "^1.0.13", "vue-cropper": "0.4.9", "vue-echarts": "^5.0.0-beta.0", @@ -102,7 +103,7 @@ "svg-sprite-loader": "4.1.3", "svgo": "1.2.0", "tasksfile": "^5.1.1", - "vue-template-compiler": "2.7.15" + "vue-template-compiler": "2.7.16" }, "engines": { "node": ">=8.9", diff --git a/cutejava-ui/src/components/JavaEdit/index.vue b/cutejava-ui/src/components/JavaEdit/index.vue index 2939e36a..7bb78bec 100644 --- a/cutejava-ui/src/components/JavaEdit/index.vue +++ b/cutejava-ui/src/components/JavaEdit/index.vue @@ -47,7 +47,7 @@ export default { cursorHeight: 0.9, // 替换主题这里需修改名称 theme: 'idea', - readOnly: true + readOnly: false }) this.editor.setSize('auto', this.height) this.editor.setValue(this.value) diff --git a/cutejava-ui/src/main.js b/cutejava-ui/src/main.js index a6f5eec2..0b8bad80 100644 --- a/cutejava-ui/src/main.js +++ b/cutejava-ui/src/main.js @@ -9,6 +9,15 @@ import Element from 'element-ui' // 数据字典 import dict from './components/Dict' +// 防止二次提交 +import { preventReClick } from '@/utils/commands' + +// 一键复制插件 +import VueClipboard from 'vue-clipboard2' + +// 窗口分割组件 +import SplitPane from 'vue-splitpane' + // 权限指令 import checkPer from '@/utils/permission' import permission from './components/Permission' @@ -27,10 +36,56 @@ import './router/index' // permission control Vue.use(checkPer) Vue.use(permission) Vue.use(dict) +Vue.use(preventReClick) +Vue.use(VueClipboard) Vue.use(Element, { size: Cookies.get('size') || 'small' // set element-ui default size }) +Vue.component('split-pane', SplitPane) + +/** + * 日期格式化
+ * 例子: {{ scope.row.createTime | dateFormat }} + */ +Vue.filter('dateFormat', function(originVal) { + if (originVal === undefined) { + return '' + } + const dt = new Date(originVal) + const y = dt.getFullYear() + const m = (dt.getMonth() + 1 + '').padStart(2, '0') + const d = (dt.getDate() + '').padStart(2, '0') + return `${y}-${m}-${d}` +}) + +/** + * 日期时间格式化 + */ +Vue.filter('dateTimeFormat', function(originVal) { + if (originVal === undefined) { + return '' + } + const dt = new Date(originVal) + const y = dt.getFullYear() + const m = (dt.getMonth() + 1 + '').padStart(2, '0') + const d = (dt.getDate() + '').padStart(2, '0') + const hh = (dt.getHours() + '').padStart(2, '0') + const mm = (dt.getMinutes() + '').padStart(2, '0') + const ss = (dt.getSeconds() + '').padStart(2, '0') + return `${y}-${m}-${d} ${hh}:${mm}:${ss}` +}) + +/** + * 金额格式化 + */ +Vue.filter('priceFormat', function(data) { + if (data !== undefined && data != null) { + return data.toFixed(2) + } + return 0.00 +}) + Vue.config.productionTip = false new Vue({ diff --git a/cutejava-ui/src/store/modules/api.js b/cutejava-ui/src/store/modules/api.js index 563c5788..aa898f2f 100644 --- a/cutejava-ui/src/store/modules/api.js +++ b/cutejava-ui/src/store/modules/api.js @@ -2,10 +2,6 @@ const baseUrl = process.env.VUE_APP_BASE_API === '/' ? '' : process.env.VUE_APP_BASE_API const api = { state: { - // 部署包上传 - deployUploadApi: baseUrl + '/api/deploy/upload', - // SQL脚本上传 - databaseUploadApi: baseUrl + '/api/database/upload', // 图片上传 imagesUploadApi: baseUrl + '/api/localStorage/pictures', // 修改头像 @@ -14,6 +10,8 @@ const api = { qiNiuUploadApi: baseUrl + '/api/qiNiuContent', // Sql 监控 sqlApi: baseUrl + '/druid/index.html', + // websocket + websocketApi: baseUrl + '/webSocket/{sid}', // swagger swaggerApi: baseUrl + '/doc.html', // 文件上传 diff --git a/cutejava-ui/src/utils/commands.js b/cutejava-ui/src/utils/commands.js new file mode 100644 index 00000000..246c7da1 --- /dev/null +++ b/cutejava-ui/src/utils/commands.js @@ -0,0 +1,20 @@ +import Vue from 'vue' + +/** + * 防止重复提交指令
+ * 例子: 提交 + */ +const preventReClick = Vue.directive('preventReClick', { + inserted(el, binding) { + el.addEventListener('click', () => { + if (!el.disabled) { + el.disabled = true + setTimeout(() => { + el.disabled = false + }, binding.value || 3000) + } + }) + } +}) + +export { preventReClick } diff --git a/cutejava-ui/src/utils/index.js b/cutejava-ui/src/utils/index.js index ab7ad304..7f5c1ee6 100644 --- a/cutejava-ui/src/utils/index.js +++ b/cutejava-ui/src/utils/index.js @@ -281,28 +281,6 @@ export function debounce(func, wait, immediate) { } } -/** - * This is just a simple version of deep copy - * Has a lot of edge cases bug - * If you want to use a perfect deep copy, use lodash's _.cloneDeep - * @param {Object} source - * @returns {Object} - */ -export function deepClone(source) { - if (!source && typeof source !== 'object') { - throw new Error('error arguments', 'deepClone') - } - const targetObj = source.constructor === Array ? [] : {} - Object.keys(source).forEach(keys => { - if (source[keys] && typeof source[keys] === 'object') { - targetObj[keys] = deepClone(source[keys]) - } else { - targetObj[keys] = source[keys] - } - }) - return targetObj -} - /** * @param {Array} arr * @returns {Array} @@ -386,3 +364,12 @@ export function downloadFile(obj, name, suffix) { link.click() document.body.removeChild(link) } + +// 数组去重 +export const uniqueArrays = (arr) => [...new Set(arr)] + +// 获取变量类型 +export const type = (value) => Object.prototype.toString.call(value).slice(8, -1).toLowerCase() + +// 深拷贝对象 +export const deepClone = (obj) => JSON.parse(JSON.stringify(obj)) diff --git a/cutejava-ui/src/utils/myCmd.js b/cutejava-ui/src/utils/myCmd.js new file mode 100644 index 00000000..246c7da1 --- /dev/null +++ b/cutejava-ui/src/utils/myCmd.js @@ -0,0 +1,20 @@ +import Vue from 'vue' + +/** + * 防止重复提交指令
+ * 例子: 提交 + */ +const preventReClick = Vue.directive('preventReClick', { + inserted(el, binding) { + el.addEventListener('click', () => { + if (!el.disabled) { + el.disabled = true + setTimeout(() => { + el.disabled = false + }, binding.value || 3000) + } + }) + } +}) + +export { preventReClick } diff --git a/cutejava-ui/src/utils/myElement.js b/cutejava-ui/src/utils/myElement.js new file mode 100644 index 00000000..2f8a2aef --- /dev/null +++ b/cutejava-ui/src/utils/myElement.js @@ -0,0 +1,183 @@ +/** + * 消息提示工具 + * @type {{success: MessageUtil.success, warning: MessageUtil.warning, error: MessageUtil.error, info: MessageUtil.info}} + */ +const MessageUtil = { + info: function(context, content) { + context.$message(content) + }, + success: function(context, content) { + context.$message({ + message: content, + type: 'success' + }) + }, + warning: function(context, content) { + context.$message({ + message: content, + type: 'warning' + }) + }, + error: function(context, content) { + context.$message.error(content) + } +} +/** + * 通知工具类 + * @type {{success: NotificationUtil.success, warning: NotificationUtil.warning, error: NotificationUtil.error, info: NotificationUtil.info}} + */ +const NotificationUtil = { + info: function(context, content) { + context.$notify({ + message: content + }) + }, + success: function(context, content) { + context.$notify({ + message: content, + type: 'success' + }) + }, + successDuration: function(context, content, durationTime) { + context.$notify({ + message: content, + type: 'success', + duration: durationTime + }) + }, + warning: function(context, content) { + context.$notify({ + message: content, + type: 'warning' + }) + }, + error: function(context, content) { + context.$notify({ + message: content, + type: 'error' + }) + }, + errorDuration: function(context, content, durationTime) { + context.$notify({ + message: content, + type: 'error', + duration: durationTime + }) + } +} + +const MessageBoxUtil = { + /** + * 确认消息对话框
+ * 提示用户确认其已经触发的动作, 并询问是否进行此操作时会用到此对话框 + * @param context 上下文 + * @param questionText 提示语 + * @param msgType 消息类型(w、i、e、s) + * @param confirmCallBack 确认回调 + * @param cancelCallBack 取消回调 + */ + fullConfirm: function(context, questionText, msgType, confirmCallBack, cancelCallBack) { + let currentType = 'info' + if (msgType === 's') { + currentType = 'success' + } else if (msgType === 'e') { + currentType = 'error' + } else if (msgType === 'i') { + currentType = 'info' + } else if (msgType === 'w') { + currentType = 'warning' + } + context.$confirm(questionText, '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: currentType + }).then(() => { + if (confirmCallBack != null) { + confirmCallBack() + } + }).catch(() => { + if (cancelCallBack != null) { + cancelCallBack() + } + }) + }, + /** + * 数据删除确认对话框 + * @param context 上下文 + * @param confirmCallBack 确认回调 + * @param cancelCallBack 取消回调 + */ + deleteConfirm: function(context, confirmCallBack, cancelCallBack) { + this.fullConfirm(context, '确定删除本条数据吗?', 'w', confirmCallBack, cancelCallBack) + }, + /** + * 数据删除确认对话框(自定义提示内容) + * @param context 上下文 + * @param message 提示内容 + * @param confirmCallBack 确认回调 + * @param cancelCallBack 取消回调 + */ + deleteMessageConfirm: function(context, message, confirmCallBack, cancelCallBack) { + this.fullConfirm(context, message, 'w', confirmCallBack, cancelCallBack) + }, + /** + * 数据输入对话框 + * @param context 上下文 + * @param title 标题提示 + * @param patternText 正则表达式 + * @param errorMsg 校验失败消息内容 + * @param confirmCallBack 校验通过回调 + * @param cancelCallBack 取消回调 + */ + textInputConfirm: function(context, title, patternText, errorMsg, confirmCallBack, cancelCallBack) { + context.$prompt('', title, { + confirmButtonText: '确定', + cancelButtonText: '取消', + inputPattern: patternText, + inputErrorMessage: errorMsg + }).then(({ value }) => { + if (confirmCallBack != null) { + confirmCallBack(value) + } + }).catch(() => { + if (cancelCallBack != null) { + cancelCallBack() + } + }) + }, + /** + * 确认内容消息框 + * @param context 上下文 + * @param title 标题 + * @param content 内容 + */ + showConfirm: function(context, title, content) { + context.$alert(content, title, { + confirmButtonText: '关闭' + }) + } +} + +/** + * 全屏加载动画
+ * const loading = LoadingUtil.product() + * loading.close() + * @type {{product: (function(*): *)}} + */ +const LoadingUtil = { + product: function(context) { + return context.$loading({ + lock: true, + text: '数据加载中', + spinner: 'el-icon-loading', + background: 'rgba(0, 0, 0, 0.7)' + }) + } +} + +export { + MessageUtil, + MessageBoxUtil, + NotificationUtil, + LoadingUtil +} diff --git a/cutejava-ui/src/utils/mySocket.js b/cutejava-ui/src/utils/mySocket.js new file mode 100644 index 00000000..791f3e61 --- /dev/null +++ b/cutejava-ui/src/utils/mySocket.js @@ -0,0 +1,43 @@ +/** + * 构造方法式 + * @param context + * @param wsUri + * @constructor + */ +function MyWebSocket(context, wsUri) { + this.context = context + this.wsUri = wsUri + this.webSocket = null + /** + * 初始化WebSocket连接 + * @param handleError -> function (e) { e是异常本身 } + * @param handleMessage -> function (e) { e.data是message } + */ + this.connect = function(handleError, handleMessage) { + this.webSocket = new WebSocket(this.wsUri) + // 连接发生错误 + this.webSocket.onerror = handleError + // 收到消息 + this.webSocket.onmessage = handleMessage + return this + } + /** + * 发送客户端数据 + * @param data 客户端数据 + */ + this.sendData = function(data) { + this.webSocket.send(JSON.stringify(data)) + } + /** + * 用于关闭ws连接 + */ + this.close = function() { + console.info('关闭连接') + if (this.webSocket.readyState === 1) { + this.sendData([{}]) + this.webSocket.close() + } + } +} + +export default MyWebSocket diff --git a/cutejava-ui/src/utils/myUtil.js b/cutejava-ui/src/utils/myUtil.js new file mode 100644 index 00000000..243c9580 --- /dev/null +++ b/cutejava-ui/src/utils/myUtil.js @@ -0,0 +1,83 @@ +import store from '@/store' + +const PermissionUtil = { + /** + * 权限校验 + * @param value + * @returns {boolean|*} + */ + validate: function(value) { + if (value && value instanceof Array && value.length > 0) { + // 拥有的权限 + const roles = store.getters && store.getters.roles + // 需要的权限 + const permissionRoles = value + return roles.some(role => { + return permissionRoles.includes(role) + }) + } else { + console.error(`need roles! Like v-permission="['admin','editor']"`) + return false + } + } +} + +const StringUtil = { + /** + * 字符串转数字 + * @param value + * @returns {Number|*} + */ + toNumber: function(value) { + if (value) { + return Number(value) + } + return 0 + }, + /** + * 保留几位小数 + * @param num Number + * @param accuracy 精度 + * @returns {string|number} + */ + retailNum: function(num, accuracy) { + return num instanceof Number ? num.toFixed(accuracy) : 0 + } +} + +const ObjectUtil = { + /** + * 浅拷贝 + * @param source 源对象 + * @param target 目标对象 + * @returns {*} + */ + copy: function(source, target) { + return Object.assign(target, source) + } +} + +const LabelUtil = { + /** + * 根据value获取label + * @param options / + * @param value / + * @returns {*} + */ + getLabel: function(options, value) { + if (options instanceof Array) { + const find = options.find(f => f.value === value) + if (find) { + return find.label + } + return '' + } + } +} + +export { + PermissionUtil, + StringUtil, + ObjectUtil, + LabelUtil +} diff --git a/cutejava-ui/src/utils/websocket.js b/cutejava-ui/src/utils/websocket.js new file mode 100644 index 00000000..1b6ea910 --- /dev/null +++ b/cutejava-ui/src/utils/websocket.js @@ -0,0 +1,42 @@ +/** + * @param context 上下文,例如 this + * @param wsUri websocket地址 + * @constructor + */ +function EasyWebSocket(context, wsUri) { + this.context = context + this.wsUri = wsUri + this.webSocket = null + /** + * 初始化WebSocket连接 + * @param handleError -> function (e) { e是异常本身 } + * @param handleMessage -> function (e) { e.data是message } + */ + this.connect = function(handleError, handleMessage) { + this.webSocket = new WebSocket(this.wsUri) + // 连接发生错误 + this.webSocket.onerror = handleError + // 收到消息 + this.webSocket.onmessage = handleMessage + return this + } + /** + * 发送客户端数据 + * @param data 客户端数据 + */ + this.sendData = function(data) { + this.webSocket.send(JSON.stringify(data)) + } + /** + * 用于关闭ws连接 + */ + this.close = function() { + console.info('关闭连接') + if (this.webSocket.readyState === 1) { + this.sendData([{}]) + this.webSocket.close() + } + } +} + +export default EasyWebSocket diff --git a/cutejava-ui/src/views/components/ClipboardDemo.vue b/cutejava-ui/src/views/components/ClipboardDemo.vue new file mode 100644 index 00000000..94ca03b2 --- /dev/null +++ b/cutejava-ui/src/views/components/ClipboardDemo.vue @@ -0,0 +1,61 @@ + + + diff --git a/cutejava-ui/src/views/components/CodemirrorDemo.vue b/cutejava-ui/src/views/components/CodemirrorDemo.vue new file mode 100644 index 00000000..f2b7c08c --- /dev/null +++ b/cutejava-ui/src/views/components/CodemirrorDemo.vue @@ -0,0 +1,18 @@ + + + diff --git a/cutejava-ui/src/views/components/CountToDemo.vue b/cutejava-ui/src/views/components/CountToDemo.vue new file mode 100644 index 00000000..83703eb6 --- /dev/null +++ b/cutejava-ui/src/views/components/CountToDemo.vue @@ -0,0 +1,40 @@ + + + + diff --git a/cutejava-ui/src/views/components/DragTableDemo.vue b/cutejava-ui/src/views/components/DragTableDemo.vue new file mode 100644 index 00000000..34d1a9ca --- /dev/null +++ b/cutejava-ui/src/views/components/DragTableDemo.vue @@ -0,0 +1,71 @@ + + + diff --git a/cutejava-ui/src/views/components/OneKeyCopy.vue b/cutejava-ui/src/views/components/OneKeyCopy.vue new file mode 100644 index 00000000..15873401 --- /dev/null +++ b/cutejava-ui/src/views/components/OneKeyCopy.vue @@ -0,0 +1,44 @@ + + + + + + + diff --git a/cutejava-ui/src/views/components/SplitPaneDemo.vue b/cutejava-ui/src/views/components/SplitPaneDemo.vue new file mode 100644 index 00000000..7b80ad8a --- /dev/null +++ b/cutejava-ui/src/views/components/SplitPaneDemo.vue @@ -0,0 +1,67 @@ + + + + + diff --git a/cutejava-ui/src/views/components/WebSocketDemo.vue b/cutejava-ui/src/views/components/WebSocketDemo.vue new file mode 100644 index 00000000..c585158e --- /dev/null +++ b/cutejava-ui/src/views/components/WebSocketDemo.vue @@ -0,0 +1,80 @@ + + + diff --git a/cutejava-ui/src/views/devops/demo.vue b/cutejava-ui/src/views/devops/demo.vue new file mode 100644 index 00000000..5669f5c9 --- /dev/null +++ b/cutejava-ui/src/views/devops/demo.vue @@ -0,0 +1,26 @@ + + + + diff --git a/cutejava-ui/src/views/login.vue b/cutejava-ui/src/views/login.vue index cd19441f..8c6de004 100644 --- a/cutejava-ui/src/views/login.vue +++ b/cutejava-ui/src/views/login.vue @@ -168,47 +168,58 @@ export default { + diff --git a/cutejava-ui/src/views/monitor/online/index.vue b/cutejava-ui/src/views/monitor/online/index.vue index cc5e427a..e707d50f 100644 --- a/cutejava-ui/src/views/monitor/online/index.vue +++ b/cutejava-ui/src/views/monitor/online/index.vue @@ -23,7 +23,6 @@ - diff --git a/cutejava-ui/src/views/tools/storage/local/index.vue b/cutejava-ui/src/views/tools/storage/local/index.vue index ca705bb3..3eb7efba 100644 --- a/cutejava-ui/src/views/tools/storage/local/index.vue +++ b/cutejava-ui/src/views/tools/storage/local/index.vue @@ -93,7 +93,7 @@ - + diff --git a/cutejava-ui/src/views/tools/storage/qiniu/form.vue b/cutejava-ui/src/views/tools/storage/qiniu/form.vue index c77904e9..365f8576 100644 --- a/cutejava-ui/src/views/tools/storage/qiniu/form.vue +++ b/cutejava-ui/src/views/tools/storage/qiniu/form.vue @@ -40,7 +40,7 @@ import { get, update } from '@/api/tools/qiniu' export default { data() { return { - zones: ['华东', '华北', '华南', '北美', '东南亚'], dialog: false, + zones: ['华东', '华北', '东南亚'], dialog: false, loading: false, form: { accessKey: '', secretKey: '', bucket: '', host: '', zone: '', type: '' }, rules: { accessKey: [