Commit 80b3be3e authored by rockyl's avatar rockyl

Merge branch 'code-diff' into publish

# Conflicts:
#	src/locales/zh-CN.json
#	src/store/modules/project.js
#	src/views/Editor.vue
parents e2224b7c 01406053
...@@ -24,11 +24,8 @@ class ApiError extends Error { ...@@ -24,11 +24,8 @@ class ApiError extends Error {
} }
} }
export async function fetchApi(uri, {params, method = 'get', auth = true, judgeSuccess = true, contentType = 'json', errMessage} = { export async function fetchApi(uri, {host = '', params, method = 'get', auth = true, judgeSuccess = true, contentType = 'json', dataField = 'data', errMessage}) {
method: 'get', let url = host + (uri.startsWith('http') || uri.startsWith('//') ? uri : API_HOST + uri);
contentType: 'json'
}) {
let url = uri.startsWith('http') || uri.startsWith('//') ? uri : API_HOST + uri;
const options = { const options = {
method, method,
......
...@@ -6,7 +6,7 @@ export let API_HOST; ...@@ -6,7 +6,7 @@ export let API_HOST;
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
//API_HOST = '//10.10.95.74:7777'; //API_HOST = '//10.10.95.74:7777';
//API_HOST = '//192.168.1.16:7777'; //API_HOST = '//192.168.1.16:7777';
API_HOST = '//10.10.35.210:3000'; API_HOST = '//10.10.94.107:3000';
//API_HOST = '//192.168.0.105:7777'; //API_HOST = '//192.168.0.105:7777';
//API_HOST = '//localhost:3002'; //API_HOST = '//localhost:3002';
//API_HOST = window.__data.apiHost; //API_HOST = window.__data.apiHost;
......
...@@ -227,10 +227,15 @@ ...@@ -227,10 +227,15 @@
"Store": "数据", "Store": "数据",
"Operate": "操作", "Operate": "操作",
"Computed": "计算属性", "Computed": "计算属性",
"Are you sure to close?": "确定关闭吗?", "Are you sure to close?": "确定关闭吗?",
"Failed to update operator": "更新权限列表失败", "Project conflict resolver": "项目冲突解决",
"Error delete self": "连自己都删? 不可以!", "Merge conflicts": "合并冲突",
"No permission": "没有权限喔!", "There are still unresolved conflicts": "还有冲突未解决,不能保存!",
"The format of the JSON document is wrong": "JSON文档格式有误,请先更正!",
"The conflict has been resolved": "冲突已解决,确定保存吗?",
"Failed to update operator": "更新权限列表失败",
"Error delete self": "连自己都删? 不可以!",
"No permission": "没有权限喔!",
"eventGroup": { "eventGroup": {
"in": "接收", "in": "接收",
"out": "派发" "out": "派发"
......
...@@ -23,5 +23,10 @@ export default new Router({ ...@@ -23,5 +23,10 @@ export default new Router({
name: 'preview', name: 'preview',
component: () => import('./views/Preview.vue') component: () => import('./views/Preview.vue')
}, },
{
path: '/diff',
name: 'diff',
component: () => import('./views/ProjectDiff.vue')
},
] ]
}) })
...@@ -7,7 +7,15 @@ import {editorApi, projectApi} from "../../api" ...@@ -7,7 +7,15 @@ import {editorApi, projectApi} from "../../api"
import path from "path" import path from "path"
import generateUUID from "uuid/v4" import generateUUID from "uuid/v4"
import {flattenViews, getCmpByUUID, getCmpProps} from '../../utils/common' import {flattenViews, getCmpByUUID, getCmpProps} from '../../utils/common'
import {assetScheme, clonePureObj, findProcess, getMockServeEnabled, saveAs, traverseViewNode} from "../../utils" import {
assetScheme,
clonePureObj, deleteAssetsDepConfig,
deleteDesignConfig,
findProcess,
getMockServeEnabled,
saveAs,
traverseViewNode
} from "../../utils"
import {template} from "../../template" import {template} from "../../template"
import events from "@/global-events" import events from "@/global-events"
import {packImages} from "../../utils/sheet-pack" import {packImages} from "../../utils/sheet-pack"
...@@ -20,7 +28,6 @@ import {fetchApi} from "../../api/common" ...@@ -20,7 +28,6 @@ import {fetchApi} from "../../api/common"
import {toZeroing} from "psd-parse-web" import {toZeroing} from "psd-parse-web"
import {arrayFind} from "element-ui/src/utils/util"; import {arrayFind} from "element-ui/src/utils/util";
const storeName = 'project'; const storeName = 'project';
const psStoreName = 'pack-history'; const psStoreName = 'pack-history';
...@@ -47,47 +54,6 @@ const defaultOptions = { ...@@ -47,47 +54,6 @@ const defaultOptions = {
const OPERATE_MAX_LENGTH = 200; // 撤销重做栈最大值 const OPERATE_MAX_LENGTH = 200; // 撤销重做栈最大值
function getDefaultOptions() {
return clonePureObj(defaultOptions)
}
function setUUIDForAllChildren(node) {
if (node.children && node.children.length > 0) {
for (let i = 0; i < node.children.length; i++) {
node.children[i] = copyBaseRoot(node.children[i]);
setUUIDForAllChildren(node.children[i])
}
}
}
let copyNodeCatch = null;
function copyBaseRoot(node) {
let _node = JSON.parse(JSON.stringify(node));
let data;
if (_node.children && _node.children.length > 0) {
data = {
name: _node.name,
type: _node.type,
properties: _node.properties,
events: _node.events,
uuid: generateUUID(),
children: _node.children
};
} else {
data = {
name: _node.name,
type: _node.type,
properties: _node.properties,
events: _node.events,
uuid: generateUUID(),
};
}
return data
}
export const projectStore = { export const projectStore = {
modules: { modules: {
package: packageStore, package: packageStore,
...@@ -98,6 +64,7 @@ export const projectStore = { ...@@ -98,6 +64,7 @@ export const projectStore = {
creator: '', creator: '',
operator: '', operator: '',
operators: '', operators: '',
update_time: '',
data: { data: {
options: {}, options: {},
views: [], views: [],
...@@ -124,14 +91,18 @@ export const projectStore = { ...@@ -124,14 +91,18 @@ export const projectStore = {
}, },
makeProjectDirty() { makeProjectDirty() {
},
updateProjectUpdateTime(state, updateTime) {
state.update_time = updateTime;
}, },
updateProject(state, project) { updateProject(state, project) {
const {id, name, creator, data, operators, operator} = project; const {id, name, creator, data, operators, operator, update_time} = project;
state.id = id; state.id = id;
state.name = name; state.name = name;
state.creator = creator; state.creator = creator;
state.operators = operators; state.operators = operators;
state.operator = operator; state.operator = operator;
state.update_time = update_time;
const localData = state.data; const localData = state.data;
if (data) { if (data) {
...@@ -385,15 +356,14 @@ export const projectStore = { ...@@ -385,15 +356,14 @@ export const projectStore = {
parentChildren.splice(index, 1); parentChildren.splice(index, 1);
}, },
copyNode(state, {node, parentNode, copyState}) {
copyNode(state, {node, parentNode,copyState}) {
let _node1 = node; let _node1 = node;
console.log(_node1) console.log(_node1)
copyNodeCatch =clonePureObj(_node1) copyNodeCatch = clonePureObj(_node1)
if(copyState==1){ if (copyState == 1) {
//复制行为 //复制行为
copyNodeCatch.events copyNodeCatch.events
}else if(copyState==2){ } else if (copyState == 2) {
//不复制行为 //不复制行为
delete copyNodeCatch.events delete copyNodeCatch.events
} }
...@@ -490,27 +460,30 @@ export const projectStore = { ...@@ -490,27 +460,30 @@ export const projectStore = {
state.mockServeEnabled = enabled; state.mockServeEnabled = enabled;
}, },
modifyViewStore(state, {view, store}){ modifyViewStore(state, {view, store}) {
view.store = store; view.store = store;
this.commit('makeProjectDirty'); this.commit('makeProjectDirty');
}, },
addCmd(state, cmd){ addCmd(state, cmd) {
Vue.set(state.activeComponent.properties, cmd, ''); Vue.set(state.activeComponent.properties, cmd, '');
this.commit('makeProjectDirty'); this.commit('makeProjectDirty');
}, },
deleteCmd(state, cmd){ deleteCmd(state, cmd) {
Vue.delete(state.activeComponent.properties, cmd); Vue.delete(state.activeComponent.properties, cmd);
this.commit('makeProjectDirty'); this.commit('makeProjectDirty');
}, },
}, },
getters: { getters: {
project(state) { project(state) {
const {id, name, creator, data} = state; const {id, name, creator, data, update_time} = state;
let newData = clonePureObj(data);
deleteDesignConfig(newData.processes);
deleteAssetsDepConfig(newData);
return { return {
id, name, creator, id, name, creator, update_time,
data: JSON.stringify(data), data: JSON.stringify(newData),
}; };
}, },
menuBadge: (state) => (key) => { menuBadge: (state) => (key) => {
...@@ -600,7 +573,7 @@ export const projectStore = { ...@@ -600,7 +573,7 @@ export const projectStore = {
let index = entries.indexOf(behavior.meta); let index = entries.indexOf(behavior.meta);
if (index >= 0) { if (index >= 0) {
let path = paths.splice(index, 1, null)[0]; let path = paths.splice(index, 1, null)[0];
if(!path){ if (!path) {
continue; continue;
} }
path[0] = { path[0] = {
...@@ -628,7 +601,7 @@ export const projectStore = { ...@@ -628,7 +601,7 @@ export const projectStore = {
}, },
actions: { actions: {
async saveToLocal({getters, commit}) { async saveToLocal({getters, commit}) {
const {project} = getters; const project = getters.project;
await db.set(storeName, {id: project.id, data: JSON.stringify(project)}); await db.set(storeName, {id: project.id, data: JSON.stringify(project)});
//localStorage.setItem('project-' + project.id, JSON.stringify(project)); //localStorage.setItem('project-' + project.id, JSON.stringify(project));
...@@ -675,9 +648,19 @@ export const projectStore = { ...@@ -675,9 +648,19 @@ export const projectStore = {
throw new Error('Project does not exist') throw new Error('Project does not exist')
} }
}, },
async saveToRemote({state, dispatch, getters}, {remark}) { async saveToRemote({state, dispatch, getters, commit}, {remark, data}) {
await projectApi.saveOne(getters.project, remark); let project = Object.assign({}, getters.project);
dispatch('deleteLocalVersion', state.id); if (data) {
project.data = data;
project.force = true;
}
let resp = await projectApi.saveOne(project, remark);
if (resp.result) {
commit('updateProjectUpdateTime', resp.project.update_time);
dispatch('deleteLocalVersion', state.id);
}
resp.localData = project.data;
return resp;
}, },
async updateProject({commit}, projectID) { async updateProject({commit}, projectID) {
const project = await projectApi.getData(projectID); const project = await projectApi.getData(projectID);
...@@ -707,10 +690,10 @@ export const projectStore = { ...@@ -707,10 +690,10 @@ export const projectStore = {
} }
} }
if(_view.data === data.data){ if (_view.data === data.data) {
if(!data.data.hasOwnProperty('$isRootView')){ if (!data.data.hasOwnProperty('$isRootView')) {
Object.defineProperty(data.data, '$isRootView', { Object.defineProperty(data.data, '$isRootView', {
get(){ get() {
return true; return true;
} }
}) })
...@@ -844,7 +827,7 @@ export const projectStore = { ...@@ -844,7 +827,7 @@ export const projectStore = {
let debug = params.debug; let debug = params.debug;
let packedAssets; let packedAssets;
//if (!debug) { //if (!debug) {
packedAssets = await packAssets(state.data.assets); packedAssets = await packAssets(state.data.assets);
//} //}
const packResult = await projectApi.pack(state.id, debug, packedAssets); const packResult = await projectApi.pack(state.id, debug, packedAssets);
...@@ -867,7 +850,7 @@ export const projectStore = { ...@@ -867,7 +850,7 @@ export const projectStore = {
await db.remove(psStoreName, id); await db.remove(psStoreName, id);
}, },
savePreview({state, rootState, getters}) { savePreview({state, rootState, getters}) {
const {project} = getters; const project = getters.project;
const packages = state.package.packages; const packages = state.package.packages;
/*const data = { /*const data = {
...@@ -877,7 +860,7 @@ export const projectStore = { ...@@ -877,7 +860,7 @@ export const projectStore = {
localStorage.setItem('preview-project-' + project.id, JSON.stringify(data)); localStorage.setItem('preview-project-' + project.id, JSON.stringify(data));
localStorage.setItem('preview-ts', Date.now().toString());*/ localStorage.setItem('preview-ts', Date.now().toString());*/
preprocess(project, state.data, clonePureObj(packages)); preprocess(project, clonePureObj(packages));
}, },
addBehaviorDirect({state}, {behaviors, alias}) { addBehaviorDirect({state}, {behaviors, alias}) {
...@@ -967,3 +950,45 @@ export async function updateMock(mocks) { ...@@ -967,3 +950,45 @@ export async function updateMock(mocks) {
db.set('mock', mock); db.set('mock', mock);
} }
} }
function getDefaultOptions() {
return clonePureObj(defaultOptions)
}
function setUUIDForAllChildren(node) {
if (node.children && node.children.length > 0) {
for (let i = 0; i < node.children.length; i++) {
node.children[i] = copyBaseRoot(node.children[i]);
setUUIDForAllChildren(node.children[i])
}
}
}
let copyNodeCatch = null;
function copyBaseRoot(node) {
let _node = JSON.parse(JSON.stringify(node));
let data;
if (_node.children && _node.children.length > 0) {
data = {
name: _node.name,
type: _node.type,
properties: _node.properties,
events: _node.events,
uuid: generateUUID(),
children: _node.children
};
} else {
data = {
name: _node.name,
type: _node.type,
properties: _node.properties,
events: _node.events,
uuid: generateUUID(),
};
}
return data
}
...@@ -219,11 +219,13 @@ ...@@ -219,11 +219,13 @@
.tpl-editor { .tpl-editor {
flex: 1; flex: 1;
height: 0;
.el-form-item__content { .el-form-item__content {
height: 100%; height: 100%;
.editor { .editor {
width: 100%;
height: 100%; height: 100%;
} }
} }
...@@ -269,6 +271,7 @@ ...@@ -269,6 +271,7 @@
} }
.editor { .editor {
width: 100%;
height: 300px; height: 300px;
} }
} }
...@@ -322,11 +325,13 @@ ...@@ -322,11 +325,13 @@
.editor-form-item { .editor-form-item {
flex: 1; flex: 1;
height: 0;
.el-form-item__content { .el-form-item__content {
height: 100%; height: 100%;
.editor { .editor {
width: 100%;
height: 100%; height: 100%;
} }
} }
...@@ -359,11 +364,13 @@ ...@@ -359,11 +364,13 @@
} }
.editor { .editor {
width: 100%;
height: 100%; height: 100%;
} }
.computed-editor{ .computed-editor{
.editor{ .editor{
width: 100%;
height: 200px; height: 200px;
} }
} }
...@@ -519,3 +526,21 @@ ...@@ -519,3 +526,21 @@
.pack-failed-details{ .pack-failed-details{
width: 80vw !important; width: 80vw !important;
} }
.project-conflict-resolve-editor{
.wrapper{
height: 100%;
padding: 10px;
flex: 1;
display: flex;
flex-direction: column;
.container {
flex: 1;
.editor{
height: 100%;
}
}
}
}
...@@ -33,10 +33,10 @@ const attrShortMapper = { ...@@ -33,10 +33,10 @@ const attrShortMapper = {
size: 'font-size', size: 'font-size',
font: 'font-family', font: 'font-family',
alpha: 'opacity', alpha: 'opacity',
'strokeColor': 'border-color', strokeColor: 'border-color',
'strokeWidth': 'border-width', strokeWidth: 'border-width',
'fillColor': 'background-color', fillColor: 'background-color',
'source': 'background-image' source: 'background-image'
}; };
// 编辑时想拖拽组件需要生成的css属性 // 编辑时想拖拽组件需要生成的css属性
...@@ -277,6 +277,8 @@ export const styles = { ...@@ -277,6 +277,8 @@ export const styles = {
// 如果是label类型,把fillColor转换为color // 如果是label类型,把fillColor转换为color
cmpSelfProps.color = cmpSelfProps.fillColor; cmpSelfProps.color = cmpSelfProps.fillColor;
delete cmpSelfProps.fillColor; delete cmpSelfProps.fillColor;
delete cmpSelfProps.stroke;
delete cmpSelfProps.strokeColor;
if (cmpSelfProps.italic) { //斜体 if (cmpSelfProps.italic) { //斜体
delete cmpSelfProps.italic; delete cmpSelfProps.italic;
cmpSelfProps.fontStyle = 'italic'; cmpSelfProps.fontStyle = 'italic';
......
...@@ -34,7 +34,8 @@ export const pxHostMapping = { ...@@ -34,7 +34,8 @@ export const pxHostMapping = {
export const monacoEditorOptions = { export const monacoEditorOptions = {
tabSize: 2, tabSize: 2,
insertSpaces: false insertSpaces: false,
automaticLayout: true,
}; };
export const cmdPrefix = 'z-'; export const cmdPrefix = 'z-';
...@@ -93,6 +94,9 @@ export function guid() { ...@@ -93,6 +94,9 @@ export function guid() {
* @param parent * @param parent
*/ */
export function traverseViewNode(nodes, callback, parent) { export function traverseViewNode(nodes, callback, parent) {
if (!nodes) {
return;
}
for (let node of nodes) { for (let node of nodes) {
callback(node, parent); callback(node, parent);
if (node.children && node.children.length > 0) { if (node.children && node.children.length > 0) {
...@@ -400,3 +404,28 @@ export function getViewNodePath(node, sep = '/') { ...@@ -400,3 +404,28 @@ export function getViewNodePath(node, sep = '/') {
export function timeFormat(time, format = 'YYYY-MM-DD HH:mm:ss') { export function timeFormat(time, format = 'YYYY-MM-DD HH:mm:ss') {
return moment(time).format(format) return moment(time).format(format)
} }
export function deleteDesignConfig(processes) {
for (let process of processes) {
if (process.sub) {
for (let key in process.sub) {
let p = process.sub[key];
delete p.design['input'];
delete p.design['output'];
}
}
if (process.metas) {
deleteDesignConfig(process.metas);
}
}
}
export function deleteAssetsDepConfig(data) {
for (let asset of data.assets) {
delete asset['dep'];
}
}
export function formatJson(source){
return JSON.stringify(JSON.parse(source), null, '\t')
}
...@@ -131,6 +131,16 @@ export default { ...@@ -131,6 +131,16 @@ export default {
type: 'color', type: 'color',
default: '#000' default: '#000'
}, },
stroke: {
alias: '描边宽度',
type: 'number',
default: 0,
},
strokeColor: {
alias: '描边颜色',
type: 'color',
default: '#ffffff'
},
lineType: { lineType: {
alias: '自动换行', alias: '自动换行',
type: 'enum', type: 'enum',
...@@ -299,7 +309,7 @@ export default { ...@@ -299,7 +309,7 @@ export default {
alias: '边框宽度', alias: '边框宽度',
type: 'number', type: 'number',
default: 0, default: 0,
} },
} }
}, },
rect: { rect: {
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
<px-skin-editor-dialog ref="pxSkinEditorDialog"/> <px-skin-editor-dialog ref="pxSkinEditorDialog"/>
<process-search-dialog ref="processSearchDialog"/> <process-search-dialog ref="processSearchDialog"/>
<behavior-editor-dialog @change="handleBehaviorsChange" ref="behaviorEditorDialog"></behavior-editor-dialog> <behavior-editor-dialog @change="handleBehaviorsChange" ref="behaviorEditorDialog"></behavior-editor-dialog>
<project-conflict-resolve-dialog ref="projectConflictResolveDialog" @resolved="onConflictResolved"/>
</div> </div>
</template> </template>
...@@ -45,10 +46,12 @@ ...@@ -45,10 +46,12 @@
import PxSkinEditorDialog from "./Editor/dialogs/PxSkinEditorDialog"; import PxSkinEditorDialog from "./Editor/dialogs/PxSkinEditorDialog";
import BehaviorEditorDialog from "./Editor/dialogs/BehaviorEditorDialog"; import BehaviorEditorDialog from "./Editor/dialogs/BehaviorEditorDialog";
import ProcessSearchDialog from "./Editor/dialogs/ProcessSearchDialog"; import ProcessSearchDialog from "./Editor/dialogs/ProcessSearchDialog";
import ProjectConflictResolveDialog from "./Editor/dialogs/ProjectConflictResolveDialog";
export default { export default {
name: 'Editor', name: 'Editor',
components: { components: {
ProjectConflictResolveDialog,
ProcessSearchDialog, ProcessSearchDialog,
BehaviorEditorDialog, BehaviorEditorDialog,
PxSkinEditorDialog, PxSkinEditorDialog,
...@@ -192,7 +195,7 @@ ...@@ -192,7 +195,7 @@
this.panesConfig[id] = configs[0].width / 100; this.panesConfig[id] = configs[0].width / 100;
localStorage.panesConfig = JSON.stringify(this.panesConfig); localStorage.panesConfig = JSON.stringify(this.panesConfig);
}, },
async saveProject(closeLoading) { async saveProject(closeLoading, data) {
let remark, cancel; let remark, cancel;
await this.$prompt(this.$t('Input version remark'), this.$t('Alert'), { await this.$prompt(this.$t('Input version remark'), this.$t('Alert'), {
confirmButtonText: this.$t('Confirm'), confirmButtonText: this.$t('Confirm'),
...@@ -206,26 +209,40 @@ ...@@ -206,26 +209,40 @@
cancel = true; cancel = true;
}); });
if (!cancel) { if (!cancel) {
await playWaiting(this.saveToRemote({remark}), this.$t('Saving'), closeLoading); let resp = await playWaiting(this.saveToRemote({remark, data}), this.$t('Saving'), closeLoading);
this.$message({ if (resp.result) {
message: i18n.t('Save project successfully'), //因为message是异步出现,但是当路由回退的时候,this.i18n的实例已经置空,所以要用全局的i18n实例 this.$message({
type: 'success' message: i18n.t('Save project successfully'), //因为message是异步出现,但是当路由回退的时候,this.i18n的实例已经置空,所以要用全局的i18n实例
}); type: 'success'
});
} else {
await this.$confirm(i18n.t('There are conflicts in the project'), i18n.t('Alert'), {
confirmButtonText: i18n.t('Confirm'),
cancelButtonText: i18n.t('Cancel'),
type: 'warning'
}).then(() => {
this.$refs.projectConflictResolveDialog.show(resp.remoteData, resp.localData);
}).catch((e) => {
});
}
} }
return cancel; return cancel;
}, },
checkAuth() { async onConflictResolved(data) {
let checkStatus = this.operators.includes(this.currentOperator); this.saveProject(true, data);
if(!checkStatus) { },
this.$message({ checkAuth() {
let checkStatus = this.operators.includes(this.currentOperator);
if(!checkStatus) {
this.$message({
message: this.$t('No permission'), message: this.$t('No permission'),
type: 'error', type: 'error',
duration: 1000, duration: 1000,
}); });
} }
return checkStatus; return checkStatus;
}, },
async clickMenu(menuItem) { async clickMenu(menuItem) {
switch (menuItem) { switch (menuItem) {
case 'save': case 'save':
...@@ -319,7 +336,7 @@ ...@@ -319,7 +336,7 @@
type: 'error', type: 'error',
duration: 1000, duration: 1000,
}); });
if(e.details){ if (e.details) {
let details = e.details.split('\n').join('\n'); let details = e.details.split('\n').join('\n');
this.$alert(`<p>Compile error</p><pre style="color:red;">${details}</pre>`, this.$t('Alert'), { this.$alert(`<p>Compile error</p><pre style="color:red;">${details}</pre>`, this.$t('Alert'), {
dangerouslyUseHTMLString: true, dangerouslyUseHTMLString: true,
......
<template>
<el-dialog :title="$t('Project conflict resolver')" width="70%" :visible.sync="visible" @opened="onOpen"
:close-on-click-modal="false"
:append-to-body="true"
fullscreen
custom-class="flex-dialog project-conflict-resolve-editor"
>
<div class="wrapper">
<el-steps :active="step" finish-status="success" align-center>
<el-step title="查看冲突"></el-step>
<el-step title="手动合并"></el-step>
<el-step title="完成"></el-step>
</el-steps>
<div class="container">
<monaco-editor
ref="editor"
class="editor"
v-model="localData"
language="json"
:options="monacoEditorOptions"
diff-editor
:original="remoteData"
/>
</div>
</div>
<div slot="footer" class="dialog-footer">
<div>
<el-button size="mini" @click="mergeConflicts" type="success" v-show="step===0">{{$t('Merge conflicts')}}
</el-button>
</div>
<div>
<el-button size="mini" @click="onClose">{{$t('Close')}}</el-button>
<el-button size="mini" @click="onSave" type="primary" :disabled="step===0">{{$t('Save')}}</el-button>
</div>
</div>
</el-dialog>
</template>
<script>
import {mapMutations} from 'vuex';
import MonacoEditor from "vue-monaco";
import {formatJson, monacoEditorOptions} from "../../../utils";
import SplitPanes from 'splitpanes'
const conflictFlags = ['<<<<<<< REMOTE', '=======', '>>>>>>> LOCAL'];
export default {
name: "ProjectConflictResolveDialog",
components: {MonacoEditor, SplitPanes},
data() {
let monacoEditorOptionsSelf = Object.assign({
readOnly: true,
}, monacoEditorOptions);
return {
monacoEditorOptions: monacoEditorOptionsSelf,
visible: false,
step: 0,
remoteData: '',
localData: '',
}
},
mounted() {
},
methods: {
show(remoteData, localData) {
this.remoteData = '';
this.localData = '';
this.$nextTick(() => {
this.remoteData = this.formatJson(remoteData);
this.localData = this.formatJson(localData);
this.step = 0;
this.visible = true;
this.monacoEditorOptions.readOnly = true;
this.diff = null;
this.$nextTick(() => {
if (!this.inited) {
this.inited = true;
let modifiedEditor = this.$refs.editor.getModifiedEditor();
let editor = this.$refs.editor.getEditor();
editor.onDidUpdateDiff(() => {
if (!this.diff) {
this.diff = editor.getLineChanges();
}
});
modifiedEditor.onDidChangeModelDecorations(() => {
});
}
});
});
},
async onSave() {
let resolved = true;
for (let conflictFlag of conflictFlags) {
if (this.localData.includes(conflictFlag)) {
resolved = false;
break;
}
}
if (resolved) {
try {
JSON.parse(this.localData);
await this.$confirm(this.$t('The conflict has been resolved'), this.$t('Alert'), {
confirmButtonText: this.$t('Confirm'),
cancelButtonText: this.$t('Cancel'),
type: 'warning'
}).then(() => {
this.visible = false;
this.$emit('resolved', this.localData);
}).catch((e) => {
});
} catch (e) {
this.$alert(this.$t('The format of the JSON document is wrong'), {
type: 'warning'
});
}
} else {
this.$alert(this.$t('There are still unresolved conflicts'), {
type: 'warning'
});
}
},
onClose() {
this.visible = false;
},
onOpen() {
},
...mapMutations([
'modifyProjectDetails',
]),
formatJson(source) {
return formatJson(source);
},
mergeConflicts() {
this.monacoEditorOptions.readOnly = false;
this.step++;
let remoteCodeLines = this.remoteData.split('\n');
let localCodeLines = this.localData.split('\n');
let mergedCodeLines = localCodeLines.concat();
//console.log(this.diff);
let offset = 0;
for (let {modifiedStartLineNumber, modifiedEndLineNumber, originalStartLineNumber, originalEndLineNumber} of this.diff) {
let remotePart = [];
for (let i = originalStartLineNumber, li = originalEndLineNumber; i <= li; i++) {
remotePart.push(remoteCodeLines[i - 1]);
}
let localPart = [];
for (let i = modifiedStartLineNumber, li = modifiedEndLineNumber; i <= li; i++) {
localPart.push(localCodeLines[i - 1]);
}
let merged = [];
merged.push(conflictFlags[0]);
merged.push(...remotePart);
merged.push(conflictFlags[1]);
merged.push(...localPart);
merged.push(conflictFlags[2]);
//console.log(merged);
mergedCodeLines.splice(modifiedStartLineNumber - 1 + offset, modifiedEndLineNumber - modifiedStartLineNumber + 1, ...merged);
offset += 3 + remotePart.length;
}
this.localData = mergedCodeLines.join('\n');
},
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
...@@ -24,9 +24,9 @@ function getPackages(packages) { ...@@ -24,9 +24,9 @@ function getPackages(packages) {
} }
} }
export async function preprocess(project, data, packages) { export async function preprocess(project, packages) {
let newData = clonePureObj(data); let data = JSON.parse(project.data);
const codes = await divideCode(newData, { const codes = await divideCode(data, {
debug: true, debug: true,
getPackages: getPackages(packages), getPackages: getPackages(packages),
dependencies: data.dependencies, dependencies: data.dependencies,
...@@ -50,7 +50,7 @@ export async function preprocess(project, data, packages) { ...@@ -50,7 +50,7 @@ export async function preprocess(project, data, packages) {
scripts.push(newScriptContent('var proxy_mode=true;')); scripts.push(newScriptContent('var proxy_mode=true;'));
codesCache = codes; codesCache = codes;
const dataUrl = URL.createObjectURL(new Blob([JSON.stringify(newData)])); const dataUrl = URL.createObjectURL(new Blob([JSON.stringify(data)]));
const {libraryScriptElMap, analyseResult} = await generateLibraryScriptEl(tpl, dependencies, getPackages(packages), '//yun.duiba.com.cn/editor/zeroing/libs/'); const {libraryScriptElMap, analyseResult} = await generateLibraryScriptEl(tpl, dependencies, getPackages(packages), '//yun.duiba.com.cn/editor/zeroing/libs/');
...@@ -65,7 +65,7 @@ export async function preprocess(project, data, packages) { ...@@ -65,7 +65,7 @@ export async function preprocess(project, data, packages) {
db.set(storeName, { db.set(storeName, {
id: project.id, id: project.id,
data: newData, data,
tpl, tpl,
}); });
localStorage.setItem('preview-ts', Date.now().toString()); localStorage.setItem('preview-ts', Date.now().toString());
......
<template>
<monaco-editor
class="script-editor"
ref="editor"
v-model="code"
language="json"
:options="monacoEditorOptions"
diff-editor
:original="originalCode"
/>
</template>
<script>
import MonacoEditor from "vue-monaco";
import {monacoEditorOptions} from "../utils";
//import old from './old.json'
//let originalCode = JSON.stringify(old, null, '\t');
let originalCode = `hello`;
console.log(originalCode);
export default {
name: "ProjectDiff",
components: {MonacoEditor},
data() {
return {
monacoEditorOptions,
code: '',
originalCode,
}
},
mounted() {
let editor = this.$refs.editor.getEditor();
editor.onDidUpdateDiff(()=>{
let m = editor.getLineChanges();
console.log(m);
})
}
}
</script>
<style scoped>
.script-editor{
width: 100%;
}
</style>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment