refactor: 代码规范、Bug修复

This commit is contained in:
2025-09-26 09:10:37 +08:00
parent 3610f8f7db
commit dcc288acc4
572 changed files with 41415 additions and 44746 deletions
@@ -1,111 +1,112 @@
<template>
<div style="padding: 50px">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>表单值绑定</span>
</div>
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="用户" prop="user">
<!-- v-model 本质上是 :value 和 @input 事件的语法糖 -->
<cute-user-select v-model="form.user" />
</el-form-item>
<el-form-item label="部门" prop="dept">
<cute-dept-tree v-model="form.dept" />
</el-form-item>
<el-form-item label="产品线" prop="productLine">
<cute-product-line-select v-model="form.productLine" @detail="onProductLineDetailChange" />
</el-form-item>
<el-form-item label="产品线Pro" prop="productLinePro">
<cute-product-line-select-pro v-model="form.productLine" @detail="onProductLineDetailProChange" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit('form')">提 交</el-button>
<el-button type="danger" @click="onReset('form')">重 置</el-button>
<el-button>取 消</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card style="margin-top: 10px">
<div slot="header" class="clearfix">
<span>用户选择框</span>
</div>
<cute-user-select @change="onUserSelectChange" />
</el-card>
<el-card style="margin-top: 10px">
<div slot="header" class="clearfix">
<span>部门树</span>
</div>
<cute-dept-tree @node-click="onDeptTreeNodeClick" @search="onDeptTreeSearch" />
</el-card>
<el-card style="margin-top: 10px">
<div slot="header" class="clearfix">
<span>产品线选择框</span>
</div>
<cute-product-line-select @change="onProductLineChange" @detail="onProductLineDetailChange" />
</el-card>
<el-card style="margin-top: 10px">
<div slot="header" class="clearfix">
<span>产品线选择框Pro</span>
</div>
<cute-product-line-select-pro @change="onProductLineDetailProChange" />
</el-card>
</div>
</template>
<script>
import CuteUserSelect from '@/views/components/business/CuteUserSelect.vue'
import CuteDeptTree from '@/views/components/business/CuteDeptTree.vue'
import CuteProductLineSelect from '@/views/components/business/CuteProductLineSelect.vue'
import CuteProductLineSelectPro from '@/views/components/business/CuteProductLineSelectPro.vue'
export default {
name: 'CuteBusinessDemo',
components: { CuteProductLineSelectPro, CuteProductLineSelect, CuteDeptTree, CuteUserSelect },
data() {
return {
form: {
user: null,
dept: null,
productLine: null,
productLinePro: null
}
}
},
methods: {
onUserSelectChange(data) {
console.log('onUserSelectChange=', data)
},
onDeptTreeNodeClick(data) {
console.log('onDeptTreeNodeClick=', data)
},
onSubmit(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
console.log('this.form=', this.form)
} else {
console.error('error submit!!')
return false
}
})
},
onReset(formName) {
this.$refs[formName].resetFields()
},
onDeptTreeSearch(key) {
console.log('onDeptTreeSearch:key', key)
console.log('onDeptTreeSearch:form.dept', this.form.dept)
},
onProductLineChange(data) {
console.log('onProductLineChange', data)
},
onProductLineDetailChange(data) {
console.log('onProductLineDetailChange', data)
},
onProductLineDetailProChange(data) {
console.log('onProductLineDetailProChange', data)
}
}
}
</script>
<template>
<div style="padding: 50px">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>表单值绑定</span>
</div>
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="用户" prop="user">
<!-- v-model 本质上是 :value 和 @input 事件的语法糖 -->
<cute-user-select v-model="form.user" />
</el-form-item>
<el-form-item label="部门" prop="dept">
<cute-dept-tree v-model="form.dept" />
</el-form-item>
<el-form-item label="产品线" prop="productLine">
<cute-product-line-select v-model="form.productLine" @detail="onProductLineDetailChange" />
</el-form-item>
<el-form-item label="产品线Pro" prop="productLinePro">
<cute-product-line-select-pro v-model="form.productLine" @detail="onProductLineDetailProChange" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit('form')">提 交</el-button>
<el-button type="danger" @click="onReset('form')">重 置</el-button>
<el-button>取 消</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card style="margin-top: 10px">
<div slot="header" class="clearfix">
<span>用户选择框</span>
</div>
<cute-user-select @change="onUserSelectChange" />
</el-card>
<el-card style="margin-top: 10px">
<div slot="header" class="clearfix">
<span>部门树</span>
</div>
<cute-dept-tree @node-click="onDeptTreeNodeClick" @search="onDeptTreeSearch" />
</el-card>
<el-card style="margin-top: 10px">
<div slot="header" class="clearfix">
<span>产品线选择框</span>
</div>
<cute-product-line-select @change="onProductLineChange" @detail="onProductLineDetailChange" />
</el-card>
<el-card style="margin-top: 10px">
<div slot="header" class="clearfix">
<span>产品线选择框Pro</span>
</div>
<cute-product-line-select-pro @change="onProductLineDetailProChange" />
</el-card>
</div>
</template>
<script>
import CuteUserSelect from '@/views/components/business/CuteUserSelect.vue'
import CuteDeptTree from '@/views/components/business/CuteDeptTree.vue'
import CuteProductLineSelect from '@/views/components/business/CuteProductLineSelect.vue'
import CuteProductLineSelectPro from '@/views/components/business/CuteProductLineSelectPro.vue'
export default {
name: 'CuteBusinessDemo',
components: { CuteProductLineSelectPro, CuteProductLineSelect, CuteDeptTree, CuteUserSelect },
data() {
return {
form: {
user: null,
dept: null,
productLine: null,
productLinePro: null
},
searchFormModel: {}
}
},
methods: {
onUserSelectChange(data) {
console.log('onUserSelectChange=', data)
},
onDeptTreeNodeClick(data) {
console.log('onDeptTreeNodeClick=', data)
},
onSubmit(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
console.log('this.form=', this.form)
} else {
console.error('error submit!!')
return false
}
})
},
onReset(formName) {
this.$refs[formName].resetFields()
},
onDeptTreeSearch(key) {
console.log('onDeptTreeSearch:key', key)
console.log('onDeptTreeSearch:form.dept', this.form.dept)
},
onProductLineChange(data) {
console.log('onProductLineChange', data)
},
onProductLineDetailChange(data) {
console.log('onProductLineDetailChange', data)
},
onProductLineDetailProChange(data) {
console.log('onProductLineDetailProChange', data)
}
}
}
</script>
@@ -1,125 +1,125 @@
<template>
<div class="app-container">
<!-- 工具栏 -->
<div class="head-container">
<el-form
ref="searchForm"
:inline="true"
:model="form.model"
label-position="right"
label-width="80px"
:rules="form.rules"
>
<el-form-item label="模糊查询" prop="blurry">
<el-input v-model="form.model.blurry" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onFormSubmit('searchForm')">查询</el-button>
<el-button @click="onFormReset('searchForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
<!-- 表格渲染 -->
<!-- fetch: 获取远程数据 -->
<!-- params-transform: 组装查询参数 -->
<!-- responseTransform: 组装表格对象。对响应结果做处理 -->
<!-- primary-key: 主键 -->
<!-- data-source: 数据源。当data-source不为空时,以data-source的数据为主 -->
<!-- mode: 模式。不传默认,传multi为多选 -->
<!-- @selection-change: 当且仅当mode为multi时启用 -->
<cute-drag-table
ref="instance"
:fetch="curd.fetch"
:params-transform="curd.paramsTransform"
primary-key="id"
:page-props="curd.pageProps"
>
<el-table-column prop="name" label="名称" />
<el-table-column prop="description" label="描述" />
<el-table-column prop="createTime" label="创建时间" :formatter="FormatRowDateTimeStr" />
<el-table-column prop="createBy" label="创建人" />
<el-table-column label="操作" width="150" min-width="150" fixed="right">
<template slot-scope="scope">
<div>
<el-button type="text" @click="onTableEditClick(scope.row)">编辑</el-button>
<el-button type="text" @click="onTableDeleteClick(scope.row)">删除</el-button>
</div>
</template>
</el-table-column>
</cute-drag-table>
</div>
</template>
<script>
import DictService from '@/api/system/dict'
import CuteDragTable from '@/views/components/dev/CuteDragTable.vue'
import { FormatRowDateTimeStr } from '@/utils/CsUtil'
export default {
name: 'CuteDragTableDemo',
components: { CuteDragTable },
data() {
return {
form: {
model: {
blurry: ''
},
rules: {}
},
curd: {
paramsTransform: (pageProps) => {
const values = this.form.model
return {
page: pageProps.current,
size: pageProps.pageSize,
args: {
...values
}
}
},
fetch: async(queryParams) => {
return DictService.queryPageDict(queryParams)
},
pageProps: {
current: 1,
pageSize: 10,
total: 0
}
}
}
},
mounted() {
this.initData()
},
methods: {
FormatRowDateTimeStr,
initData() {
this.$refs.instance.refresh()
},
onFormSubmit(formName) {
const that = this
that.$refs[formName].validate((valid) => {
if (valid) {
that.$refs.instance.refresh()
} else {
return false
}
})
},
onFormReset(formName) {
try {
this.$refs[formName].resetFields()
} catch (e) {
console.error(e)
}
},
onTableEditClick(row) {
console.log('编辑', row)
},
onTableDeleteClick(row) {
console.log('删除', row)
}
}
}
</script>
<template>
<div class="app-container">
<!-- 工具栏 -->
<div class="head-container">
<el-form
ref="searchForm"
:inline="true"
:model="form.model"
label-position="right"
label-width="80px"
:rules="form.rules"
>
<el-form-item label="模糊查询" prop="blurry">
<el-input v-model="form.model.blurry" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onFormSubmit('searchForm')">查询</el-button>
<el-button @click="onFormReset('searchForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
<!-- 表格渲染 -->
<!-- fetch: 获取远程数据 -->
<!-- params-transform: 组装查询参数 -->
<!-- responseTransform: 组装表格对象。对响应结果做处理 -->
<!-- primary-key: 主键 -->
<!-- data-source: 数据源。当data-source不为空时,以data-source的数据为主 -->
<!-- mode: 模式。不传默认,传multi为多选 -->
<!-- @selection-change: 当且仅当mode为multi时启用 -->
<cute-drag-table
ref="instance"
:fetch="curd.fetch"
:params-transform="curd.paramsTransform"
primary-key="id"
:page-props="curd.pageProps"
>
<el-table-column prop="name" label="名称" />
<el-table-column prop="description" label="描述" />
<el-table-column prop="createTime" label="创建时间" :formatter="FormatRowDateTimeStr" />
<el-table-column prop="createBy" label="创建人" />
<el-table-column label="操作" width="150" min-width="150" fixed="right">
<template slot-scope="scope">
<div>
<el-button type="text" @click="onTableEditClick(scope.row)">编辑</el-button>
<el-button type="text" @click="onTableDeleteClick(scope.row)">删除</el-button>
</div>
</template>
</el-table-column>
</cute-drag-table>
</div>
</template>
<script>
import DictService from '@/api/system/dict'
import CuteDragTable from '@/views/components/dev/CuteDragTable.vue'
import { FormatRowDateTimeStr } from '@/utils/CsUtil'
export default {
name: 'CuteDragTableDemo',
components: { CuteDragTable },
data() {
return {
form: {
model: {
blurry: ''
},
rules: {}
},
curd: {
paramsTransform: (pageProps) => {
const values = this.form.model
return {
page: pageProps.current,
size: pageProps.pageSize,
args: {
...values
}
}
},
fetch: async(queryParams) => {
return DictService.queryPageDict(queryParams)
},
pageProps: {
current: 1,
pageSize: 10,
total: 0
}
}
}
},
mounted() {
this.initData()
},
methods: {
FormatRowDateTimeStr,
initData() {
this.$refs.instance.refresh()
},
onFormSubmit(formName) {
const that = this
that.$refs[formName].validate((valid) => {
if (valid) {
that.$refs.instance.refresh()
} else {
return false
}
})
},
onFormReset(formName) {
try {
this.$refs[formName].resetFields()
} catch (e) {
console.error(e)
}
},
onTableEditClick(row) {
console.log('编辑', row)
},
onTableDeleteClick(row) {
console.log('删除', row)
}
}
}
</script>
@@ -1,52 +1,52 @@
<template>
<div class="app-container">
<el-form ref="form" :model="form" label-width="100px">
<el-form-item label="活动名称" prop="name">
<el-input v-model="form.name" style="width: 100%" />
</el-form-item>
<el-form-item label="活动区域" prop="region">
<el-select v-model="form.region" placeholder="请选择活动区域" style="width: 100%">
<el-option label="区域一" value="shanghai" />
<el-option label="区域二" value="beijing" />
</el-select>
</el-form-item>
<el-form-item label="文件上传" prop="fileUrl">
<cute-file-drag-upload v-model="form" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('form')">提 交</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import CuteFileDragUpload from '@/views/components/business/CuteFileDragUpload'
export default {
name: 'CuteFileDragUploadDemo',
components: { CuteFileDragUpload },
data() {
return {
form: {
name: '',
region: '',
fileUrl: ''
}
}
},
methods: {
submitForm(formName) {
const that = this
that.$refs[formName].validate((valid) => {
if (valid) {
console.log('submitForm:form', that.form)
} else {
return false
}
})
}
}
}
</script>
<template>
<div class="app-container">
<el-form ref="form" :model="form" label-width="100px">
<el-form-item label="活动名称" prop="name">
<el-input v-model="form.name" style="width: 100%" />
</el-form-item>
<el-form-item label="活动区域" prop="region">
<el-select v-model="form.region" placeholder="请选择活动区域" style="width: 100%">
<el-option label="区域一" value="shanghai" />
<el-option label="区域二" value="beijing" />
</el-select>
</el-form-item>
<el-form-item label="文件上传" prop="fileUrl">
<cute-file-drag-upload v-model="form" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('form')">提 交</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import CuteFileDragUpload from '@/views/components/business/CuteFileDragUpload'
export default {
name: 'CuteFileDragUploadDemo',
components: { CuteFileDragUpload },
data() {
return {
form: {
name: '',
region: '',
fileUrl: ''
}
}
},
methods: {
submitForm(formName) {
const that = this
that.$refs[formName].validate((valid) => {
if (valid) {
console.log('submitForm:form', that.form)
} else {
return false
}
})
}
}
}
</script>
@@ -1,52 +1,52 @@
<template>
<div class="app-container">
<el-form ref="form" :model="form" label-width="100px">
<el-form-item label="活动名称" prop="name">
<el-input v-model="form.name" style="width: 100%" />
</el-form-item>
<el-form-item label="活动区域" prop="region">
<el-select v-model="form.region" placeholder="请选择活动区域" style="width: 100%">
<el-option label="区域一" value="shanghai" />
<el-option label="区域二" value="beijing" />
</el-select>
</el-form-item>
<el-form-item label="文件上传" prop="fileUrl">
<cute-file-upload v-model="form" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('form')">提 交</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import CuteFileUpload from '@/views/components/business/CuteFileUpload'
export default {
name: 'CuteFileUploadDemo',
components: { CuteFileUpload },
data() {
return {
form: {
name: '',
region: '',
fileUrl: ''
}
}
},
methods: {
submitForm(formName) {
const that = this
that.$refs[formName].validate((valid) => {
if (valid) {
console.log('submitForm:form', that.form)
} else {
return false
}
})
}
}
}
</script>
<template>
<div class="app-container">
<el-form ref="form" :model="form" label-width="100px">
<el-form-item label="活动名称" prop="name">
<el-input v-model="form.name" style="width: 100%" />
</el-form-item>
<el-form-item label="活动区域" prop="region">
<el-select v-model="form.region" placeholder="请选择活动区域" style="width: 100%">
<el-option label="区域一" value="shanghai" />
<el-option label="区域二" value="beijing" />
</el-select>
</el-form-item>
<el-form-item label="文件上传" prop="fileUrl">
<cute-file-upload v-model="form" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('form')">提 交</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import CuteFileUpload from '@/views/components/business/CuteFileUpload'
export default {
name: 'CuteFileUploadDemo',
components: { CuteFileUpload },
data() {
return {
form: {
name: '',
region: '',
fileUrl: ''
}
}
},
methods: {
submitForm(formName) {
const that = this
that.$refs[formName].validate((valid) => {
if (valid) {
console.log('submitForm:form', that.form)
} else {
return false
}
})
}
}
}
</script>
@@ -1,47 +1,47 @@
<template>
<div class="app-container">
<!-- <cute-java-editor :content="content" @change="onChange" />-->
<cute-code-editor :content="content" mode="java" @change="onChange" />
</div>
</template>
<script>
// 旧组件
// import CuteYamlEditor from '@/views/components/dev/CuteYamlEditor'
// 新组件
import CuteCodeEditor from '@/views/components/dev/CuteCodeEditor'
export default {
name: 'CuteJavaEditorDemo',
// components: { CuteJavaEditor },
components: { CuteCodeEditor },
data() {
return {
content: 'package cn.odboy;\n' +
'\n' +
'import cn.odboy.framework.context.CsBootApplication;\n' +
'import io.swagger.annotations.Api;\n' +
'import org.springframework.boot.SpringApplication;\n' +
'import org.springframework.boot.autoconfigure.SpringBootApplication;\n' +
'\n' +
'import java.net.UnknownHostException;\n' +
'\n' +
'@Api(hidden = true)\n' +
'@SpringBootApplication\n' +
'public class AppRun extends CsBootApplication {\n' +
'\n' +
' public static void main(String[] args) throws UnknownHostException {\n' +
' SpringApplication springApplication = new SpringApplication(AppRun.class);\n' +
' inited(springApplication.run(args));\n' +
' }\n' +
'}\n'
}
},
methods: {
onChange(value) {
console.log('onChange', value)
}
}
}
</script>
<template>
<div class="app-container">
<!-- <cute-java-editor :content="content" @change="onChange" />-->
<cute-code-editor :content="content" mode="java" @change="onChange" />
</div>
</template>
<script>
// 旧组件
// import CuteYamlEditor from '@/views/components/dev/CuteYamlEditor'
// 新组件
import CuteCodeEditor from '@/views/components/dev/CuteCodeEditor'
export default {
name: 'CuteJavaEditorDemo',
// components: { CuteJavaEditor },
components: { CuteCodeEditor },
data() {
return {
content: 'package cn.odboy;\n' +
'\n' +
'import cn.odboy.framework.context.CsBootApplication;\n' +
'import io.swagger.annotations.Api;\n' +
'import org.springframework.boot.SpringApplication;\n' +
'import org.springframework.boot.autoconfigure.SpringBootApplication;\n' +
'\n' +
'import java.net.UnknownHostException;\n' +
'\n' +
'@Api(hidden = true)\n' +
'@SpringBootApplication\n' +
'public class AppRun extends CsBootApplication {\n' +
'\n' +
' public static void main(String[] args) throws UnknownHostException {\n' +
' SpringApplication springApplication = new SpringApplication(AppRun.class);\n' +
' inited(springApplication.run(args));\n' +
' }\n' +
'}\n'
}
},
methods: {
onChange(value) {
console.log('onChange', value)
}
}
}
</script>
@@ -1,39 +1,39 @@
<template>
<div class="app-container">
<!-- @change 编辑区发生变化的回调事件 -->
<!-- @save ctrl + s 的回调事件(保存按键,同样触发该回调) -->
<cute-markdown
:content="markdown.content"
@change="onChange"
@save="onSave"
/>
</div>
</template>
<script>
import CuteMarkdown from '@/views/components/dev/CuteMarkdown'
export default {
name: 'CuteMarkdownDemo',
components: { CuteMarkdown },
data() {
return {
markdown: {
height: '200px',
content: '初始化内容'
}
}
},
methods: {
onChange(text, markdown) {
console.log('onChange:text', text)
console.log('onChange:markdown', markdown)
},
onSave(text, markdown) {
console.log('onSave:text', text)
console.log('onSave:markdown', markdown)
}
}
}
</script>
<template>
<div class="app-container">
<!-- @change 编辑区发生变化的回调事件 -->
<!-- @save ctrl + s 的回调事件(保存按键,同样触发该回调) -->
<cute-markdown
:content="markdown.content"
@change="onChange"
@save="onSave"
/>
</div>
</template>
<script>
import CuteMarkdown from '@/views/components/dev/CuteMarkdown'
export default {
name: 'CuteMarkdownDemo',
components: { CuteMarkdown },
data() {
return {
markdown: {
height: '200px',
content: '初始化内容'
}
}
},
methods: {
onChange(text, markdown) {
console.log('onChange:text', text)
console.log('onChange:markdown', markdown)
},
onSave(text, markdown) {
console.log('onSave:text', text)
console.log('onSave:markdown', markdown)
}
}
}
</script>
@@ -1,63 +1,63 @@
<template>
<div>
<el-divider>clipboard版</el-divider>
<span>{{ msg }}</span>
<div id="btn" @click="copy">复制</div>
<el-divider>OneKeyCopy组件版</el-divider>
<cute-one-key-copy style="margin-left: 10pt" :content.sync="msg" />
</div>
</template>
<script>
import Clipboard from 'clipboard'
import CuteOneKeyCopy from '@/views/components/dev/CuteOneKeyCopy'
import CsMessage from '@/utils/elementui/CsMessage'
export default {
components: { CuteOneKeyCopy },
data() {
return {
msg: '来复制我吧'
}
},
methods: {
// 复制方法
copy() {
const that = this
const clipboard = new Clipboard('#btn', {
text(trigger) {
console.log(trigger)
// 返回字符串
return that.msg
}
})
// 复制成功
clipboard.on('success', (e) => {
CsMessage.Success('复制成功')
console.log(e, '复制成功')
clipboard.destroy()
})
// //复制失败
clipboard.on('error', (e) => {
CsMessage.Error('复制失败')
console.log(e, '复制失败')
clipboard.destroy()
})
}
}
}
</script>
<style scoped>
#btn {
display: inline-block;
padding: 3px 12px;
border-radius: 6px;
background-color: #eee;
color: #333;
cursor: pointer;
}
#btn:active {
background-color: #ddd;
color: #666;
}
</style>
<template>
<div>
<el-divider>clipboard版</el-divider>
<span>{{ msg }}</span>
<div id="btn" @click="copy">复制</div>
<el-divider>OneKeyCopy组件版</el-divider>
<cute-one-key-copy style="margin-left: 10pt" :content.sync="msg" />
</div>
</template>
<script>
import Clipboard from 'clipboard'
import CuteOneKeyCopy from '@/views/components/dev/CuteOneKeyCopy'
import CsMessage from '@/utils/elementui/CsMessage'
export default {
components: { CuteOneKeyCopy },
data() {
return {
msg: '来复制我吧'
}
},
methods: {
// 复制方法
copy() {
const that = this
const clipboard = new Clipboard('#btn', {
text(trigger) {
console.log(trigger)
// 返回字符串
return that.msg
}
})
// 复制成功
clipboard.on('success', (e) => {
CsMessage.Success('复制成功')
console.log(e, '复制成功')
clipboard.destroy()
})
// //复制失败
clipboard.on('error', (e) => {
CsMessage.Error('复制失败')
console.log(e, '复制失败')
clipboard.destroy()
})
}
}
}
</script>
<style scoped>
#btn {
display: inline-block;
padding: 3px 12px;
border-radius: 6px;
background-color: #eee;
color: #333;
cursor: pointer;
}
#btn:active {
background-color: #ddd;
color: #666;
}
</style>
@@ -1,304 +0,0 @@
<template>
<div>
<el-divider>演示:{{ dynamicTemplate.description ? dynamicTemplate.description: '动态流水线演示' }}
<el-button
v-prevent-re-click
style="margin-left: 10px"
type="primary"
:loading="dynamicStartButtonLoading"
:disabled="dynamicStartButtonLoading"
@click="doStartPipeline"
>{{ dynamicStartupStatusMap[dynamicStartupStatus].label }}
</el-button>
<el-button
v-prevent-re-click
:disabled="!dynamicRunning"
style="margin-left: 10px"
type="danger"
@click="doStopPipeline"
>停止
</el-button>
</el-divider>
<div class="box-pipeline">
<div v-if="dynamicInstance.nodes && dynamicInstance.nodes.length > 0" class="box-pipeline-content">
<cute-pipeline-node
v-for="(template, index) in dynamicInstance.nodes"
:key="template.code"
:template-data.sync="dynamicInstance.nodes[index]"
:instance-data.sync="dynamicInstance"
@node-click="onPipelineNodeClick"
@node-retry="onPipelineNodeRetryClick"
@node-opera="onPipelineNodeOperationClick"
/>
</div>
<div v-else class="box-pipeline-content">
<cute-pipeline-node
v-for="(template, index) in dynamicTemplateList"
:key="template.code"
:template-data.sync="dynamicTemplateList[index]"
:instance-data.sync="dynamicInstance"
/>
</div>
</div>
<cute-preview-drawer ref="detailDrawer" :title="currentNodeData.name">
<el-timeline>
<el-timeline-item timestamp="2018/4/12" placement="top">
<el-card>
<h4>更新 Github 模板</h4>
<p>王小虎 提交于 2018/4/12 20:46</p>
</el-card>
</el-timeline-item>
<el-timeline-item timestamp="2018/4/3" placement="top">
<el-card>
<h4>更新 Github 模板</h4>
<p>王小虎 提交于 2018/4/3 20:46</p>
</el-card>
</el-timeline-item>
<el-timeline-item timestamp="2018/4/2" placement="top">
<el-card>
<h4>更新 Github 模板</h4>
<p>王小虎 提交于 2018/4/2 20:46</p>
</el-card>
</el-timeline-item>
</el-timeline>
</cute-preview-drawer>
</div>
</template>
<script>
import CutePipelineNode from '@/views/components/dev/CutePipelineNode'
import { getPipelineTemplate } from '@/api/pipeline/pipelineTemplate'
import {
queryLastPipelineDetailWs,
restartPipeline,
retryPipeline,
startPipeline,
stopPipeline
} from '@/api/pipeline/pipelineInstance'
import { CountArraysObjectByPropKey } from '@/utils/CsUtil'
import CsMessage from '@/utils/elementui/CsMessage'
import CsWsClient from '@/utils/CsWsClient'
import { mapGetters } from 'vuex'
import CutePreviewDrawer from '@/views/components/dev/CutePreviewDrawer.vue'
export default {
name: 'CutePipelineNodeDemo',
components: { CutePreviewDrawer, CutePipelineNode },
data() {
return {
testAppInfo: {
appName: 'cuteops',
pipelineTemplateEnv: 'daily',
iterationName: '流水线测试'
},
// ============== 动态流水线
dynamicStartupStatusMap: {
start: { label: '启动', code: 'start' },
restart: { label: '重新启动', code: 'restart' }
},
// 按钮状态
dynamicStartupStatus: 'start',
dynamicStartButtonLoading: false,
// 当前模板
dynamicTemplate: {
id: 21
},
// 当前流水线节点模板
dynamicTemplateList: [],
// dynamicHook: null,
// 当前流水线实例
dynamicInstance: {},
// 当前ws客户端
dynamicWsClient: null,
dynamicRunning: false,
// ============== 交互变量
currentNodeData: {}
}
},
computed: {
...mapGetters([
'user'
])
},
mounted() {
this.initPipelineTemplate(this.dynamicTemplate.id)
},
methods: {
/**
* 初始化流水线模板
* @param templateId
* @returns {Promise<void>}
*/
async initPipelineTemplate(templateId) {
const pipelineTemplate = await getPipelineTemplate(templateId)
if (pipelineTemplate && pipelineTemplate.template) {
try {
this.dynamicTemplate = pipelineTemplate
this.dynamicTemplateList = JSON.parse(pipelineTemplate.template)
} catch (e) {
// ignore
}
}
},
/**
* 连接WebSocket服务
*/
connectWebSocketServer(instanceId) {
const that = this
// {username}_{bizCode}_{contextParams}
const sid = `${that.user.username}_FetchPipelineLastDetail_${instanceId}`
if (that.dynamicWsClient) {
try {
that.dynamicWsClient.close()
} catch (e) {
// ignore
}
}
that.dynamicWsClient = new CsWsClient(sid)
that.dynamicWsClient.connect(that.handleWebSocketError, that.handleWebSocketMessage)
setTimeout(() => {
// 请求推送流水线数据
queryLastPipelineDetailWs(sid)
that.dynamicStartButtonLoading = false
that.dynamicStartupStatus = that.dynamicStartupStatusMap.restart.code
}, 1000)
},
handleWebSocketError(e) {
console.error('连接WebSocket服务失败', e)
},
handleWebSocketMessage(e) {
const that = this
const data = e.data
// console.log('来自服务器的数据:data', data)
const callbackData = JSON.parse(data)
that.dynamicRunning = true
// console.log('callbackData', callbackData)
try {
that.dynamicInstance = JSON.parse(callbackData.data)
// 判断流水线是否结束
const successCount = CountArraysObjectByPropKey(that.dynamicInstance.nodes, 'status', 'success')
if (that.dynamicTemplateList && that.dynamicTemplateList.length === successCount) {
// 所有节点执行成功
if (that.dynamicWsClient) {
sessionStorage.removeItem('pipelineInstanceId')
that.dynamicWsClient.close()
that.dynamicRunning = false
}
that.dynamicStartupStatus = that.dynamicStartupStatusMap.start.code
} else {
const failCount = CountArraysObjectByPropKey(that.dynamicInstance.nodes, 'status', 'fail')
// 存在失败的节点
if (that.dynamicWsClient && failCount > 0) {
that.dynamicWsClient.close()
that.dynamicRunning = false
}
that.dynamicStartupStatus = that.dynamicStartupStatusMap.restart.code
}
} catch (e) {
// ignore
that.dynamicRunning = false
}
},
/**
* 启动流水线
* @returns {Promise<void>}
*/
async doStartPipeline() {
const that = this
try {
that.dynamicStartButtonLoading = true
// 这里的 dynamicStartupStatus状态,需要后期与上下文关联后,初始化的时候带入最近一个流水线实例
const args = {
templateId: that.dynamicTemplate.id,
instanceName: that.testAppInfo.iterationName,
contextName: that.testAppInfo.appName,
env: that.testAppInfo.pipelineTemplateEnv
}
let result
const pipelineInstanceId = sessionStorage.getItem('pipelineInstanceId')
if (pipelineInstanceId) {
result = await restartPipeline({
...args,
instanceId: pipelineInstanceId
})
CsMessage.Success('流水线重启成功')
} else {
result = await startPipeline(args)
CsMessage.Success('流水线启动成功')
}
sessionStorage.setItem('pipelineInstanceId', result.instanceId)
that.connectWebSocketServer(result.instanceId)
} catch (e) {
console.error('error', e)
that.dynamicStartButtonLoading = false
CsMessage.Error('流水线启动失败')
}
},
/**
* 停止流水线
* @returns {Promise<void>}
*/
async doStopPipeline() {
const that = this
const args = {
templateId: that.dynamicTemplate.id,
instanceName: that.testAppInfo.iterationName,
contextName: that.testAppInfo.appName,
env: that.testAppInfo.pipelineTemplateEnv
}
const pipelineInstanceId = sessionStorage.getItem('pipelineInstanceId')
if (pipelineInstanceId) {
await stopPipeline({
...args,
instanceId: pipelineInstanceId
})
CsMessage.Success('流水线停止成功')
}
},
onPipelineNodeClick(data) {
console.log('data', data)
this.currentNodeData = data
this.$refs.detailDrawer.show()
},
async onPipelineNodeRetryClick(data) {
console.log('data', data)
const result = await retryPipeline({
instanceId: data.instanceId,
code: data.code
})
sessionStorage.setItem('pipelineInstanceId', result.instanceId)
this.connectWebSocketServer(data.instanceId)
},
async onPipelineNodeOperationClick(data, buttonInfo) {
console.log('data', data, buttonInfo)
}
}
}
</script>
<style scoped>
.box-pipeline {
width: 1500px; /* 固定宽度 */
overflow-x: auto; /* 允许水平滚动 */
white-space: nowrap; /* 防止内容换行,使所有内容在一行显示 */
padding: 30px 20px 30px 20px;
}
.box-pipeline::-webkit-scrollbar {
height: 5px; /* 设置水平滚动条高度 */
}
.box-pipeline::-webkit-scrollbar-track {
background: #f1f1f1; /* 滚动条底色 */
}
.box-pipeline::-webkit-scrollbar-thumb {
background: #DCDFE6; /* 滚动条颜色 */
}
.box-pipeline-content {
display: inline-block; /* 使内容水平排列 */
white-space: nowrap; /* 防止内容换行 */
}
</style>
@@ -1,31 +1,31 @@
<template>
<div class="app-container">
<cute-rich-text-editor
:read-only="false"
@change="onChange"
/>
</div>
</template>
<script>
import CuteRichTextEditor from '@/views/components/dev/CuteRichTextEditor'
export default {
name: 'CuteRichTextEditorDemo',
components: { CuteRichTextEditor },
data() {
return {
html: {
height: '200px'
}
}
},
methods: {
onChange(html, text) {
console.log('onChange:html', html)
console.log('onChange:text', text)
}
}
}
</script>
<template>
<div class="app-container">
<cute-rich-text-editor
:read-only="false"
@change="onChange"
/>
</div>
</template>
<script>
import CuteRichTextEditor from '@/views/components/dev/CuteRichTextEditor'
export default {
name: 'CuteRichTextEditorDemo',
components: { CuteRichTextEditor },
data() {
return {
html: {
height: '200px'
}
}
},
methods: {
onChange(html, text) {
console.log('onChange:html', html)
console.log('onChange:text', text)
}
}
}
</script>
@@ -1,199 +1,199 @@
<template>
<div class="app-container">
<!-- 工具栏 -->
<div class="head-container">
<el-form
ref="searchForm"
:inline="true"
:model="form.model"
label-position="right"
label-width="80px"
:rules="form.rules"
>
<el-form-item label="模糊查询" prop="blurry">
<el-input v-model="form.model.blurry" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onFormSubmit('searchForm')">查询</el-button>
<el-button @click="onFormReset('searchForm')">重置</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onDialogClick">演示:表单对话框</el-button>
<el-button type="primary" @click="onDrawerClick">演示:表单抽屉</el-button>
</el-form-item>
</el-form>
</div>
<!-- 表格渲染 -->
<!-- fetch: 获取远程数据 -->
<!-- params-transform: 组装查询参数 -->
<!-- responseTransform: 组装表格对象。对响应结果做处理 -->
<!-- primary-key: 主键 -->
<!-- mode: 模式。不传默认,传multi为多选 -->
<!-- @selection-change: 当且仅当mode为multi时启用 -->
<cute-simple-table
ref="instance"
:fetch="curd.fetch"
:params-transform="curd.paramsTransform"
primary-key="id"
:page-props="curd.pageProps"
>
<el-table-column prop="name" label="名称" />
<el-table-column prop="description" label="描述" />
<el-table-column prop="createTime" label="创建时间" :formatter="FormatRowDateTimeStr" />
<el-table-column prop="createBy" label="创建人" />
<el-table-column label="操作" width="150" min-width="150" fixed="right">
<template slot-scope="scope">
<div>
<el-button type="text" @click="onTableEditClick(scope.row)">编辑</el-button>
<el-button type="text" @click="onTableDeleteClick(scope.row)">删除</el-button>
</div>
</template>
</el-table-column>
</cute-simple-table>
<cute-form-dialog ref="dialogForm" :model="createFormModel" :rules="createFormRules" title="演示:表单对话框" @submit="onDialogFormSubmit">
<el-form-item label="活动名称" prop="name" label-width="100px">
<el-input v-model="createFormModel.name" placeholder="请输入" style="width: 100%" />
</el-form-item>
<el-form-item label="活动区域" prop="region" label-width="100px">
<el-select v-model="createFormModel.region" placeholder="请选择" style="width: 100%">
<el-option label="区域一" value="shanghai" />
<el-option label="区域二" value="beijing" />
</el-select>
</el-form-item>
</cute-form-dialog>
<cute-form-drawer ref="drawerFrom" :model="createFormModel" :rules="createFormRules" title="演示:表单抽屉" @submit="onDrawerFormSubmit">
<el-form-item label="活动名称" prop="name" label-width="100px">
<el-input v-model="createFormModel.name" placeholder="请输入" style="width: 100%" />
</el-form-item>
<el-form-item label="活动区域" prop="region" label-width="100px">
<el-select v-model="createFormModel.region" placeholder="请选择" style="width: 100%">
<el-option label="区域一" value="shanghai" />
<el-option label="区域二" value="beijing" />
</el-select>
</el-form-item>
</cute-form-drawer>
</div>
</template>
<script>
import CuteSimpleTable from '@/views/components/dev/CuteSimpleTable'
import DictService from '@/api/system/dict'
import CuteFormDialog from '@/views/components/dev/CuteFormDialog'
import CuteFormDrawer from '@/views/components/dev/CuteFormDrawer'
import { FormatRowDateTimeStr } from '@/utils/CsUtil'
export default {
name: 'CuteSimpleTableDemo',
components: { CuteFormDrawer, CuteFormDialog, CuteSimpleTable },
data() {
return {
form: {
model: {
blurry: ''
},
rules: {}
},
curd: {
paramsTransform: (pageProps) => {
const values = this.form.model
return {
page: pageProps.current,
size: pageProps.pageSize,
args: {
...values
}
}
},
fetch: async(queryParams) => {
return DictService.queryPageDict(queryParams)
},
columns: [
{ prop: 'name', label: '名称' },
{ prop: 'description', label: '描述' },
{ prop: 'createTime', label: '创建时间', formatter: FormatRowDateTimeStr },
{ prop: 'createBy', label: '创建人' }
],
operateColumn: {
width: '150',
fixed: 'right',
formatter: (row, column, cellValue, index) => {
return (<div>
<el-button type='text' onClick={() => {
console.log('编辑')
}}>编辑
</el-button>
<el-button type='text' onClick={() => {
console.log('删除')
}}>删除
</el-button>
</div>)
}
},
pageProps: {
current: 1,
pageSize: 10,
total: 0
}
},
createFormModel: {
name: '',
region: ''
},
createFormRules: {
name: [
{ required: true, message: '请输入活动名称', trigger: 'blur' },
{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
],
region: [
{ required: true, message: '请选择活动区域', trigger: 'change' }
]
}
}
},
mounted() {
this.initData()
},
methods: {
FormatRowDateTimeStr,
initData() {
this.$refs.instance.refresh()
},
onFormSubmit(formName) {
const that = this
that.$refs[formName].validate((valid) => {
if (valid) {
that.$refs.instance.refresh()
} else {
return false
}
})
},
onFormReset(formName) {
try {
this.$refs[formName].resetFields()
} catch (e) {
console.error(e)
}
},
onDialogClick() {
this.$refs.dialogForm.show()
},
onDialogFormSubmit(values) {
console.log('onDialogFormSubmit', values)
},
onDrawerClick() {
this.$refs.drawerFrom.show()
},
onDrawerFormSubmit(values) {
console.log('onDrawerFormSubmit', values)
},
onTableEditClick(row) {
console.log('编辑', row)
},
onTableDeleteClick(row) {
console.log('删除', row)
}
}
}
</script>
<template>
<div class="app-container">
<!-- 工具栏 -->
<div class="head-container">
<el-form
ref="searchForm"
:inline="true"
:model="form.model"
label-position="right"
label-width="80px"
:rules="form.rules"
>
<el-form-item label="模糊查询" prop="blurry">
<el-input v-model="form.model.blurry" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onFormSubmit('searchForm')">查询</el-button>
<el-button @click="onFormReset('searchForm')">重置</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onDialogClick">演示:表单对话框</el-button>
<el-button type="primary" @click="onDrawerClick">演示:表单抽屉</el-button>
</el-form-item>
</el-form>
</div>
<!-- 表格渲染 -->
<!-- fetch: 获取远程数据 -->
<!-- params-transform: 组装查询参数 -->
<!-- responseTransform: 组装表格对象。对响应结果做处理 -->
<!-- primary-key: 主键 -->
<!-- mode: 模式。不传默认,传multi为多选 -->
<!-- @selection-change: 当且仅当mode为multi时启用 -->
<cute-simple-table
ref="instance"
:fetch="curd.fetch"
:params-transform="curd.paramsTransform"
primary-key="id"
:page-props="curd.pageProps"
>
<el-table-column prop="name" label="名称" />
<el-table-column prop="description" label="描述" />
<el-table-column prop="createTime" label="创建时间" :formatter="FormatRowDateTimeStr" />
<el-table-column prop="createBy" label="创建人" />
<el-table-column label="操作" width="150" min-width="150" fixed="right">
<template slot-scope="scope">
<div>
<el-button type="text" @click="onTableEditClick(scope.row)">编辑</el-button>
<el-button type="text" @click="onTableDeleteClick(scope.row)">删除</el-button>
</div>
</template>
</el-table-column>
</cute-simple-table>
<cute-form-dialog ref="dialogForm" :model="createFormModel" :rules="createFormRules" title="演示:表单对话框" @submit="onDialogFormSubmit">
<el-form-item label="活动名称" prop="name" label-width="100px">
<el-input v-model="createFormModel.name" placeholder="请输入" style="width: 100%" />
</el-form-item>
<el-form-item label="活动区域" prop="region" label-width="100px">
<el-select v-model="createFormModel.region" placeholder="请选择" style="width: 100%">
<el-option label="区域一" value="shanghai" />
<el-option label="区域二" value="beijing" />
</el-select>
</el-form-item>
</cute-form-dialog>
<cute-form-drawer ref="drawerFrom" :model="createFormModel" :rules="createFormRules" title="演示:表单抽屉" @submit="onDrawerFormSubmit">
<el-form-item label="活动名称" prop="name" label-width="100px">
<el-input v-model="createFormModel.name" placeholder="请输入" style="width: 100%" />
</el-form-item>
<el-form-item label="活动区域" prop="region" label-width="100px">
<el-select v-model="createFormModel.region" placeholder="请选择" style="width: 100%">
<el-option label="区域一" value="shanghai" />
<el-option label="区域二" value="beijing" />
</el-select>
</el-form-item>
</cute-form-drawer>
</div>
</template>
<script>
import CuteSimpleTable from '@/views/components/dev/CuteSimpleTable'
import DictService from '@/api/system/dict'
import CuteFormDialog from '@/views/components/dev/CuteFormDialog'
import CuteFormDrawer from '@/views/components/dev/CuteFormDrawer'
import { FormatRowDateTimeStr } from '@/utils/CsUtil'
export default {
name: 'CuteSimpleTableDemo',
components: { CuteFormDrawer, CuteFormDialog, CuteSimpleTable },
data() {
return {
form: {
model: {
blurry: ''
},
rules: {}
},
curd: {
paramsTransform: (pageProps) => {
const values = this.form.model
return {
page: pageProps.current,
size: pageProps.pageSize,
args: {
...values
}
}
},
fetch: async(queryParams) => {
return DictService.queryPageDict(queryParams)
},
columns: [
{ prop: 'name', label: '名称' },
{ prop: 'description', label: '描述' },
{ prop: 'createTime', label: '创建时间', formatter: FormatRowDateTimeStr },
{ prop: 'createBy', label: '创建人' }
],
operateColumn: {
width: '150',
fixed: 'right',
formatter: (row, column, cellValue, index) => {
return (<div>
<el-button type='text' onClick={() => {
console.log('编辑')
}}>编辑
</el-button>
<el-button type='text' onClick={() => {
console.log('删除')
}}>删除
</el-button>
</div>)
}
},
pageProps: {
current: 1,
pageSize: 10,
total: 0
}
},
createFormModel: {
name: '',
region: ''
},
createFormRules: {
name: [
{ required: true, message: '请输入活动名称', trigger: 'blur' },
{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
],
region: [
{ required: true, message: '请选择活动区域', trigger: 'change' }
]
}
}
},
mounted() {
this.initData()
},
methods: {
FormatRowDateTimeStr,
initData() {
this.$refs.instance.refresh()
},
onFormSubmit(formName) {
const that = this
that.$refs[formName].validate((valid) => {
if (valid) {
that.$refs.instance.refresh()
} else {
return false
}
})
},
onFormReset(formName) {
try {
this.$refs[formName].resetFields()
} catch (e) {
console.error(e)
}
},
onDialogClick() {
this.$refs.dialogForm.show()
},
onDialogFormSubmit(values) {
console.log('onDialogFormSubmit', values)
},
onDrawerClick() {
this.$refs.drawerFrom.show()
},
onDrawerFormSubmit(values) {
console.log('onDrawerFormSubmit', values)
},
onTableEditClick(row) {
console.log('编辑', row)
},
onTableDeleteClick(row) {
console.log('删除', row)
}
}
}
</script>
@@ -1,256 +1,256 @@
<template>
<div class="app-container">
<!-- <cute-yaml-editor :content="content" @change="onChange" />-->
<cute-code-editor :content="content" mode="yaml" @change="onChange" />
</div>
</template>
<script>
// 旧组件
// import CuteYamlEditor from '@/views/components/dev/CuteYamlEditor'
// 新组件
import CuteCodeEditor from '@/views/components/dev/CuteCodeEditor'
export default {
name: 'CuteYamlEditorDemo',
// components: { CuteYamlEditor },
components: { CuteCodeEditor },
data() {
return {
content: 'server:\n' +
' port: 8000\n' +
' http2:\n' +
' # 启用 HTTP/2 支持,提升传输效率\n' +
' enabled: true\n' +
' undertow:\n' +
' threads:\n' +
' # 工作线程数,默认设置为io-threads * 8。如果你的应用程序有很多同步阻塞操作,可以适当增加这个值\n' +
' worker: 8\n' +
' # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程\n' +
' # 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载\n' +
' io: 4\n' +
' # 设置为true以使用直接内存(堆外内存)来存储缓冲区。这可以减少垃圾回收的开销。\n' +
' direct-buffers: true\n' +
' # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理\n' +
' # 每块buffer的空间大小,越小的空间被利用越充分\n' +
' buffer-size: 1024\n' +
' accesslog:\n' +
' # 关闭日志\n' +
' enabled: false\n' +
' compression:\n' +
' # 启用 GZIP 压缩,减少传输数据量\n' +
' enabled: true\n' +
' # 需要压缩的 MIME 类型\n' +
' mime-types: text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json\n' +
' # 最小压缩响应大小(字节)\n' +
' min-response-size: 1024\n' +
' # 启用优雅停机,并遵守spring.lifecycle.timeout-per-shutdown-phase属性中给出的超时\n' +
' # GRACEFUL (优雅): 当应用程序以"GRACEFUL"模式关闭时,它不会接受新的请求且会尝试完成所有正在进行的请求和处理,然后才会终止。这种方式适用于那些可能需要一些时间来清理资源或完成正在进行的任务的场景。\n' +
' # IMMEDIATE(立即): 当应用程序以"IMMEDIATE"模式关闭时,它会立即终止,而不管当前是否有任何活动任务或请求。这种方式适用于那些可以立即停止而不会造成严重问题的情况。\n' +
' shutdown: graceful\n' +
'spring:\n' +
' application:\n' +
' name: kenaito-devops\n' +
' title: Kenaito DevOps\n' +
' lifecycle:\n' +
' # 采用java.time.Duration格式的值,如果在这个时间内,优雅停机没有停掉应用,超过这个时间就会强制停止应用\n' +
' timeout-per-shutdown-phase: 30s\n' +
' freemarker:\n' +
' # 是否检查模板位置是否存在\n' +
' check-template-location: false\n' +
' # 模板编码\n' +
' charset: utf-8\n' +
' cache:\n' +
' # 解决缓存异常 https://blog.csdn.net/jikeyeka/article/details/125804049\n' +
' type: redis\n' +
' data:\n' +
' redis:\n' +
' repositories:\n' +
' # 是否启用Redis存储(关闭防止出现 Multiple Spring Data modules found, entering strict repository configuration mode)\n' +
' enabled: false\n' +
' datasource:\n' +
' druid:\n' +
' db-type: com.alibaba.druid.pool.DruidDataSource\n' +
' driverClassName: com.p6spy.engine.spy.P6SpyDriver\n' +
' url: jdbc:p6spy:mysql://192.168.100.128:23306/cutejava?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true\n' +
' username: root\n' +
' password: lm,101208..,.\n' +
' # 初始连接数,建议设置为与最小空闲连接数相同\n' +
' initial-size: 2\n' +
' # 最小空闲连接数,保持足够的空闲连接以应对请求\n' +
' min-idle: 2\n' +
' # 最大连接数,根据并发需求适当增加\n' +
' max-active: 8\n' +
' # 获取连接超时时间(毫秒),调整以满足响应时间要求\n' +
' max-wait: 3000\n' +
' # 启用KeepAlive机制,保持长连接\n' +
' keep-alive: true\n' +
' # 连接有效性检测间隔时间(毫秒),定期检查连接的健康状态\n' +
' time-between-eviction-runs-millis: 60000\n' +
' # 连接在池中最小生存时间(毫秒),确保连接在池中至少存在一段时间\n' +
' min-evictable-idle-time-millis: 300000\n' +
' # 连接在池中最大生存时间(毫秒),防止连接在池中停留过长\n' +
' max-evictable-idle-time-millis: 900000\n' +
' # 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除\n' +
' test-while-idle: true\n' +
' # 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个\n' +
' test-on-borrow: true\n' +
' # 是否在归还到池中前进行检验\n' +
' test-on-return: false\n' +
' # 停用 com_ping 探活机制\n' +
' use-ping-method: false\n' +
' # 检测连接是否有效\n' +
' validation-query: SELECT 1\n' +
' # 配置监控统计\n' +
' web-stat-filter:\n' +
' enabled: true\n' +
' url-pattern: /*\n' +
' # 开启session统计功能\n' +
' session-stat-enable: true\n' +
' exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"\n' +
' # 缺省sessionStatMaxCount是1000个\n' +
' session-stat-max-count: 1000\n' +
' stat-view-servlet:\n' +
' enabled: true\n' +
' url-pattern: /druid/*\n' +
' reset-enable: false\n' +
' filter:\n' +
' stat:\n' +
' enabled: true\n' +
' # 记录慢SQL\n' +
' log-slow-sql: true\n' +
' slow-sql-millis: 2000\n' +
' merge-sql: true\n' +
' wall:\n' +
' config:\n' +
' multi-statement-allow: true\n' +
' aop-patterns: "cn.odboy.mapper.*,cn.odboy.service.*,cn.odboy.*.mapper.*,cn.odboy.*.service.*"\n' +
' redis:\n' +
' database: ${REDIS_DB:1}\n' +
' host: ${REDIS_HOST:192.168.100.128}\n' +
' port: ${REDIS_PORT:26379}\n' +
' password: ${REDIS_PWD:lm,101208..,.}\n' +
' # 连接超时时间\n' +
' timeout: 5000\n' +
' # 连接池配置\n' +
' lettuce:\n' +
' pool:\n' +
' # 连接池最大连接数\n' +
' max-active: 30\n' +
' # 连接池最大阻塞等待时间(毫秒),负值表示没有限制\n' +
' max-wait: -1\n' +
' # 连接池中的最大空闲连接数\n' +
' max-idle: 20\n' +
' # 连接池中的最小空闲连接数\n' +
' min-idle: 1\n' +
'mybatis-plus:\n' +
' configuration:\n' +
' # 开启 Mybatis 二级缓存,默认为 true\n' +
' cache-enabled: false\n' +
' # 设置本地缓存作用域, Mybatis 一级缓存, 默认为 SESSION\n' +
' # 同一个 session 相同查询语句不会再次查询数据库\n' +
' # 微服务中, 建议设置为STATEMENT, 即关闭一级缓存\n' +
' local-cache-scope: STATEMENT\n' +
' # 是否开启自动驼峰命名规则(camel case)映射, 即从经典数据库列名 A_COLUMN(下划线命名) 到经典 Java 属性名 aColumn(驼峰命名) 的类似映射\n' +
' map-underscore-to-camel-case: true\n' +
' # Sql日志\n' +
' log-impl: org.apache.ibatis.logging.stdout.StdOutImpl\n' +
' # 启动时是否检查 MyBatis XML 文件的存在, 默认不检查\n' +
' check-config-location: true\n' +
' # MyBatis Mapper 所对应的 XML 文件位置\n' +
' # Maven 多模块项目的扫描路径需以 classpath*: 开头 (即加载多个 jar 包下的 XML 文件)\n' +
' mapper-locations: classpath*:/mapper/**/*.xml\n' +
' # MyBatis-Plus 全局策略中的 DB 策略配置\n' +
' global-config:\n' +
' db-config:\n' +
' # 逻辑已删除值(逻辑删除下有效)\n' +
' logic-delete-value: 0\n' +
' # 逻辑未删除值(逻辑删除下有效)\n' +
' logic-not-delete-value: 1\n' +
' # 全局默认主键类型, 这里为自增主键\n' +
' id-type: auto\n' +
' # 表名是否使用驼峰转下划线命名,只对表名生效\n' +
' table-underline: true\n' +
' # 是否控制台 print mybatisplus-plus 的 LOGO\n' +
' banner: true\n' +
'app:\n' +
' # 密码加密传输,前端公钥加密,后端私钥解密\n' +
' rsa:\n' +
' private-key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==\n' +
' # 鉴权\n' +
' jwt:\n' +
' # 必须使用最少88位的Base64对该令牌进行编码\n' +
' base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI=\n' +
' # 令牌过期时间 此处单位/毫秒 ,默认4小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html\n' +
' token-validity-in-seconds: 14400000\n' +
' # token 续期检查时间范围(默认30分钟,单位毫秒),在token即将过期的一段时间内用户操作了,则给用户的token续期\n' +
' detect: 1800000\n' +
' # 续期时间范围,默认1小时,单位毫秒\n' +
' renew: 3600000\n' +
' # 登录\n' +
' login:\n' +
' # 是否限制单用户登录\n' +
' single: false\n' +
' # 验证码\n' +
' captchaSetting:\n' +
' # 验证码类型配置 查看 LoginProperties 类\n' +
' code-type: arithmetic\n' +
' # 登录图形验证码有效时间/分钟\n' +
' expiration: 2\n' +
' # 验证码高度\n' +
' width: 111\n' +
' # 验证码宽度\n' +
' height: 36\n' +
' # 内容长度\n' +
' length: 2\n' +
' # 字体名称,为空则使用默认字体\n' +
' font-name:\n' +
' # 字体大小\n' +
' font-size: 25\n' +
' # 是否开启 swagger-ui\n' +
' swagger:\n' +
' enabled: true\n' +
' # 针对@Async\n' +
' async-task-pool:\n' +
' # 核心线程池大小\n' +
' core-pool-size: 10\n' +
' # 最大线程数\n' +
' max-pool-size: 30\n' +
' # 活跃时间\n' +
' keep-alive-seconds: 60\n' +
' # 队列容量\n' +
' queue-capacity: 50\n' +
' pipeline-task-pool:\n' +
' # 核心线程池大小\n' +
' core-pool-size: 10\n' +
' # 最大线程数\n' +
' max-pool-size: 200\n' +
' # 活跃时间\n' +
' keep-alive-seconds: 60\n' +
' # 队列容量\n' +
' queue-capacity: 300\n' +
' # oss\n' +
' oss:\n' +
' max-size: 100\n' +
' minio:\n' +
' endpoint: http://192.168.100.128:9000\n' +
' bucketName: cutejava\n' +
' accessKey: 8o5oVzqvKby5TzaGcfmx\n' +
' secretKey: 8BiK5UbmvXGJNVQ98CGiohHzT1N1FMRZqHRdJllj\n' +
' captcha:\n' +
' expireTime: 300\n' +
'## 启用debug\n' +
'#debug: true\n' +
'#logging:\n' +
'# level:\n' +
'# root: debug'
}
},
methods: {
onChange(value) {
console.log('onChange', value)
}
}
}
</script>
<template>
<div class="app-container">
<!-- <cute-yaml-editor :content="content" @change="onChange" />-->
<cute-code-editor :content="content" mode="yaml" @change="onChange" />
</div>
</template>
<script>
// 旧组件
// import CuteYamlEditor from '@/views/components/dev/CuteYamlEditor'
// 新组件
import CuteCodeEditor from '@/views/components/dev/CuteCodeEditor'
export default {
name: 'CuteYamlEditorDemo',
// components: { CuteYamlEditor },
components: { CuteCodeEditor },
data() {
return {
content: 'server:\n' +
' port: 8000\n' +
' http2:\n' +
' # 启用 HTTP/2 支持,提升传输效率\n' +
' enabled: true\n' +
' undertow:\n' +
' threads:\n' +
' # 工作线程数,默认设置为io-threads * 8。如果你的应用程序有很多同步阻塞操作,可以适当增加这个值\n' +
' worker: 8\n' +
' # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程\n' +
' # 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载\n' +
' io: 4\n' +
' # 设置为true以使用直接内存(堆外内存)来存储缓冲区。这可以减少垃圾回收的开销。\n' +
' direct-buffers: true\n' +
' # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理\n' +
' # 每块buffer的空间大小,越小的空间被利用越充分\n' +
' buffer-size: 1024\n' +
' accesslog:\n' +
' # 关闭日志\n' +
' enabled: false\n' +
' compression:\n' +
' # 启用 GZIP 压缩,减少传输数据量\n' +
' enabled: true\n' +
' # 需要压缩的 MIME 类型\n' +
' mime-types: text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json\n' +
' # 最小压缩响应大小(字节)\n' +
' min-response-size: 1024\n' +
' # 启用优雅停机,并遵守spring.lifecycle.timeout-per-shutdown-phase属性中给出的超时\n' +
' # GRACEFUL (优雅): 当应用程序以"GRACEFUL"模式关闭时,它不会接受新的请求且会尝试完成所有正在进行的请求和处理,然后才会终止。这种方式适用于那些可能需要一些时间来清理资源或完成正在进行的任务的场景。\n' +
' # IMMEDIATE(立即): 当应用程序以"IMMEDIATE"模式关闭时,它会立即终止,而不管当前是否有任何活动任务或请求。这种方式适用于那些可以立即停止而不会造成严重问题的情况。\n' +
' shutdown: graceful\n' +
'spring:\n' +
' application:\n' +
' name: cutejava\n' +
' title: CuteJava\n' +
' lifecycle:\n' +
' # 采用java.time.Duration格式的值,如果在这个时间内,优雅停机没有停掉应用,超过这个时间就会强制停止应用\n' +
' timeout-per-shutdown-phase: 30s\n' +
' freemarker:\n' +
' # 是否检查模板位置是否存在\n' +
' check-template-location: false\n' +
' # 模板编码\n' +
' charset: utf-8\n' +
' cache:\n' +
' # 解决缓存异常 https://blog.csdn.net/jikeyeka/article/details/125804049\n' +
' type: redis\n' +
' data:\n' +
' redis:\n' +
' repositories:\n' +
' # 是否启用Redis存储(关闭防止出现 Multiple Spring Data modules found, entering strict repository configuration mode)\n' +
' enabled: false\n' +
' datasource:\n' +
' druid:\n' +
' db-type: com.alibaba.druid.pool.DruidDataSource\n' +
' driverClassName: com.p6spy.engine.spy.P6SpyDriver\n' +
' url: jdbc:p6spy:mysql://192.168.100.128:23306/cutejava?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true\n' +
' username: root\n' +
' password: lm,101208..,.\n' +
' # 初始连接数,建议设置为与最小空闲连接数相同\n' +
' initial-size: 2\n' +
' # 最小空闲连接数,保持足够的空闲连接以应对请求\n' +
' min-idle: 2\n' +
' # 最大连接数,根据并发需求适当增加\n' +
' max-active: 8\n' +
' # 获取连接超时时间(毫秒),调整以满足响应时间要求\n' +
' max-wait: 3000\n' +
' # 启用KeepAlive机制,保持长连接\n' +
' keep-alive: true\n' +
' # 连接有效性检测间隔时间(毫秒),定期检查连接的健康状态\n' +
' time-between-eviction-runs-millis: 60000\n' +
' # 连接在池中最小生存时间(毫秒),确保连接在池中至少存在一段时间\n' +
' min-evictable-idle-time-millis: 300000\n' +
' # 连接在池中最大生存时间(毫秒),防止连接在池中停留过长\n' +
' max-evictable-idle-time-millis: 900000\n' +
' # 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除\n' +
' test-while-idle: true\n' +
' # 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个\n' +
' test-on-borrow: true\n' +
' # 是否在归还到池中前进行检验\n' +
' test-on-return: false\n' +
' # 停用 com_ping 探活机制\n' +
' use-ping-method: false\n' +
' # 检测连接是否有效\n' +
' validation-query: SELECT 1\n' +
' # 配置监控统计\n' +
' web-stat-filter:\n' +
' enabled: true\n' +
' url-pattern: /*\n' +
' # 开启session统计功能\n' +
' session-stat-enable: true\n' +
' exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"\n' +
' # 缺省sessionStatMaxCount是1000个\n' +
' session-stat-max-count: 1000\n' +
' stat-view-servlet:\n' +
' enabled: true\n' +
' url-pattern: /druid/*\n' +
' reset-enable: false\n' +
' filter:\n' +
' stat:\n' +
' enabled: true\n' +
' # 记录慢SQL\n' +
' log-slow-sql: true\n' +
' slow-sql-millis: 2000\n' +
' merge-sql: true\n' +
' wall:\n' +
' config:\n' +
' multi-statement-allow: true\n' +
' aop-patterns: "cn.odboy.mapper.*,cn.odboy.service.*,cn.odboy.*.mapper.*,cn.odboy.*.service.*"\n' +
' redis:\n' +
' database: ${REDIS_DB:1}\n' +
' host: ${REDIS_HOST:192.168.100.128}\n' +
' port: ${REDIS_PORT:26379}\n' +
' password: ${REDIS_PWD:lm,101208..,.}\n' +
' # 连接超时时间\n' +
' timeout: 5000\n' +
' # 连接池配置\n' +
' lettuce:\n' +
' pool:\n' +
' # 连接池最大连接数\n' +
' max-active: 30\n' +
' # 连接池最大阻塞等待时间(毫秒),负值表示没有限制\n' +
' max-wait: -1\n' +
' # 连接池中的最大空闲连接数\n' +
' max-idle: 20\n' +
' # 连接池中的最小空闲连接数\n' +
' min-idle: 1\n' +
'mybatis-plus:\n' +
' configuration:\n' +
' # 开启 Mybatis 二级缓存,默认为 true\n' +
' cache-enabled: false\n' +
' # 设置本地缓存作用域, Mybatis 一级缓存, 默认为 SESSION\n' +
' # 同一个 session 相同查询语句不会再次查询数据库\n' +
' # 微服务中, 建议设置为STATEMENT, 即关闭一级缓存\n' +
' local-cache-scope: STATEMENT\n' +
' # 是否开启自动驼峰命名规则(camel case)映射, 即从经典数据库列名 A_COLUMN(下划线命名) 到经典 Java 属性名 aColumn(驼峰命名) 的类似映射\n' +
' map-underscore-to-camel-case: true\n' +
' # Sql日志\n' +
' log-impl: org.apache.ibatis.logging.stdout.StdOutImpl\n' +
' # 启动时是否检查 MyBatis XML 文件的存在, 默认不检查\n' +
' check-config-location: true\n' +
' # MyBatis Mapper 所对应的 XML 文件位置\n' +
' # Maven 多模块项目的扫描路径需以 classpath*: 开头 (即加载多个 jar 包下的 XML 文件)\n' +
' mapper-locations: classpath*:/mapper/**/*.xml\n' +
' # MyBatis-Plus 全局策略中的 DB 策略配置\n' +
' global-config:\n' +
' db-config:\n' +
' # 逻辑已删除值(逻辑删除下有效)\n' +
' logic-delete-value: 0\n' +
' # 逻辑未删除值(逻辑删除下有效)\n' +
' logic-not-delete-value: 1\n' +
' # 全局默认主键类型, 这里为自增主键\n' +
' id-type: auto\n' +
' # 表名是否使用驼峰转下划线命名,只对表名生效\n' +
' table-underline: true\n' +
' # 是否控制台 print mybatisplus-plus 的 LOGO\n' +
' banner: true\n' +
'app:\n' +
' # 密码加密传输,前端公钥加密,后端私钥解密\n' +
' rsa:\n' +
' private-key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==\n' +
' # 鉴权\n' +
' jwt:\n' +
' # 必须使用最少88位的Base64对该令牌进行编码\n' +
' base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI=\n' +
' # 令牌过期时间 此处单位/毫秒 ,默认4小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html\n' +
' token-validity-in-seconds: 14400000\n' +
' # token 续期检查时间范围(默认30分钟,单位毫秒),在token即将过期的一段时间内用户操作了,则给用户的token续期\n' +
' detect: 1800000\n' +
' # 续期时间范围,默认1小时,单位毫秒\n' +
' renew: 3600000\n' +
' # 登录\n' +
' login:\n' +
' # 是否限制单用户登录\n' +
' single: false\n' +
' # 验证码\n' +
' captchaSetting:\n' +
' # 验证码类型配置 查看 LoginProperties 类\n' +
' code-type: arithmetic\n' +
' # 登录图形验证码有效时间/分钟\n' +
' expiration: 2\n' +
' # 验证码高度\n' +
' width: 111\n' +
' # 验证码宽度\n' +
' height: 36\n' +
' # 内容长度\n' +
' length: 2\n' +
' # 字体名称,为空则使用默认字体\n' +
' font-name:\n' +
' # 字体大小\n' +
' font-size: 25\n' +
' # 是否开启 swagger-ui\n' +
' swagger:\n' +
' enabled: true\n' +
' # 针对@Async\n' +
' async-task-pool:\n' +
' # 核心线程池大小\n' +
' core-pool-size: 10\n' +
' # 最大线程数\n' +
' max-pool-size: 30\n' +
' # 活跃时间\n' +
' keep-alive-seconds: 60\n' +
' # 队列容量\n' +
' queue-capacity: 50\n' +
' pipeline-task-pool:\n' +
' # 核心线程池大小\n' +
' core-pool-size: 10\n' +
' # 最大线程数\n' +
' max-pool-size: 200\n' +
' # 活跃时间\n' +
' keep-alive-seconds: 60\n' +
' # 队列容量\n' +
' queue-capacity: 300\n' +
' # oss\n' +
' oss:\n' +
' max-size: 100\n' +
' minio:\n' +
' endpoint: http://192.168.100.128:9000\n' +
' bucketName: cutejava\n' +
' accessKey: 8o5oVzqvKby5TzaGcfmx\n' +
' secretKey: 8BiK5UbmvXGJNVQ98CGiohHzT1N1FMRZqHRdJllj\n' +
' captcha:\n' +
' expireTime: 300\n' +
'## 启用debug\n' +
'#debug: true\n' +
'#logging:\n' +
'# level:\n' +
'# root: debug'
}
},
methods: {
onChange(value) {
console.log('onChange', value)
}
}
}
</script>