refactor(front): 重构前端组件并优化代码

- 移除了多个无用的组件和文件
- 更新了部分组件的实现方式
- 优化了代码结构和样式
- 修复了CuteSimpleTable、CuteDragTable组件,在无数据时,数据表格不刷新问题
This commit is contained in:
2025-07-17 20:39:09 +08:00
parent 4fa3c27b3b
commit ebbfac2774
29 changed files with 757 additions and 698 deletions
@@ -0,0 +1,117 @@
<!--Yaml编辑器 基于-->
<!--<a href="https://github.com/codemirror/CodeMirror" target="_blank">CodeMirror</a>,-->
<!--主题预览地址 <a href="https://codemirror.net/demo/theme.html#idea" target="_blank">Theme</a>-->
<!--</p>-->
<!-- mode取值如下:yaml、java、go、swift、dockerfile、groovy、lua、perl、python、ruby、sql、xml、vue -->
<template>
<textarea ref="textarea" />
</template>
<script>
import CodeMirror from 'codemirror'
import 'codemirror/lib/codemirror.css'
// 替换主题这里需修改名称
// 主题预览地址 https://blog.csdn.net/qq_41694291/article/details/106429772
import 'codemirror/theme/darcula.css'
import 'codemirror/mode/javascript/javascript'
import 'codemirror/mode/yaml/yaml'
import 'codemirror/mode/go/go'
import 'codemirror/mode/swift/swift'
import 'codemirror/mode/dockerfile/dockerfile'
import 'codemirror/mode/groovy/groovy'
import 'codemirror/mode/lua/lua'
import 'codemirror/mode/perl/perl'
import 'codemirror/mode/python/python'
import 'codemirror/mode/ruby/ruby'
import 'codemirror/mode/sql/sql'
import 'codemirror/mode/vue/vue'
import 'codemirror/mode/xml/xml'
import { Message } from 'element-ui'
const SupportModeList = ['yaml', 'java', 'go', 'swift', 'dockerfile', 'groovy', 'lua', 'perl', 'python', 'ruby', 'sql', 'xml', 'vue']
export default {
name: 'CuteCodeEditor',
props: {
content: {
type: String,
required: true,
default: ''
},
height: {
type: String,
required: false,
default: '500px'
},
readOnly: {
type: Boolean,
required: false,
default: false
},
mode: {
type: String,
required: false,
default: 'yaml'
}
},
data() {
return {
editor: false
}
},
watch: {
content(newVal, oldVal) {
const editorValue = this.editor.getValue()
if (newVal !== editorValue) {
this.editor.setValue(newVal)
}
},
height(newVal, oldVal) {
this.editor.setSize('auto', newVal)
}
},
mounted() {
if (this.mode && SupportModeList.includes(this.mode)) {
let mode = 'yaml'
if (this.mode === 'java' || this.mode === 'javascript') {
mode = 'javascript'
} else {
mode = this.mode
}
this.editor = CodeMirror.fromTextArea(this.$refs.textarea, {
mode: mode,
autoRefresh: true,
lineNumbers: true,
lint: true,
lineWrapping: true,
tabSize: 2,
cursorHeight: 1,
// 替换主题这里需修改名称
theme: 'darcula'
})
this.editor.setSize('auto', this.height)
if (this.content) {
this.editor.setValue(this.content)
}
this.editor.setOption('readOnly', this.readOnly)
this.editor.on('change', cm => {
this.$emit('change', cm.getValue())
})
return
}
Message.error('不支持的mode')
},
methods: {
getValue() {
if (this.editor == null) {
return ''
}
return this.editor.getValue()
},
setValue(val) {
if (this.editor == null) {
return
}
this.editor.setValue(val)
}
}
}
</script>
@@ -49,11 +49,6 @@ export default {
required: true,
default: null
},
dataSource: {
type: Array,
required: false,
default: null
},
fetch: {
type: Function,
required: false,
@@ -94,7 +89,7 @@ export default {
columns: this.columns && this.columns.length > 0 ? this.columns : [],
operateColumn: this.operateColumn,
fetchUrl: null,
dataSource: this.dataSource && this.dataSource.length > 0 ? this.dataSource : [],
dataSource: [],
onPageChange: (currentPage, pageSize) => {
this.pageProps.current = currentPage
this.pageProps.pageSize = pageSize
@@ -114,11 +109,6 @@ export default {
this.initDragTable()
},
async initData() {
// 以dataSource属性为准
if (this.dataSource) {
this.crud.dataSource = this.dataSource
return
}
let params = {}
// 自定义请求参数
if (this.paramsTransform) {
@@ -135,7 +125,7 @@ export default {
if (this.responseTransform) {
return this.responseTransform(response)
}
if (response && response.totalElements && response.content) {
if (response && response.hasOwnProperty('totalElements') && response.hasOwnProperty('content')) {
this.pageProps.total = response.totalElements
this.crud.dataSource = response.content
}
@@ -1,10 +1,19 @@
<template>
<el-dialog :title="title" :visible.sync="visible" :width="width" :fullscreen="fullscreen" :before-close="beforeClose">
<el-form ref="form" :model="form.model" :rules="form.rules">
<!-- 这里是插槽,用于渲染传入的 el-form-item -->
<slot />
</el-form>
<div slot="footer" class="dialog-footer">
<el-dialog
:title="title"
:visible.sync="visible"
:width="width"
:fullscreen="fullscreen"
:before-close="beforeClose"
>
<div class="container-form">
<el-form ref="form" :model="form.model" :rules="form.rules">
<!-- 这里是插槽,用于渲染传入的 el-form-item -->
<slot />
</el-form>
</div>
<el-divider />
<div class="dialog-footer" style="padding-right: 30px;text-align: right">
<el-button type="danger" @click="hidden">取 消</el-button>
<!--<el-button @click="resetForm('form')">重 置</el-button>-->
<el-button type="primary" @click="submitForm('form')">提 交</el-button>
@@ -69,4 +78,16 @@ export default {
}
}
</script>
<style scoped>
.container-form {
overflow-y: scroll; /* 启用滚动 */
scrollbar-width: none; /* Firefox */
padding-right: 20px;
-ms-overflow-style: none; /* Internet Explorer 10+ */
}
.container-form::-webkit-scrollbar {
display: none; /* Chrome, Safari, Opera*/
}
</style>
@@ -0,0 +1,91 @@
<template>
<el-drawer
:title="title"
:visible.sync="visible"
:size="width"
:before-close="beforeClose"
:append-to-body="true"
:close-on-press-escape="false"
:destroy-on-close="true"
:show-close="false"
>
<div class="container-form">
<el-form ref="form" :model="form.model" :rules="form.rules">
<!-- 这里是插槽,用于渲染传入的 el-form-item -->
<slot />
</el-form>
</div>
<el-divider />
<div class="dialog-footer" style="padding-right: 30px;text-align: right">
<el-button type="danger" @click="hidden">取 消</el-button>
<el-button type="primary" @click="submitForm('form')">提 交</el-button>
</div>
</el-drawer>
</template>
<script>
export default {
name: 'CuteFormDrawer',
props: {
title: {
type: String,
required: true,
default: '默认标题'
},
width: {
type: String,
required: false,
default: '40%'
},
form: {
type: Object,
required: true,
default: null
}
},
data() {
return {
visible: false
}
},
methods: {
show() {
this.visible = true
},
hidden() {
this.resetForm('form')
this.visible = false
},
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.$emit('submit', this.form.model)
} else {
return false
}
})
},
resetForm(formName) {
this.$refs[formName].resetFields()
},
beforeClose() {
this.hidden()
}
}
}
</script>
<style scoped>
.container-form {
overflow-y: scroll; /* 启用滚动 */
scrollbar-width: none; /* Firefox */
height: 88%;
padding-right: 20px;
-ms-overflow-style: none; /* Internet Explorer 10+ */
}
.container-form::-webkit-scrollbar {
display: none; /* Chrome, Safari, Opera*/
}
</style>
@@ -0,0 +1,87 @@
<!--Yaml编辑器 基于-->
<!--<a href="https://github.com/codemirror/CodeMirror" target="_blank">CodeMirror</a>,-->
<!--主题预览地址 <a href="https://codemirror.net/demo/theme.html#idea" target="_blank">Theme</a>-->
<!--</p>-->
<template>
<textarea ref="textarea" />
</template>
<script>
import CodeMirror from 'codemirror'
import 'codemirror/lib/codemirror.css'
// 替换主题这里需修改名称
// 主题预览地址 https://blog.csdn.net/qq_41694291/article/details/106429772
import 'codemirror/theme/darcula.css'
import 'codemirror/mode/javascript/javascript'
export default {
name: 'CuteJavaEditor',
props: {
content: {
type: String,
required: true,
default: ''
},
height: {
type: String,
required: false,
default: '500px'
},
readOnly: {
type: Boolean,
required: false,
default: false
}
},
data() {
return {
editor: false
}
},
watch: {
content(newVal, oldVal) {
const editorValue = this.editor.getValue()
if (newVal !== editorValue) {
this.editor.setValue(newVal)
}
},
height(newVal, oldVal) {
this.editor.setSize('auto', newVal)
}
},
mounted() {
this.editor = CodeMirror.fromTextArea(this.$refs.textarea, {
mode: 'javascript',
autoRefresh: true,
lineNumbers: true,
lint: true,
lineWrapping: true,
tabSize: 2,
cursorHeight: 1,
// 替换主题这里需修改名称
theme: 'darcula'
})
this.editor.setSize('auto', this.height)
if (this.content) {
this.editor.setValue(this.content)
}
this.editor.setOption('readOnly', this.readOnly)
this.editor.on('change', cm => {
this.$emit('change', cm.getValue())
})
},
methods: {
getValue() {
if (this.editor == null) {
return ''
}
return this.editor.getValue()
},
setValue(val) {
if (this.editor == null) {
return
}
this.editor.setValue(val)
}
}
}
</script>
@@ -0,0 +1,72 @@
<!--<p class="warn-content">-->
<!--Markdown 基于-->
<!--<el-link type="primary" href="https://github.com/hinesboy/mavonEditor" target="_blank">MavonEditor</el-link>-->
<!--</p>-->
<template>
<mavon-editor
ref="md"
v-model="content"
:style="`height: + ${height};overflow-y: hidden`"
:ishljs="true"
@imgAdd="imgAdd"
@change="onChange"
@save="onSave"
/>
</template>
<script>
import { upload } from '@/utils/upload'
import { mapGetters } from 'vuex'
import { mavonEditor } from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
const dynamicHeight = 160
export default {
name: 'CuteMarkdown',
components: {
mavonEditor
},
props: {
content: {
type: String,
required: true,
default: ''
}
},
data() {
return {
height: document.documentElement.clientHeight - dynamicHeight + 'px'
}
},
computed: {
...mapGetters([
'imagesUploadApi',
'baseApi'
])
},
mounted() {
const that = this
window.onresize = () => {
that.height = document.documentElement.clientHeight - dynamicHeight + 'px'
}
},
methods: {
imgAdd(pos, $file) {
const that = this
upload(that.imagesUploadApi, $file).then(res => {
const data = res.data
const url = that.baseApi + '/file/' + data.type + '/' + data.realName
that.$refs.md.$img2Url(pos, url)
})
},
onChange(value, render) {
this.$emit('change', value, render)
},
onSave(value, render) {
this.$emit('save', value, render)
}
}
}
</script>
<style scoped>
</style>
@@ -16,6 +16,7 @@ export default {
props: {
content: {
type: String,
required: true,
default: ''
}
},
@@ -0,0 +1,294 @@
<!--富文本基于-->
<!--<el-link type="primary" href="https://www.wangeditor.com/v5/getting-started.html" target="_blank">wangEditor</el-link>-->
<template>
<div ref="editor" style="border: 1px solid #ccc;">
<Toolbar
style="border-bottom: 1px solid #ccc"
:editor="editor"
:default-config="toolbarConfig"
:mode="editMode"
/>
<Editor
v-model="editValue"
:style="`height: 500px;overflow-y: hidden`"
:default-config="editorConfig"
:mode="editMode"
@onCreated="onCreated"
@onChange="onChange"
@onDestroyed="onDestroyed"
@onFocus="onFocus"
@onBlur="onBlur"
@customAlert="customAlert"
@customPaste="customPaste"
/>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import '@wangeditor/editor/dist/css/style.css'
import { Message } from 'element-ui'
import { upload } from '@/utils/upload'
import { Toolbar, Editor } from '@wangeditor/editor-for-vue'
export default {
name: 'CuteRichTextEditor',
components: { Toolbar, Editor },
props: {
readOnly: {
type: Boolean,
required: false,
default: false
},
content: {
type: String,
required: false,
default: ''
}
},
data() {
const that = this
return {
toolbarConfig: {},
editorConfig: {
placeholder: '请输入内容...',
readOnly: that.readOnly,
autoFocus: true,
scroll: false,
// 会造成卡顿
// maxLength: this.maxLength
MENU_CONF: {
'uploadImage': {
// 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 []
allowedFileTypes: ['image/*'],
// 自定义上传
async customUpload(file, insertFn) { // JS 语法
upload(that.imagesUploadApi, file).then(res => {
const data = res.data
const url = that.baseApi + '/file/' + data.dateGroup + '/' + data.realName
// 最后插入图片
insertFn(url, '', '')
})
}
}
}
},
// 'default' or 'simple'
editMode: 'simple',
editor: null,
editValue: ''
}
},
computed: {
...mapGetters([
'imagesUploadApi',
'baseApi'
])
},
methods: {
/**
* 编辑器创建完毕时的回调函数
* @param editor
*/
onCreated(editor) {
// 一定要用 Object.seal(), 否则会报错
this.editor = Object.seal(editor)
this.editValue = this.content
},
/**
* 编辑器内容、选区变化时的回调函数
* @param editor
*/
onChange(editor) {
if (editor == null) {
return
}
// 非格式化的 html
const html = editor.getHtml()
// 纯文本内容
const text = editor.getText()
this.$emit('change', html, text)
},
/**
* 编辑器销毁时的回调函数。调用 editor.destroy() 即可销毁编辑器
* @param editor
*/
onDestroyed(editor) {
if (editor == null) {
return
}
editor.destroy()
},
/**
* 编辑器内容达到最大长度时的回调函数(会导致卡顿)
* @param editor
*/
onMaxLength(editor) {
if (editor == null) {
return
}
},
/**
* 编辑器 focus 时的回调函数
* @param editor
*/
onFocus(editor) {
if (editor == null) {
return
}
this.$emit('focus', editor)
},
/**
* 编辑器 blur 时的回调函数
* @param editor
*/
onBlur(editor) {
if (editor == null) {
return
}
this.$emit('blur', editor)
},
/**
* 自定义编辑器 alert 。如想用 ElementUI 的 Message 功能
* @param editor
*/
customAlert(info, type) {
switch (type) {
case 'success':
Message.success(info)
break
case 'info':
Message.info(info)
break
case 'warning':
Message.warning(info)
break
case 'error':
Message.error(info)
break
default:
Message.info(info)
break
}
},
/**
* 自定义粘贴。可阻止编辑器的默认粘贴,实现自己的粘贴逻辑
* @param editor
*/
customPaste(editor, event, callback) {
if (editor == null) {
callback(true)
}
// console.log('ClipboardEvent 粘贴事件对象', event)
// // const html = event.clipboardData.getData('text/html') // 获取粘贴的 html
// // const text = event.clipboardData.getData('text/plain') // 获取粘贴的纯文本
// // const rtf = event.clipboardData.getData('text/rtf') // 获取 rtf 数据(如从 word wsp 复制粘贴)
//
// // 自定义插入内容
// editor.insertText('xxx')
//
// // 返回 false ,阻止默认粘贴行为
// event.preventDefault()
// callback(false) // 返回值(注意,vue 事件的返回值,不能用 return)
//
// // 返回 true ,继续默认的粘贴行为
// // callback(true)
callback(true)
},
/**
* 设置编辑器html内容
* @param html
* <br/>
* 如果是 editor.getHtml() 获取的 HTML 格式,可以完美解析。
* 如果是其他的 HTML 格式,则不能保证语义正确 —— dangerously 。
*/
setHtml(html) {
if (this.editor == null) {
return
}
this.editor.dangerouslyInsertHtml(html)
},
/**
* 获取编辑器html内容
*/
getHtml() {
if (this.editor == null) {
return ''
}
this.editor.getHtml()
},
/**
* 清空编辑器内容
*/
clear() {
if (this.editor == null) {
return
}
this.editor.clear()
},
/**
* 撤销
*/
undo() {
if (this.editor == null) {
return
}
this.editor.undo()
},
/**
* 重做
*/
redo() {
if (this.editor == null) {
return
}
this.editor.redo()
},
/**
* 获取选中的文本
*/
getSelectionText() {
if (this.editor == null) {
return ''
}
return this.editor.getSelectionText()
},
/**
* 删除选中的内容
*/
deleteFragment() {
if (this.editor == null) {
return
}
this.editor.deleteFragment()
},
/**
* 获取选中的内容。JSON格式
*/
getFragment() {
if (this.editor == null) {
return {}
}
return this.editor.getFragment()
},
/**
* 获取文本内容
*/
getText() {
if (this.editor == null) {
return ''
}
return this.editor.getText()
},
/**
* 在选区插入文本
* @param text
*/
insertText(text) {
if (this.editor == null) {
return
}
this.editor.insertText(text)
}
}
}
</script>
@@ -49,11 +49,6 @@ export default {
required: true,
default: null
},
dataSource: {
type: Array,
required: false,
default: null
},
fetch: {
type: Function,
required: false,
@@ -94,7 +89,7 @@ export default {
columns: this.columns && this.columns.length > 0 ? this.columns : [],
operateColumn: this.operateColumn,
fetchUrl: null,
dataSource: this.dataSource && this.dataSource.length > 0 ? this.dataSource : [],
dataSource: [],
onPageChange: (currentPage, pageSize) => {
this.pageProps.current = currentPage
this.pageProps.pageSize = pageSize
@@ -113,11 +108,6 @@ export default {
this.initData()
},
async initData() {
// 以dataSource属性为准
if (this.dataSource) {
this.crud.dataSource = this.dataSource
return
}
let params = {}
// 自定义请求参数
if (this.paramsTransform) {
@@ -134,7 +124,7 @@ export default {
if (this.responseTransform) {
return this.responseTransform(response)
}
if (response && response.totalElements && response.content) {
if (response && response.hasOwnProperty('totalElements') && response.hasOwnProperty('content')) {
this.pageProps.total = response.totalElements
this.crud.dataSource = response.content
}
@@ -0,0 +1,87 @@
<!--Yaml编辑器 基于-->
<!--<a href="https://github.com/codemirror/CodeMirror" target="_blank">CodeMirror</a>,-->
<!--主题预览地址 <a href="https://codemirror.net/demo/theme.html#idea" target="_blank">Theme</a>-->
<!--</p>-->
<template>
<textarea ref="textarea" />
</template>
<script>
import CodeMirror from 'codemirror'
import 'codemirror/lib/codemirror.css'
// 替换主题这里需修改名称
// 主题预览地址 https://blog.csdn.net/qq_41694291/article/details/106429772
import 'codemirror/theme/darcula.css'
import 'codemirror/mode/yaml/yaml'
export default {
name: 'CuteYamlEditor',
props: {
content: {
type: String,
required: true,
default: ''
},
height: {
type: String,
required: false,
default: '500px'
},
readOnly: {
type: Boolean,
required: false,
default: false
}
},
data() {
return {
editor: false
}
},
watch: {
content(newVal, oldVal) {
const editorValue = this.editor.getValue()
if (newVal !== editorValue) {
this.editor.setValue(newVal)
}
},
height(newVal, oldVal) {
this.editor.setSize('auto', newVal)
}
},
mounted() {
this.editor = CodeMirror.fromTextArea(this.$refs.textarea, {
mode: 'text/x-yaml',
autoRefresh: true,
lineNumbers: true,
lint: true,
lineWrapping: true,
tabSize: 2,
cursorHeight: 1,
// 替换主题这里需修改名称
theme: 'darcula'
})
this.editor.setSize('auto', this.height)
if (this.content) {
this.editor.setValue(this.content)
}
this.editor.setOption('readOnly', this.readOnly)
this.editor.on('change', cm => {
this.$emit('change', cm.getValue())
})
},
methods: {
getValue() {
if (this.editor == null) {
return ''
}
return this.editor.getValue()
},
setValue(val) {
if (this.editor == null) {
return
}
this.editor.setValue(val)
}
}
}
</script>