Browse Source

chore: 模板初步设计

master
wangxiang 1 year ago
parent
commit
6815a7288e
  1. 1
      src/api/platform/system/entity/gencodeTemplateObj.ts
  2. 8
      src/components/AceEditor/src/config.ts
  3. 188
      src/views/system/devtools/template/TemplateModal.vue
  4. 81
      src/views/system/devtools/template/TemplatePromptModal.vue

1
src/api/platform/system/entity/gencodeTemplateObj.ts

@ -11,6 +11,7 @@ export interface GencodeTemplateObj extends CommonEntity { @@ -11,6 +11,7 @@ export interface GencodeTemplateObj extends CommonEntity {
defaultContents: string;
sort: string;
isChild: string;
index?: string;
[key: string]: any;
}

8
src/components/AceEditor/src/config.ts

@ -1,3 +1,5 @@ @@ -1,3 +1,5 @@
// 语言配置
import ace from 'ace-builds';
import modeJsonUrl from 'ace-builds/src-noconflict/mode-json?url';
@ -12,6 +14,10 @@ ace.config.setModuleUrl('ace/mode/html', modeHtmlUrl); @@ -12,6 +14,10 @@ ace.config.setModuleUrl('ace/mode/html', modeHtmlUrl);
import modeYamlUrl from 'ace-builds/src-noconflict/mode-yaml?url';
ace.config.setModuleUrl('ace/mode/yaml', modeYamlUrl);
import modeVelocityUrl from 'ace-builds/src-noconflict/mode-velocity?url';
ace.config.setModuleUrl('ace/mode/velocity', modeVelocityUrl);
// 主题配置
import themeGithubUrl from 'ace-builds/src-noconflict/theme-github?url';
ace.config.setModuleUrl('ace/theme/github', themeGithubUrl);
@ -24,6 +30,7 @@ ace.config.setModuleUrl('ace/theme/monokai', themeMonokaiUrl); @@ -24,6 +30,7 @@ ace.config.setModuleUrl('ace/theme/monokai', themeMonokaiUrl);
import themeDraculaUrl from 'ace-builds/src-noconflict/theme-dracula?url';
ace.config.setModuleUrl('ace/theme/dracula', themeDraculaUrl);
// 浏览器后台多线程配置
import workerBaseUrl from 'ace-builds/src-noconflict/worker-base?url';
ace.config.setModuleUrl('ace/mode/base', workerBaseUrl);
@ -39,6 +46,7 @@ ace.config.setModuleUrl('ace/mode/html_worker', workerHtmlUrl); @@ -39,6 +46,7 @@ ace.config.setModuleUrl('ace/mode/html_worker', workerHtmlUrl);
import workerYamlUrl from 'ace-builds/src-noconflict/worker-yaml?url';
ace.config.setModuleUrl('ace/mode/yaml_worker', workerYamlUrl);
// 快速补全代码段配置
import snippetsHtmlUrl from 'ace-builds/src-noconflict/snippets/html?url';
ace.config.setModuleUrl('ace/snippets/html', snippetsHtmlUrl);

188
src/views/system/devtools/template/TemplateModal.vue

@ -1,27 +1,91 @@ @@ -1,27 +1,91 @@
<template>
<BasicModal
v-bind="$attrs"
defaultFullscreen
:canFullscreen="false"
@register="registerModal"
@ok="handleSubmit"
>
<BasicForm @register="registerForm"/>
<AceEditor v-model:value="state.content" @register="registerAceEditor"/>
</BasicModal>
<div>
<BasicModal
v-bind="$attrs"
defaultFullscreen
:canFullscreen="false"
@register="registerModal"
@ok="handleSubmit"
>
<BasicForm @register="registerForm"/>
<ATabs v-model:activeKey="state.typeActiveKey" type="card">
<ATabPane key="1" tab="主表">
<div class="tool-bar">
<a-button type="primary" @click="handleAddTab">新增</a-button>
<a-button type="primary" @click="handleEditTab">编辑</a-button>
</div>
<ADivider/>
<ATabs v-show="mainTemplateObjs.length > 0"
v-model:activeKey="state.mainActiveKey"
type="editable-card"
hideAdd
@edit="handleRemoveTab"
>
<ATabPane v-for="mainTemplateObj in mainTemplateObjs" :key="mainTemplateObj.index || mainTemplateObj.id" :tab="mainTemplateObj.name">
<AceEditor v-model:value="mainTemplateObj.contents"
class="vue-ace-editor"
@register="registerAceEditor"
/>
</ATabPane>
</ATabs>
</ATabPane>
<ATabPane key="2" tab="附表">
<div class="tool-bar">
<a-button type="primary" @click="handleAddTab">新增</a-button>
<a-button type="primary" @click="handleEditTab">编辑</a-button>
</div>
<ADivider/>
<ATabs v-show="childTemplateObjs.length > 0"
v-model:activeKey="state.childActiveKey"
type="editable-card"
hideAdd
@edit="handleRemoveTab"
>
<ATabPane v-for="childTemplateObj in childTemplateObjs" :key="childTemplateObj.index || childTemplateObj.id" :tab="childTemplateObj.name">
<AceEditor v-model:value="childTemplateObj.contents" @register="registerAceEditor"/>
</ATabPane>
</ATabs>
</ATabPane>
</ATabs>
</BasicModal>
<TemplatePromptModal @register="registerPromptModal" @success="handlePrompt"/>
</div>
</template>
<script lang="ts" setup>
import { reactive } from 'vue';
import { reactive, computed } from 'vue';
import { BasicForm, useForm } from '/@/components/Form/index';
import { formSchema } from './template.data';
import { getGenCodeTemplateGroup, saveAndGencodeTemplateObj } from '/@/api/platform/system/controller/gencodeTemplateGroup';
import { BasicModal, ModalProps, useModalInner } from '/@/components/Modal';
import type { GencodeTemplateObj } from '/@/api/platform/system/entity/gencodeTemplateObj';
import { BasicModal, ModalProps, useModalInner, useModal } from '/@/components/Modal';
import { AceEditor, useAceEditor } from '/@/components/AceEditor';
import { Tabs, Divider } from 'ant-design-vue';
import TemplatePromptModal from './TemplatePromptModal.vue';
const state = reactive({
const ATabs = Tabs;
const ATabPane = Tabs.TabPane;
const ADivider = Divider;
type templateTypePartial = Partial<GencodeTemplateObj>;
interface WindowState {
tag: string;
templateObjs: templateTypePartial[];
mainActiveKey: string;
childActiveKey: string;
typeActiveKey: string;
}
const state = reactive<WindowState>({
tag: '',
content: ''
templateObjs: [],
mainActiveKey: '',
childActiveKey: '',
typeActiveKey: ''
});
const mainTemplateObjs = computed(() => state.templateObjs.filter(item => item.isChild === '0'));
const childTemplateObjs = computed(() => state.templateObjs.filter(item => item.isChild === '1'));
const [registerPromptModal, { openModal: openPromptModal }] = useModal();
/** https://v3.cn.vuejs.org/api/options-data.html#emits */
const emit = defineEmits(['success', 'register']);
const [registerForm, { resetFields, setFieldsValue, validate, clearValidate, setProps, updateSchema }] = useForm({
@ -31,7 +95,7 @@ @@ -31,7 +95,7 @@
baseColProps: { span: 24 }
});
const [registerAceEditor, { setProps: setAceEditorProps }] = useAceEditor({
lang: 'javascript',
lang: 'velocity',
options: {
useWorker: true,
enableBasicAutocompletion: true,
@ -58,18 +122,76 @@ @@ -58,18 +122,76 @@
await setFieldsValue(await getGenCodeTemplateGroup(id));
break;
}
// :
setModalProps(props);
});
function handleAddTab() {
openPromptModal(true, { _tag: 'add' });
}
function handleEditTab() {
openPromptModal(true, { _tag: 'edit' });
}
function handleRemoveTab(targetKey: string) {
let lastIndex = 0;
(state.typeActiveKey == '1' ? mainTemplateObjs : childTemplateObjs).value.forEach((item, i) => {
if ((item.index || item.id) == targetKey) {
lastIndex = i - 1;
}
});
state.templateObjs = state.templateObjs.filter(item => (item.index || item.id) != targetKey);
// tabtab
if (state.typeActiveKey == '1') {
if (mainTemplateObjs.value.length && state.mainActiveKey === targetKey) {
if (lastIndex >= 0) {
const mainTemplate = mainTemplateObjs.value[lastIndex];
state.mainActiveKey = (mainTemplate.index || mainTemplate.id)!;
} else {
const mainTemplate = mainTemplateObjs.value[0];
state.mainActiveKey = (mainTemplate.index || mainTemplate.id)!;
}
}
} else {
if (childTemplateObjs.value.length && state.childActiveKey === targetKey) {
if (lastIndex >= 0) {
const childTemplate = childTemplateObjs.value[lastIndex];
state.childActiveKey = (childTemplate.index || childTemplate.id)!;
} else {
const childTemplate = childTemplateObjs.value[0];
state.childActiveKey = (childTemplate.index || childTemplate.id)!;
}
}
}
}
function handlePrompt({ name }) {
const index = state.templateObjs.findIndex(item => (item.index || item.id) == (state.typeActiveKey == '1' ? state.mainActiveKey : state.childActiveKey));
let template: templateTypePartial = {
name,
contents: '',
isChild: state.typeActiveKey == '1' ? '0' : '1',
index: `t${Date.now()}`
};
if (index != -1) {
template = Object.assign({}, state.templateObjs[index], { name });
state.templateObjs.splice(index, 1, template);
} else state.templateObjs.push(template);
// tab
if (state.typeActiveKey == '1'){
state.mainActiveKey = (template.index || template.id)!;
} else state.childActiveKey = (template.index || template.id)!;
}
/** 处理弹出框提交 */
async function handleSubmit() {
try {
//
const formData = await validate();
formData.genCodeTemplateObjList = state.templateObjs;
//
setModalProps({ confirmLoading: true });
await saveAndGencodeTemplateObj(formData);
//
closeModal();
emit('success');
@ -78,3 +200,35 @@ @@ -78,3 +200,35 @@
}
}
</script>
<style lang="less" scoped>
.ant-tabs-card {
border: 1px solid #E4E7ED;
:deep(.ant-tabs-content) {
padding: 0 10px;
min-height: 50px;
.tool-bar {
margin-bottom: 20px;
.ant-btn {
margin-right: 10px;
}
}
.vue-ace-editor {
min-height: 500px;
font-size: 12px;
}
.ant-divider-horizontal {
margin: 10px;
}
}
}
[data-theme='dark'] {
.ant-tabs-card {
border-color: #424242;
}
}
</style>

81
src/views/system/devtools/template/TemplatePromptModal.vue

@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
<template>
<BasicModal
v-bind="$attrs"
minHeight="100px"
@ok="handleSubmit"
@register="registerModal"
>
<Form :model="modelRef" :rules="rulesRef">
<FormItem name="name" v-bind="validateInfos.name">
<a-input v-model:value="modelRef.name" placeholder="请输入文件名称"/>
</FormItem>
</Form>
</BasicModal>
</template>
<script lang="ts" setup>
/**
* 提供模板规范代码参考,请尽量保证编写代码风格跟模板规范代码一致
* 采用ant-design-vue原生组件编写表单,采用 setup 写法
* Copyright © 2023-2023 <a href="https://godolphinx.org">海豚生态开源社区</a> All rights reserved.
* author wangxiang4
*/
import { reactive } from 'vue';
import { BasicModal, ModalProps, useModalInner } from '/@/components/Modal';
import { Form } from 'ant-design-vue';
import { useMessage } from '/@/hooks/web/useMessage';
/** 类型规范统一声明定义区域 */
interface WindowState {
name: string;
}
/** 通用变量统一声明区域 */
const { createMessage } = useMessage();
/** https://v3.cn.vuejs.org/api/options-data.html#emits */
const emit = defineEmits(['success', 'register']);
const FormItem = Form.Item;
const useForm = Form.useForm;
const modelRef = reactive<WindowState>({
name: ''
});
const rulesRef = reactive<Recordable>({
reason: [
{
required: true,
whitespace: true,
message: '请输入文件名称!',
}
]
});
const { resetFields, clearValidate, validate, validateInfos } = useForm(modelRef, rulesRef);
const [registerModal, { setModalProps, closeModal }] = useModalInner( (data: BoxPayload) => {
//
resetFields();
clearValidate();
//
const props: Partial<ModalProps> = { confirmLoading: false };
switch (data._tag) {
case 'add':
props.title = '新增文件';
break;
case 'edit':
props.title = '编辑文件';
break;
}
setModalProps(props);
});
/** 处理模态框提交 */
async function handleSubmit() {
try {
await validate();
setModalProps({ confirmLoading: true });
emit('success', modelRef);
closeModal();
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>
Loading…
Cancel
Save