|
|
@@ -3,10 +3,77 @@
|
|
|
<div class="miniprogram-editor">
|
|
|
<div class="editor-toolbar">
|
|
|
<a-space>
|
|
|
- <a-button type="primary" @click="loadEditorJson">加载</a-button>
|
|
|
- <a-button @click="saveEditorJson">保存</a-button>
|
|
|
+ <a-dropdown>
|
|
|
+ <a-button>
|
|
|
+ 加载
|
|
|
+ <DownOutlined />
|
|
|
+ </a-button>
|
|
|
+ <template #overlay>
|
|
|
+ <a-menu v-if="historyList.length">
|
|
|
+ <a-menu-item @click="onSelectDefault">
|
|
|
+ 选择默认配置
|
|
|
+ <a-badge v-if="currentConfig?.activeHistoryId === 0" count="激活" />
|
|
|
+ </a-menu-item>
|
|
|
+ <a-menu-item
|
|
|
+ v-for="(item, index) in historyList"
|
|
|
+ :key="index"
|
|
|
+ @click="onSelectHistory(item.id!)"
|
|
|
+ >
|
|
|
+ {{ item.name }}
|
|
|
+ <a-badge v-if="item.id === currentConfig?.activeHistoryId" count="激活" />
|
|
|
+ </a-menu-item>
|
|
|
+ </a-menu>
|
|
|
+ <a-menu v-else>
|
|
|
+ <a-menu-item disabled>暂无历史版本</a-menu-item>
|
|
|
+ </a-menu>
|
|
|
+ </template>
|
|
|
+ </a-dropdown>
|
|
|
+ <a-dropdown-button type="primary" @click="saveEditorJson">
|
|
|
+ 保存
|
|
|
+ <template #overlay>
|
|
|
+ <a-menu>
|
|
|
+ <a-menu-item @click="openSaveAsModal">另存为历史版本</a-menu-item>
|
|
|
+ </a-menu>
|
|
|
+ </template>
|
|
|
+ </a-dropdown-button>
|
|
|
+
|
|
|
+ <div>
|
|
|
+ <InfoCircleFilled />
|
|
|
+ 当前显示配置:
|
|
|
+ <span>{{ currentShowConfigName }}</span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <a-button v-if="currentConfig" @click="setActiveHistory">
|
|
|
+ {{ currentConfig.activeHistoryId === currentHistoryId ? '已经是激活版本' : '设置为激活版本' }}
|
|
|
+ </a-button>
|
|
|
+ <a-button v-if="currentConfig && currentHistoryId !== 0" danger @click="deleteHistory">删除历史版本</a-button>
|
|
|
</a-space>
|
|
|
+ <a-button @click="exportToJsonFile">
|
|
|
+ 导出为JSON文件
|
|
|
+ <DownloadOutlined />
|
|
|
+ </a-button>
|
|
|
</div>
|
|
|
+
|
|
|
+ <!-- 另存为历史版本弹框 -->
|
|
|
+ <a-modal
|
|
|
+ v-model:open="saveAsModalVisible"
|
|
|
+ title="另存为历史版本"
|
|
|
+ ok-text="保存"
|
|
|
+ cancel-text="取消"
|
|
|
+ :confirm-loading="saveAsLoading"
|
|
|
+ @ok="confirmSaveAs"
|
|
|
+ >
|
|
|
+ <a-form layout="vertical" class="save-as-form">
|
|
|
+ <a-form-item label="版本名称">
|
|
|
+ <a-input
|
|
|
+ v-model:value="saveAsVersionName"
|
|
|
+ placeholder="请输入版本名称"
|
|
|
+ allow-clear
|
|
|
+ />
|
|
|
+ </a-form-item>
|
|
|
+ </a-form>
|
|
|
+ </a-modal>
|
|
|
+
|
|
|
<div class="editor-body">
|
|
|
<!-- 左一:页面列表 -->
|
|
|
<div class="panel panel-pages">
|
|
|
@@ -56,29 +123,178 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { computed, provide, ref } from 'vue';
|
|
|
+import { computed, onMounted, provide, ref } from 'vue';
|
|
|
import { ObjectUtils } from '@imengyu/imengyu-utils';
|
|
|
-import type { IHomeCommonCategoryDefine } from '../article/data/CommonCategoryDefine';
|
|
|
-import DefaultEditorJson from '../article/data/DefaultCategory.json';
|
|
|
+import { DownOutlined, DownloadOutlined, InfoCircleFilled } from '@ant-design/icons-vue';
|
|
|
+import { message, Modal } from 'ant-design-vue';
|
|
|
+import type { IHomeCommonCategoryDefine } from '../CommonCategoryDefine';
|
|
|
+import DefaultEditorJson from '../DefaultCategory.json';
|
|
|
import PropsEditorTree from './subpart/PropsEditorTree.vue';
|
|
|
import EditorPreview from './subpart/EditorPreview.vue';
|
|
|
import zhCN from 'ant-design-vue/es/locale/zh_CN';
|
|
|
+import CommonCategoryApi, { type ICommonCategoryConfigItem } from '../api/CommonCategoryApi';
|
|
|
+
|
|
|
+/** 历史版本列表项(接口返回的 items 元素) */
|
|
|
+interface IHistoryListItem {
|
|
|
+ id?: number;
|
|
|
+ data?: IHomeCommonCategoryDefine;
|
|
|
+ createTime?: string;
|
|
|
+ [key: string]: any;
|
|
|
+}
|
|
|
|
|
|
const currentEditorJson = ref<IHomeCommonCategoryDefine>(DefaultEditorJson as IHomeCommonCategoryDefine);
|
|
|
const selectedPage = ref<(IHomeCommonCategoryDefine['page'][0]) | null>(null);
|
|
|
const pageList = computed(() => currentEditorJson.value.page || []);
|
|
|
+const historyList = ref<IHistoryListItem[]>([]);
|
|
|
+const currentConfig = ref<ICommonCategoryConfigItem>();
|
|
|
+const currentHistoryId = ref<number>(0);
|
|
|
+const currentShowConfigName = computed(() => {
|
|
|
+ if (currentHistoryId.value === 0)
|
|
|
+ return '默认配置';
|
|
|
+ else
|
|
|
+ return historyList.value.find(item => item.id === currentHistoryId.value)?.name ?? '未知';
|
|
|
+});
|
|
|
+
|
|
|
+const saveAsModalVisible = ref(false);
|
|
|
+const saveAsVersionName = ref('');
|
|
|
+const saveAsLoading = ref(false);
|
|
|
|
|
|
provide('pageList', pageList);
|
|
|
|
|
|
-async function loadEditorJson() {
|
|
|
- // 临时使用本地文件,后续接入后端接口
|
|
|
- currentEditorJson.value = ObjectUtils.clone(DefaultEditorJson) as IHomeCommonCategoryDefine;
|
|
|
+async function loadEditorJson(selectDefault = false) {
|
|
|
+ try {
|
|
|
+ //加载基础配置
|
|
|
+ currentConfig.value = await CommonCategoryApi.getConfigWithoutCache();
|
|
|
+ if (!currentConfig.value)
|
|
|
+ throw new Error('加载基础配置失败');
|
|
|
+ if (selectDefault)
|
|
|
+ currentHistoryId.value = currentConfig.value.activeHistoryId;
|
|
|
+ //根据activeHistoryId选择当前激活的历史版本
|
|
|
+ if (currentHistoryId.value > 0) {
|
|
|
+ const activeHistory = historyList.value.find(item => item.id === currentHistoryId.value);
|
|
|
+ if (activeHistory)
|
|
|
+ currentEditorJson.value = ObjectUtils.clone(activeHistory.data!) as IHomeCommonCategoryDefine;
|
|
|
+ else
|
|
|
+ throw new Error('当前激活的历史版本不存在');
|
|
|
+ } else {
|
|
|
+ currentEditorJson.value = ObjectUtils.clone(currentConfig.value.data) as IHomeCommonCategoryDefine;
|
|
|
+ }
|
|
|
+ message.success('加载分类成功');
|
|
|
+ } catch (error) {
|
|
|
+ Modal.error({
|
|
|
+ title: '加载分类失败',
|
|
|
+ content: '' + error,
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
+async function loadEditorJsonHistorys() {
|
|
|
+ try {
|
|
|
+ const res = await CommonCategoryApi.getConfigHistoryList(1, 10);
|
|
|
+ const items = res?.items ?? [];
|
|
|
+ historyList.value = Array.isArray(items) ? items : [];
|
|
|
+ } catch (error) {
|
|
|
+ historyList.value = [];
|
|
|
+ Modal.error({
|
|
|
+ title: '加载历史版本列表失败',
|
|
|
+ content: '' + error,
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+function onSelectDefault() {
|
|
|
+ currentHistoryId.value = 0;
|
|
|
+ loadEditorJson(true);
|
|
|
+}
|
|
|
+function onSelectHistory(id: number) {
|
|
|
+ currentHistoryId.value = id;
|
|
|
+ loadEditorJson(false);
|
|
|
+}
|
|
|
+
|
|
|
+/** 默认保存:根据 currentHistoryId 保存到默认配置或指定历史版本 */
|
|
|
async function saveEditorJson() {
|
|
|
- // 临时测试,后续接入后端接口
|
|
|
- console.log(currentEditorJson.value);
|
|
|
+ try {
|
|
|
+ const saveToHistoryId = currentHistoryId.value === 0 ? undefined : currentHistoryId.value;
|
|
|
+ await CommonCategoryApi.editConfig(
|
|
|
+ currentEditorJson.value,
|
|
|
+ undefined,
|
|
|
+ saveToHistoryId
|
|
|
+ );
|
|
|
+ message.success('保存成功');
|
|
|
+ } catch (error) {
|
|
|
+ Modal.error({
|
|
|
+ title: '保存失败',
|
|
|
+ content: '' + error,
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function openSaveAsModal() {
|
|
|
+ saveAsVersionName.value = '';
|
|
|
+ saveAsModalVisible.value = true;
|
|
|
+}
|
|
|
+
|
|
|
+async function confirmSaveAs() {
|
|
|
+ const name = saveAsVersionName.value?.trim();
|
|
|
+ if (!name) {
|
|
|
+ message.warning('请输入版本名称');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ saveAsLoading.value = true;
|
|
|
+ try {
|
|
|
+ await CommonCategoryApi.editConfig(
|
|
|
+ currentEditorJson.value,
|
|
|
+ name,
|
|
|
+ 0
|
|
|
+ );
|
|
|
+ message.success('已另存为历史版本');
|
|
|
+ saveAsModalVisible.value = false;
|
|
|
+ await loadEditorJsonHistorys();
|
|
|
+ } catch (error) {
|
|
|
+ Modal.error({
|
|
|
+ title: '另存为失败',
|
|
|
+ content: '' + error,
|
|
|
+ });
|
|
|
+ } finally {
|
|
|
+ saveAsLoading.value = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function setActiveHistory() {
|
|
|
+ await CommonCategoryApi.setActiveConfigHistory(currentHistoryId.value);
|
|
|
+ message.success('设置为激活版本成功');
|
|
|
}
|
|
|
+async function deleteHistory() {
|
|
|
+ Modal.confirm({
|
|
|
+ title: '删除历史版本',
|
|
|
+ content: '确定要删除该历史版本吗?',
|
|
|
+ onOk: async () => {
|
|
|
+ await CommonCategoryApi.deleteConfigHistory(currentHistoryId.value);
|
|
|
+ message.success('删除历史版本成功');
|
|
|
+ await loadEditorJsonHistorys();
|
|
|
+ await loadEditorJson(true);
|
|
|
+ },
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function exportToJsonFile() {
|
|
|
+ const json = JSON.stringify(currentEditorJson.value);
|
|
|
+ const blob = new Blob([json], { type: 'application/json' });
|
|
|
+ const url = URL.createObjectURL(blob);
|
|
|
+ const a = document.createElement('a');
|
|
|
+ a.href = url;
|
|
|
+ a.download = 'editor.json';
|
|
|
+ a.click();
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(async () => {
|
|
|
+ await loadEditorJsonHistorys();
|
|
|
+ await loadEditorJson(true);
|
|
|
+ window.addEventListener('beforeunload', function(e) {
|
|
|
+ const message = '你还有未保存的内容,确定要离开吗?';
|
|
|
+ e.returnValue = message;
|
|
|
+ return message;
|
|
|
+ });
|
|
|
+})
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
@@ -92,6 +308,9 @@ async function saveEditorJson() {
|
|
|
padding: 8px 16px;
|
|
|
background: #fff;
|
|
|
border-bottom: 1px solid #eee;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
}
|
|
|
.editor-body {
|
|
|
flex: 1;
|