Commit 3c50201e authored by 任建锋's avatar 任建锋

合并publish

parents e7ec6f42 53b816a1
module.exports = { module.exports = {
region: 'oss-cn-hangzhou', region: 'oss-cn-hangzhou',
id: 'LTAIqO2wblIxQvwc', id: 'LTAI4Fw25WcfcGv7FvcHoiHK',
secret: '4brsaSRbRpjxw3oDIxJi6bNMcndIR6', secret: 'NZk1NtT9J5HFaAolNbtQdzTzLLvLYm',
bucket: 'duiba', bucket: 'duiba',
output: '/editor/zeroing/v1', output: '/editor/zeroing/v1',
exclude: /.js.map$/, exclude: /.js.map$/,
internal: true,
}; };
...@@ -33,10 +33,10 @@ export async function fetchApi(uri, {params, method = 'get', auth = true, judgeS ...@@ -33,10 +33,10 @@ export async function fetchApi(uri, {params, method = 'get', auth = true, judgeS
const options = { const options = {
method, method,
headers: {}, headers: {},
//credentials: 'include', credentials: 'include',
}; };
if (auth) { if (auth) {
options.headers.authorization = 'Bearer ' + window['zeroing_token']; //options.headers.authorization = 'Bearer ' + window['zeroing_token'];
} }
if (params) { if (params) {
if (method.toLowerCase() === 'post') { if (method.toLowerCase() === 'post') {
...@@ -69,12 +69,14 @@ export async function fetchApi(uri, {params, method = 'get', auth = true, judgeS ...@@ -69,12 +69,14 @@ export async function fetchApi(uri, {params, method = 'get', auth = true, judgeS
} }
const response = await fetch(url, options); const response = await fetch(url, options);
if (response.status === 401) { const respText = await response.text();
location.href = '/admin/permission';
if (response.status === 310) { //客户端重定向,用于跨域重定向
location.href = respText;
} }
const jsonObj = await response.json();
//console.log(jsonObj);
try {
let jsonObj = JSON.parse(respText);
if (judgeSuccess) { if (judgeSuccess) {
if (jsonObj.success) { if (jsonObj.success) {
return jsonObj.data; return jsonObj.data;
...@@ -83,5 +85,8 @@ export async function fetchApi(uri, {params, method = 'get', auth = true, judgeS ...@@ -83,5 +85,8 @@ export async function fetchApi(uri, {params, method = 'get', auth = true, judgeS
return jsonObj; return jsonObj;
} }
throw new ApiError('call api failed', jsonObj.code, errMessage, jsonObj.details); return Promise.reject(new ApiError('call api failed', jsonObj.code, errMessage, jsonObj.details));
}catch (e) {
return Promise.reject(e);
}
} }
...@@ -4,6 +4,15 @@ ...@@ -4,6 +4,15 @@
import {fetchApi} from "./common"; import {fetchApi} from "./common";
let devPersons;
export async function getDevPersons() {
if (!devPersons) {
devPersons = await fetchApi('/api/editor/devPersons');
}
return devPersons
}
export async function importView(file) { export async function importView(file) {
const response = await fetchApi('/api/parsePSD', { const response = await fetchApi('/api/parsePSD', {
params: { params: {
...@@ -12,8 +21,8 @@ export async function importView(file) { ...@@ -12,8 +21,8 @@ export async function importView(file) {
method: 'post', method: 'post',
contentType: 'form-data', contentType: 'form-data',
errMessage: 'Failed to import view', errMessage: 'Failed to import view',
}) });
response.__originFile = file response.__originFile = file;
return response return response
} }
...@@ -25,13 +34,13 @@ export async function uploadView(file) { ...@@ -25,13 +34,13 @@ export async function uploadView(file) {
method: 'post', method: 'post',
contentType: 'form-data', contentType: 'form-data',
errMessage: 'Failed to upload view', errMessage: 'Failed to upload view',
}) });
response.__originFile = file; response.__originFile = file;
return response return response
} }
export async function uploadFile(file, compress = false, uuid) { export async function uploadFile(file, compress = false, uuid) {
let params = { file } let params = {file};
if (compress) { if (compress) {
params.compress = true params.compress = true
} }
...@@ -43,7 +52,7 @@ export async function uploadFile(file, compress = false, uuid) { ...@@ -43,7 +52,7 @@ export async function uploadFile(file, compress = false, uuid) {
method: 'post', method: 'post',
contentType: 'form-data', contentType: 'form-data',
errMessage: 'Failed to upload file', errMessage: 'Failed to upload file',
}) });
response.__originFile = file response.__originFile = file;
return response return response
} }
...@@ -5,32 +5,15 @@ ...@@ -5,32 +5,15 @@
import {fetchApi} from "./common"; import {fetchApi} from "./common";
import {getCookie} from "./utils"; import {getCookie} from "./utils";
export async function saveSkins(params) { export async function saveSkin(params) {
return await fetchApi(`/polaris/autoSaveSkins`, { return await fetchApi(`/polaris/saveSkin`, {
params, params,
method: 'post' method: 'post'
}) })
} }
export async function getProjectSkins(projectId, env) { export async function getSkins(projectId, env) {
return await fetchApi(`/polaris/getProjectSkins?projectId=${projectId}&env=${env}`, { return await fetchApi(`/polaris/getSkins?projectId=${projectId}&env=${env}`)
method: 'post',
params: {
cookie: {
dev: getCookie('sso_ticket'),
test: localStorage.getItem('ticket'),
prod: localStorage.getItem('prod_ticket'),
}
}
})
}
export async function getTestEnvTicket() {
return await fetchApi(`/polaris/getTestEnvTicket`, { method: 'get' })
}
export async function getProdTicket() {
return await fetchApi(`/polaris/getProdTicket`, { method: 'get' })
} }
export async function sendDingTalk() { export async function sendDingTalk() {
......
...@@ -7,6 +7,14 @@ ...@@ -7,6 +7,14 @@
import { fetchApi } from "./common" import { fetchApi } from "./common"
import { getCookie } from './utils' import { getCookie } from './utils'
/**
* 获取项目列表
* @param keyword
* @param currentPage
* @param pageSize
* @param onlyMine
* @return {Promise<*|any>}
*/
export async function fetchAll(keyword, currentPage, pageSize, onlyMine) { export async function fetchAll(keyword, currentPage, pageSize, onlyMine) {
return await fetchApi('/api/project/query', { return await fetchApi('/api/project/query', {
params: {name: keyword, currentPage, pageSize, isAll: onlyMine ? 0 : 1 }, params: {name: keyword, currentPage, pageSize, isAll: onlyMine ? 0 : 1 },
...@@ -14,6 +22,11 @@ export async function fetchAll(keyword, currentPage, pageSize, onlyMine) { ...@@ -14,6 +22,11 @@ export async function fetchAll(keyword, currentPage, pageSize, onlyMine) {
}) })
} }
/**
* 创建一个项目
* @param project
* @return {Promise<*|any>}
*/
export async function createOne(project) { export async function createOne(project) {
return await fetchApi('/api/project/create', { return await fetchApi('/api/project/create', {
params: project, params: project,
...@@ -22,6 +35,11 @@ export async function createOne(project) { ...@@ -22,6 +35,11 @@ export async function createOne(project) {
}) })
} }
/**
* 复制一个项目
* @param project
* @return {Promise<*|any>}
*/
export async function duplicateOne(project) { export async function duplicateOne(project) {
return await fetchApi('/api/project/copy', { return await fetchApi('/api/project/copy', {
params: project, params: project,
...@@ -30,6 +48,11 @@ export async function duplicateOne(project) { ...@@ -30,6 +48,11 @@ export async function duplicateOne(project) {
}) })
} }
/**
* 删除一个项目
* @param id
* @return {Promise<*|any>}
*/
export async function deleteOne(id) { export async function deleteOne(id) {
return await fetchApi('/api/project/delete', { return await fetchApi('/api/project/delete', {
params: { id }, params: { id },
...@@ -38,6 +61,11 @@ export async function deleteOne(id) { ...@@ -38,6 +61,11 @@ export async function deleteOne(id) {
}) })
} }
/**
* 获取一个项目
* @param id
* @return {Promise<*|any>}
*/
export async function fetchOne(id) { export async function fetchOne(id) {
return await fetchApi('/api/project/query/data', { return await fetchApi('/api/project/query/data', {
params: { id }, params: { id },
...@@ -46,6 +74,11 @@ export async function fetchOne(id) { ...@@ -46,6 +74,11 @@ export async function fetchOne(id) {
}) })
} }
/**
* 从历史版本打开
* @param dataUrl
* @return {Promise<*|any>}
*/
export async function fetchOneFromDataUrl(dataUrl) { export async function fetchOneFromDataUrl(dataUrl) {
return await fetchApi(dataUrl, { return await fetchApi(dataUrl, {
auth: false, auth: false,
...@@ -54,6 +87,13 @@ export async function fetchOneFromDataUrl(dataUrl) { ...@@ -54,6 +87,13 @@ export async function fetchOneFromDataUrl(dataUrl) {
}) })
} }
/**
* 获取历史保存列表
* @param id
* @param currentPage
* @param pageSize
* @return {Promise<*|any>}
*/
export async function fetchHistory(id, currentPage, pageSize) { export async function fetchHistory(id, currentPage, pageSize) {
return await fetchApi('/api/project/history', { return await fetchApi('/api/project/history', {
params: { id, currentPage, pageSize }, params: { id, currentPage, pageSize },
...@@ -62,8 +102,14 @@ export async function fetchHistory(id, currentPage, pageSize) { ...@@ -62,8 +102,14 @@ export async function fetchHistory(id, currentPage, pageSize) {
}) })
} }
/**
* 保存项目
* @param project
* @param remark
* @return {Promise<*|any>}
*/
export async function saveOne(project, remark) { export async function saveOne(project, remark) {
project.remark = remark project.remark = remark;
return await fetchApi('/api/project/update', { return await fetchApi('/api/project/update', {
params: project, params: project,
method: 'post', method: 'post',
...@@ -71,6 +117,13 @@ export async function saveOne(project, remark) { ...@@ -71,6 +117,13 @@ export async function saveOne(project, remark) {
}) })
} }
/**
* 打包项目
* @param id
* @param debug
* @param packedAssets
* @return {Promise<*|any>}
*/
export async function pack(id, debug, packedAssets) { export async function pack(id, debug, packedAssets) {
return await fetchApi('/api/project/pack', { return await fetchApi('/api/project/pack', {
params: { id, debug, packedAssets }, params: { id, debug, packedAssets },
...@@ -78,3 +131,17 @@ export async function pack(id, debug, packedAssets) { ...@@ -78,3 +131,17 @@ export async function pack(id, debug, packedAssets) {
errMessage: 'Failed to pack project', errMessage: 'Failed to pack project',
}) })
} }
/**
* 修改开发人员名单
* @param id
* @param operators
* @return {Promise<*|any|>}
*/
export async function updateOperators(id, operators) {
return await fetchApi('/api/project/updateOperators', {
params: { id, operators },
method: 'post',
errMessage: 'Failed to update operator',
})
}
<template> <template>
<el-form class="props-editor" v-if="data&&meta" v-model="data.props" size="mini" :label-width="labelWidth" <el-form class="props-editor" v-if="data&&meta" v-model="data" size="mini" :label-width="labelWidth"
label-position="right" @submit.native.prevent> label-position="right" @submit.native.prevent>
<component v-for="(property, key) in meta.props" <component v-for="(property, key) in meta.props"
:key="key"
:is="mode + '-input-wrapper'"
:editable="editable"
:switchable="switchable"
:mode="mode"
:value="data[key]"
:container="data"
:property="property"
:propertyName="key"
@cmd-prop-change="onCmdPropChanged"
>
<component
:is="getInput(property)" :is="getInput(property)"
:container="data.props" :container="data"
:value="data.props[key]" :value="data[key]"
:propertyName="key" :propertyName="key"
:property="property" :property="property"
:key="key"
:editable="editable" :editable="editable"
:linkable="linkable"
@input="onInput" @input="onInput"
/> />
</component>
</el-form> </el-form>
</template> </template>
...@@ -19,6 +31,7 @@ ...@@ -19,6 +31,7 @@
import { import {
NumberInput, NumberInput,
StringInput, StringInput,
TextInput,
EnumInput, EnumInput,
BooleanInput, BooleanInput,
ColorInput, ColorInput,
...@@ -27,12 +40,17 @@ ...@@ -27,12 +40,17 @@
MapInput, MapInput,
DynamicInput, DynamicInput,
Vector2Input, Vector2Input,
SourceInput,
} from "./inputs"; } from "./inputs";
import {parseType} from 'props-compute' import {parseType} from 'props-compute'
import LinkableInputWrapper from "./inputs/LinkableInputWrapper";
import CmdInputWrapper from "./inputs/CmdInputWrapper";
import SampleInputWrapper from "./inputs/SampleInputWrapper";
const inputMapping = { const inputMapping = {
number: 'NumberInput', number: 'NumberInput',
string: 'StringInput', string: 'StringInput',
text: 'TextInput',
enum: 'EnumInput', enum: 'EnumInput',
boolean: 'BooleanInput', boolean: 'BooleanInput',
color: 'ColorInput', color: 'ColorInput',
...@@ -42,11 +60,13 @@ ...@@ -42,11 +60,13 @@
map: 'MapInput', map: 'MapInput',
vector2: 'Vector2Input', vector2: 'Vector2Input',
array: 'StringInput', array: 'StringInput',
source: 'SourceInput',
}; };
export default { export default {
name: "PropsEditor", name: "PropsEditor",
components: { components: {
SourceInput,
DynamicInput, DynamicInput,
MapInput, MapInput,
NodeSelectInput, NodeSelectInput,
...@@ -56,10 +76,16 @@ ...@@ -56,10 +76,16 @@
EnumInput, EnumInput,
NumberInput, NumberInput,
StringInput, StringInput,
Vector2Input TextInput,
Vector2Input,
LinkableInputWrapper,
CmdInputWrapper,
SampleInputWrapper,
}, },
data() { data() {
return {} return {
}
}, },
props: { props: {
labelWidth: { labelWidth: {
...@@ -70,10 +96,14 @@ ...@@ -70,10 +96,14 @@
type: Boolean, type: Boolean,
default: true default: true
}, },
linkable: { switchable: {
type: Boolean, type: Boolean,
default: false default: false
}, },
mode: {
type: String,
default: 'sample',
},
data: { data: {
type: Object, type: Object,
}, },
...@@ -81,6 +111,11 @@ ...@@ -81,6 +111,11 @@
type: Object, type: Object,
}, },
}, },
watch: {
data(v){
}
},
methods: { methods: {
getInput(property) { getInput(property) {
let {type} = parseType(property.type); let {type} = parseType(property.type);
...@@ -92,6 +127,10 @@ ...@@ -92,6 +127,10 @@
} else { } else {
this.$set(container, propName, value); this.$set(container, propName, value);
} }
this.$emit('input', value, container, propName, oldValue);
},
onCmdPropChanged(value, container, propName, oldValue){
this.$emit('input', value, container, propName, oldValue);
}, },
} }
} }
......
<template>
<div :draggable="draggable" @dragstart="onDragstart" ref="playerContainer" :style="style">
</div>
</template>
<script>
import {mapActions} from 'vuex';
import {Player} from 'svgaplayerweb';
export default {
name: "SvgaPreviewView",
props: {
maxWidth: {
type: Number
},
maxHeight: {
type: Number
},
src: {
type: String
},
draggable: {
type: Boolean,
default: false,
},
},
data() {
return {
videoSize: {
width: 0,
height: 0,
}
}
},
computed: {
style() {
const {width, height} = this.videoSize;
return {
width: (this.maxWidth || width) + 'px',
height: (this.maxHeight || height) + 'px',
}
},
size() {
const {width, height} = this.videoSize;
return `${width}x${height}`;
},
},
watch: {
src(v, oldv) {
if(v !== oldv){
this.update();
}
}
},
mounted() {
let container = this.$refs.playerContainer;
this.player = new Player(container);
this.update();
},
methods: {
onDragstart(e){
this.$emit('dragstart', e);
},
async update() {
const player = this.player;
player.clear();
if(this.src){
let videoItem = await this.loadSvga(this.src);
this.videoSize.width = videoItem.videoSize.width;
this.videoSize.height = videoItem.videoSize.height;
this.$nextTick(() => {
player.setVideoItem(videoItem);
player.startAnimation();
});
}
},
...mapActions([
'loadSvga'
]),
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<el-select v-model="selected" :filterable="filterable" allow-create placeholder="请选择">
<el-option
v-for="item in props"
:style="`${optionStyle}${item.value}`"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</template>
<script>
import optionMapper from './optionMapper';
export default {
props: {
/*
* fontFamily: 字体
* fontSize: 字体大小选择列表
* borderStyle: 边框类型
* animeCount: 动效次数
*/
optionType: {
type: String,
default: 'fontSize'
},
optionList: Array, // 若有 optionList 则groupType 不起作用
value: [String, Number, Boolean],
filterable: Boolean
},
data() {
return {
selected: this.value || '',
optionMapper
};
},
computed: {
props() {
return this.optionList || this.optionMapper[this.optionType];
},
optionStyle() {
return this.optionType === 'fontFamily' ? 'font-family: ' : '';
}
},
watch: {
selected(v) {
this.$emit('change', v);
}
}
};
</script>
import _ from 'lodash'
const rangeStep = (start, step, stop) =>
_.map(
_.range(0, (1 + (stop - start) / step) >>> 0),
(n) => (start + step * n).toFixed(0),
);
export default {
fontFamily: [
{
label: '默认字体',
value: ''
},
{ label: '微软雅黑', value: 'Microsoft Yahei' },
// { label: '方正黑体简体', value: 'FZHei-B01S' },
// { label: '方正楷体简体', value: 'FZKai-Z03S' },
// { label: '方正书宋简体', value: 'FZShuSong-Z01S' },
// { label: '方正仿宋简体', value: 'FZFangSong-Z02S' },
// { label: '思源极细体', value: 'NotoSansSC-Thin' },
// { label: '思源细体', value: 'NotoSansSC-Light' },
// { label: '思源正常', value: 'NotoSansSC-DemiLight' },
// { label: '思源常规', value: 'NotoSansSC-Regular' },
// { label: '思源中等粗体', value: 'NotoSansSC-Medium' },
// { label: '思源粗体', value: 'NotoSansSC-Bold' },
// { label: '思源特粗', value: 'NotoSansSC-Black' },
{ label: '宋体', value: 'SimSun' },
// { label: '黑体', value: 'SimHei' },
{ label: 'fantasy', value: 'fantasy' },
{ label: 'Cursive', value: 'Cursive' }
],
borderStyle: [
{ label: '实线', value: 'solid' },
{ label: '点线', value: 'dotted' },
{ label: '虚线', value: 'dashed' },
{ label: '双线', value: 'double' }
],
backgroundSize: [
{ label: '全覆盖', value: 'cover' },
{ label: '完全显示图片', value: 'contain' }
],
backgroundRepeat: [
{ label: '显示一次', value: 'no-repeat' },
{ label: '重复', value: 'repeat' },
{ label: '水平方向重复', value: 'repeat-x' },
{ label: '垂直方向重复', value: 'repeat-y' }
],
backgroundPosition: [
{ label: '居中', value: 'center' },
{ label: '左上', value: 'top left' },
{ label: '顶部居中', value: 'top center' },
{ label: '右上', value: 'top right' },
{ label: '靠左', value: 'center left' },
{ label: '靠右', value: 'center right' },
{ label: '左下', value: 'bottom left' },
{ label: '底部居中', value: 'bottom center' },
{ label: '右下', value: 'bottom right' }
],
weekIndex: [
{ label: '周日', value: 0 },
{ label: '周一', value: 1 },
{ label: '周二', value: 2 },
{ label: '周三', value: 3 },
{ label: '周四', value: 4 },
{ label: '周五', value: 5 },
{ label: '周六', value: 6 }
],
fontSize: rangeStep(12, 1, 120).map((v) => ({ value: v, label: v })),
animeCount: rangeStep(1, 1, 10)
.map((v) => ({ value: v, label: v }))
.concat({ label: '无限循环', value: true })
};
<template>
<el-slider class="zero-slider" v-model="swvalue" :min="min" :max="max" :step="step" show-input :show-input-controls="false" input-size="mini"></el-slider>
</template>
<style>
/* .zero-slider > .el-slider__input > span {
display: none;
}
.zero-slider > .el-slider__input input {
padding: 0 10px;
} */
/* .zero-slider {
position: relative;
}
.zero-slider > .el-slider__input {
position: absolute;
left: 110%;
top: -250%;
width: 60px;
}
.zero-slider > .el-slider__input input {
padding: 0 10px;
} */
</style>
<script>
export default {
props: {
min: Number,
max: Number,
value: [String, Number, Boolean],
step: Number
},
data() {
return {
swvalue: this.value || 0
};
},
watch: {
swvalue(v) {
this.$emit('change', v);
}
}
};
</script>
<template>
<el-popover
placement="top"
trigger="hover"
width="auto"
:disabled="!legalUrl"
:content="url"
>
<img style="max-width: 200px;" v-if="url" :src="url" alt=""/>
<el-input v-model="swvalue" slot="reference" @drop.native="drop" @dragover.native="dragOver">
<el-button slot="append" icon="el-icon-aim" @click="locateAsset"></el-button>
</el-input>
</el-popover>
</template>
<style>
</style>
<script>
import events from "@/global-events.js"
import {assetScheme} from "../../../utils";
export default {
props: {
value: [String, Number, Boolean]
},
data() {
return {
swvalue: this.value || ''
};
},
watch: {
swvalue(v) {
this.$emit('change', v);
}
},
methods: {
drop(e) {
if (this.$store.state.project.dragUUID) {
console.log('native drop', this.$store.state);
this.swvalue = assetScheme + this.$store.state.project.dragUUID
}
},
dragOver(e) {
e.preventDefault();
},
locateAsset() {
let uuid = this.swvalue ? this.swvalue.split('//')[1] : null;
if (uuid) {
let asset = this.$store.state.project.data.assets.find(a => a.uuid === uuid);
if (asset) {
events.$emit('select-asset-item', asset);
}
}
}
},
computed: {
url: function () {
if (this.swvalue) {
if (this.swvalue.indexOf(assetScheme) > -1) {
let uuid = this.swvalue.split('//')[1];
let _ass = this.$store.state.project.data.assets.find(a => a.uuid === uuid);
return _ass ? _ass.url : '';
} else {
return this.swvalue;
}
} else {
return '';
}
},
legalUrl: function () {
return (this.swvalue + '').indexOf('//') > -1;
}
}
};
</script>
<template>
<el-switch v-model="swvalue"></el-switch>
</template>
<style>
</style>
<script>
export default {
props: {
value: [String, Number, Boolean],
},
data() {
return {
swvalue: true
};
},
mounted() {
console.log('switch created', this.swvalue);
},
watch: {
swvalue(v) {
console.log('switch value change', this.swvalue);
this.$emit('change', v);
}
}
};
</script>
<template> <template>
<input-wrapper :editable="editable" :linkable="linkable" :value="value" :container="container" :property="property" :propertyName="propertyName"> <component :is="mode + '-input-wrapper'" :editable="editable" :linkable="linkable" :value="value" :container="container" :property="property" :propertyName="propertyName">
<el-select :disabled="!editable" :value="editValue" filterable @input="onInput" :placeholder="property.default" class="el-select"> <el-select :disabled="!editable" :value="editValue" filterable @input="onInput" :placeholder="property.default" class="el-select">
<el-option <el-option
v-for="(item, key) in assets" v-for="(item, key) in assets"
...@@ -9,17 +9,18 @@ ...@@ -9,17 +9,18 @@
<span>{{item.name}}</span> <span>{{item.name}}</span>
</el-option> </el-option>
</el-select> </el-select>
</input-wrapper> </component>
</template> </template>
<script> <script>
import {mapMutations} from 'vuex' import {mapMutations} from 'vuex'
import InputWrapper from "./InputWrapper"; import LinkableInputWrapper from "./LinkableInputWrapper";
import CmdInputWrapper from "./CmdInputWrapper";
export default { export default {
name: "AssetInput", name: "AssetInput",
components: {InputWrapper,}, components: {LinkableInputWrapper, CmdInputWrapper},
props: ['value', 'container', 'property', 'propertyName', 'editable', 'linkable'], props: ['value', 'container', 'property', 'propertyName', 'editable'],
computed: { computed: {
editValue() { editValue() {
return this.value === undefined ? this.property.default : this.value; return this.value === undefined ? this.property.default : this.value;
......
<template> <template>
<input-wrapper :editable="editable" :linkable="linkable" :value="value" :container="container" :property="property" :propertyName="propertyName">
<el-switch :disabled="!editable" :value="editValue" @input="onInput" <el-switch :disabled="!editable" :value="editValue" @input="onInput"
class="picker"></el-switch> class="picker"></el-switch>
</input-wrapper>
</template> </template>
<script> <script>
import InputWrapper from "./InputWrapper"; import LinkableInputWrapper from "./LinkableInputWrapper";
import CmdInputWrapper from "./CmdInputWrapper";
export default { export default {
name: "BooleanInput", name: "BooleanInput",
components: {InputWrapper}, components: {LinkableInputWrapper, CmdInputWrapper},
props: ['value', 'container', 'property', 'propertyName', 'editable', 'linkable'], props: ['value', 'container', 'property', 'propertyName', 'editable'],
data() { data() {
return {} return {}
}, },
...@@ -32,6 +31,7 @@ ...@@ -32,6 +31,7 @@
<style scoped> <style scoped>
.picker { .picker {
flex: 1;
float: right; float: right;
margin-top: 4px; margin-top: 4px;
} }
......
<template>
<el-form-item class="input-wrapper" :label="propertyName" content-float="right"
:content-width="contentWidth" :labelOffsetTop="labelOffsetTop">
<el-tooltip placement="left" class="label" slot="label" trigger="hover" :open-delay="500" :enterable="false">
<div slot="content" class="property-name-popover">
<p>{{$t('Alias')}}{{property.alias}}</p>
<p>{{$t('Name')}}{{propertyName}}</p>
</div>
<div>
<p class="alias">{{property.alias||propertyName}}</p>
<p class="property-name">{{propertyName}}</p>
</div>
</el-tooltip>
<template v-if="cmdMode">
<el-input class="cmd-input" placeholder="exp" :value="cmdValue" @input="onInputCmdValue"
@change="saveCmdValue"></el-input>
</template>
<template v-else>
<slot></slot>
</template>
<el-link style="padding: 3px;" icon="el-icon-link" :underline="false"
v-if="switchable"
:type="cmdMode ? 'success' : 'default'" :disabled="!editable" @click="onClickLink"/>
</el-form-item>
</template>
<script>
import ElFormItem from "./form-item";
import {cmdOldPrefix, cmdPrefix} from "../../utils";
export default {
name: "CmdInputWrapper",
components: {ElFormItem},
props: {
property: Object,
value: {},
container: {},
propertyName: String,
editable: Boolean,
switchable: Boolean,
contentWidth: {
type: String,
default: '65%',
},
labelOffsetTop: {
type: Number,
default: 0,
},
},
data() {
return {
//cmdValue: this.container[this.cmdPropName] || '',
}
},
watch: {
container(v) {
//this.cmdValue = this.container[this.cmdPropName] || '';
},
},
computed: {
cmdValue() {
return this.container[this.cmdPropName] || '';
},
cmdMode() {
return this.container.hasOwnProperty(this.cmdPropName);
},
cmdPropName() {
return cmdPrefix + this.propertyName;
},
cmdOldPropName() {
return cmdOldPrefix + this.propertyName;
},
},
methods: {
onClickLink() {
if (this.cmdMode) {
this.$set(this.container, this.cmdOldPropName, this.cmdValue);
this.$delete(this.container, this.cmdPropName);
} else {
let cmdValue = this.container[this.cmdOldPropName] || '';
this.$set(this.container, this.cmdPropName, cmdValue);
}
},
onInputCmdValue(v) {
this.container[this.cmdPropName] = v;
},
saveCmdValue(v) {
let oldValue = this.container[this.cmdPropName];
//this.cmdValue = v;
this.$set(this.container, this.cmdPropName, v);
this.$emit('cmd-prop-change', v, this.container, this.cmdPropName, oldValue);
},
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template> <template>
<input-wrapper :editable="editable" :linkable="linkable" :value="value" :container="container" :property="property" :propertyName="propertyName" class="color-input-container">
<el-color-picker <el-color-picker
:disabled="!editable" :disabled="!editable"
class="picker" class="picker"
...@@ -8,16 +7,16 @@ ...@@ -8,16 +7,16 @@
show-alpha show-alpha
:predefine="predefineColors"> :predefine="predefineColors">
</el-color-picker> </el-color-picker>
</input-wrapper>
</template> </template>
<script> <script>
import InputWrapper from "./InputWrapper"; import LinkableInputWrapper from "./LinkableInputWrapper";
import CmdInputWrapper from "./CmdInputWrapper";
export default { export default {
name: "ColorInput", name: "ColorInput",
components: {InputWrapper,}, components: {LinkableInputWrapper, CmdInputWrapper},
props: ['value', 'container', 'property', 'propertyName', 'editable', 'linkable'], props: ['value', 'container', 'property', 'propertyName', 'editable'],
data() { data() {
return { return {
predefineColors: [ predefineColors: [
...@@ -60,6 +59,7 @@ ...@@ -60,6 +59,7 @@
} }
.picker { .picker {
flex: 1;
float: right; float: right;
} }
</style> </style>
<template> <template>
<input-wrapper :editable="editable" :linkable="linkable" :value="value" :container="container" :property="property"
:propertyName="propertyName">
<dynamic-selector style="flex: 1;" :value="value" @input="onChange" <dynamic-selector style="flex: 1;" :value="value" @input="onChange"
:editable="editable" :editable="editable"
:container="container" :container="container"
:property="property" :property="property"
:propertyName="propertyName"/> :propertyName="propertyName"/>
</input-wrapper>
</template> </template>
<script> <script>
import InputWrapper from "./InputWrapper"; import LinkableInputWrapper from "./LinkableInputWrapper";
import CmdInputWrapper from "./CmdInputWrapper";
import DynamicSelector from "./DynamicSelector"; import DynamicSelector from "./DynamicSelector";
export default { export default {
name: "DynamicInput", name: "DynamicInput",
components: {DynamicSelector, InputWrapper,}, components: {DynamicSelector, LinkableInputWrapper, CmdInputWrapper},
props: ['value', 'container', 'property', 'propertyName', 'editable', 'linkable'], props: ['value', 'container', 'property', 'propertyName', 'editable'],
methods: { methods: {
onChange(v){ onChange(v){
this.$emit('input', v, this.container, this.propertyName, this.value); this.$emit('input', v, this.container, this.propertyName, this.value);
......
...@@ -8,9 +8,12 @@ ...@@ -8,9 +8,12 @@
v-model="popoverVisible" v-model="popoverVisible"
:disabled="!editable" :disabled="!editable"
> >
<div>
<el-radio-group v-model="editValue.type" size="mini" @change="onChange" :disabled="!editable"> <el-radio-group v-model="editValue.type" size="mini" @change="onChange" :disabled="!editable">
<el-radio-button v-for="(item, key) in dataTypes" :label="key" :key="key">{{item}}</el-radio-button> <el-radio-button v-for="(item, key) in dataTypes" :label="key" :key="key">{{item}}</el-radio-button>
</el-radio-group> </el-radio-group>
<el-button circle plain type="danger" icon="el-icon-close" class="micro" style="margin-left: 5px;" @click="popoverVisible=false"/>
</div>
<el-input clearable slot="reference" :value="editValue.value" @input="onInput" @change="onChange" <el-input clearable slot="reference" :value="editValue.value" @input="onInput" @change="onChange"
:readonly="!editable" :readonly="!editable"
:placeholder="defaultValue"/> :placeholder="defaultValue"/>
...@@ -28,7 +31,7 @@ ...@@ -28,7 +31,7 @@
export default { export default {
name: "DynamicSelector", name: "DynamicSelector",
components: {}, components: {},
props: ['value', 'container', 'property', 'propertyName', 'editable', 'linkable'], props: ['value', 'container', 'property', 'propertyName', 'editable'],
data() { data() {
let dataTypes = this.$t('dataTypes'); let dataTypes = this.$t('dataTypes');
return { return {
......
<template> <template>
<input-wrapper :editable="editable" :linkable="linkable" :value="value" :container="container" :property="property" :propertyName="propertyName">
<el-select :disabled="!editable" :value="editValue" @input="onInput" :placeholder="property.default" class="el-select"> <el-select :disabled="!editable" :value="editValue" @input="onInput" :placeholder="property.default" class="el-select">
<el-option <el-option
v-for="(item, key) in property.enum" v-for="(item, key) in property.enum"
:key="item" :key="key"
:label="item" :label="typeof item === 'object' ? item.label : item"
:value="item"> :value="typeof item === 'object' ? item.value : item">
<span>{{item}}</span> <span>{{typeof item === 'object' ? item.label : item}}</span>
<span class="comment"></span> <span class="enum-input-comment">{{typeof item === 'object' ? item.value : item}}</span>
</el-option> </el-option>
</el-select> </el-select>
</input-wrapper>
</template> </template>
<script> <script>
import InputWrapper from "./InputWrapper"; import LinkableInputWrapper from "./LinkableInputWrapper";
import CmdInputWrapper from "./CmdInputWrapper";
export default { export default {
name: "EnumInput", name: "EnumInput",
components: {InputWrapper,}, components: {LinkableInputWrapper, CmdInputWrapper},
props: ['value', 'container', 'property', 'propertyName', 'editable', 'linkable'], props: ['value', 'container', 'property', 'propertyName', 'editable'],
computed: { computed: {
editValue() { editValue() {
return this.value === undefined ? this.property.default : this.value; return this.value === undefined ? this.property.default : this.value;
......
<template> <template>
<el-form-item class="input-wrapper" :label="propertyName" content-float="right" <el-form-item class="input-wrapper" :label="propertyName" content-float="right"
:content-width="contentWidth" :labelOffsetTop="labelOffsetTop"> :content-width="contentWidth" :labelOffsetTop="labelOffsetTop">
<el-tooltip placement="top" class="label" slot="label" trigger="hover" :open-delay="500" :enterable="false"> <el-tooltip placement="left" class="label" slot="label" trigger="hover" :open-delay="500" :enterable="false">
<div slot="content" class="property-name-popover"> <div slot="content" class="property-name-popover">
<p>{{$t('Alias')}}{{property.alias}}</p> <p>{{$t('Alias')}}{{property.alias}}</p>
<p>{{$t('Name')}}{{propertyName}}</p> <p>{{$t('Name')}}{{propertyName}}</p>
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
<slot></slot> <slot></slot>
</template> </template>
<el-popover <el-popover
v-if="linkable" v-if="switchable"
trigger="click" trigger="click"
:disabled="!editable" :disabled="!editable"
> >
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
import ElFormItem from "./form-item"; import ElFormItem from "./form-item";
export default { export default {
name: "InputWrapper", name: "LinkableInputWrapper",
components: {ElFormItem}, components: {ElFormItem},
props: { props: {
property: Object, property: Object,
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
container: {}, container: {},
propertyName: String, propertyName: String,
editable: Boolean, editable: Boolean,
linkable: Boolean, switchable: Boolean,
contentWidth: { contentWidth: {
type: String, type: String,
default: '65%', default: '65%',
......
<template> <template>
<input-wrapper :editable="editable" :linkable="linkable" :value="value" :container="container" :property="property"
:propertyName="propertyName">
<div style="display: flex;flex: 1;"> <div style="display: flex;flex: 1;">
<el-popover <el-popover
popper-class="input-area-popover" popper-class="input-area-popover"
...@@ -33,18 +31,18 @@ ...@@ -33,18 +31,18 @@
<el-button icon="el-icon-delete" @click="onClickClean" :disabled="!editable"></el-button> <el-button icon="el-icon-delete" @click="onClickClean" :disabled="!editable"></el-button>
</el-button-group> </el-button-group>
</div> </div>
</input-wrapper>
</template> </template>
<script> <script>
import InputWrapper from "./InputWrapper"; import LinkableInputWrapper from "./LinkableInputWrapper";
import CmdInputWrapper from "./CmdInputWrapper";
import {getInputDefaultValue} from "../../utils"; import {getInputDefaultValue} from "../../utils";
import DynamicSelector from "./DynamicSelector"; import DynamicSelector from "./DynamicSelector";
export default { export default {
name: "MapInput", name: "MapInput",
components: {DynamicSelector, InputWrapper,}, components: {DynamicSelector, LinkableInputWrapper, CmdInputWrapper},
props: ['value', 'container', 'property', 'propertyName', 'editable', 'linkable'], props: ['value', 'container', 'property', 'propertyName', 'editable'],
data() { data() {
let dataTypes = this.$t('dataTypes'); let dataTypes = this.$t('dataTypes');
return { return {
......
<template> <template>
<input-wrapper :editable="editable" :linkable="linkable" :value="value" :container="container" :property="property"
:propertyName="propertyName">
<div style="display: flex;flex: 1;"> <div style="display: flex;flex: 1;">
<el-popover <el-popover
placement="top" placement="bottom"
popper-class="node-select-popover" popper-class="node-select-popover"
class="node-select-container" class="node-select-container"
trigger="manual" trigger="manual"
width="400" width="400"
height="500"
v-model="popoverVisible" v-model="popoverVisible"
@after-enter="onPopoverShow"
> >
<div> <div>
<el-input v-model="filterText" prefix-icon="el-icon-search" size="mini" clearable/> <el-input v-model="filterText" prefix-icon="el-icon-search" size="mini" clearable/>
...@@ -18,8 +18,10 @@ ...@@ -18,8 +18,10 @@
v-if="popoverVisible" v-if="popoverVisible"
:data="behavior_views" :data="behavior_views"
:props="defaultProps" :props="defaultProps"
:expand-on-click-node="false" :expand-on-click-node="true"
:default-expanded-keys="expandedKeys"
draggable draggable
node-key="uuid"
highlight-current highlight-current
:default-expand-all="true" :default-expand-all="true"
@node-click="handleNodeClick" @node-click="handleNodeClick"
...@@ -34,8 +36,8 @@ ...@@ -34,8 +36,8 @@
<div class="bottom-bar"> <div class="bottom-bar">
<div></div> <div></div>
<div> <div>
<el-button @click="onCancel" plain>Cancel</el-button> <el-button @click="onCancel" plain>{{$t('Cancel')}}</el-button>
<el-button @click="onConfirm" type="primary">Confirm</el-button> <el-button @click="onConfirm" type="primary">{{$t('Confirm')}}</el-button>
</div> </div>
</div> </div>
</div> </div>
...@@ -43,7 +45,7 @@ ...@@ -43,7 +45,7 @@
:readonly="!editable"> :readonly="!editable">
<template slot="prepend"> <template slot="prepend">
<el-tooltip effect="dark" :content="nodePath" placement="top" :open-delay="500" :disabled="!nodePath"> <el-tooltip effect="dark" :content="nodePath" placement="top" :open-delay="500" :disabled="!nodePath">
<el-button>{{nodeScheme}}</el-button> <span>{{nodeScheme}}</span>
</el-tooltip> </el-tooltip>
</template> </template>
</el-input> </el-input>
...@@ -53,18 +55,18 @@ ...@@ -53,18 +55,18 @@
<el-button icon="el-icon-delete" @click="onClickClean" :disabled="!editable"></el-button> <el-button icon="el-icon-delete" @click="onClickClean" :disabled="!editable"></el-button>
</el-button-group> </el-button-group>
</div> </div>
</input-wrapper>
</template> </template>
<script> <script>
import {mapGetters} from "vuex"; import {mapGetters} from "vuex";
import InputWrapper from "./InputWrapper"; import LinkableInputWrapper from "./LinkableInputWrapper";
import CmdInputWrapper from "./CmdInputWrapper";
import {nodeScheme} from "../../utils"; import {nodeScheme} from "../../utils";
export default { export default {
name: "NodeSelectInput", name: "NodeSelectInput",
components: {InputWrapper,}, components: {LinkableInputWrapper, CmdInputWrapper},
props: ['value', 'container', 'property', 'propertyName', 'editable', 'linkable'], props: ['value', 'container', 'property', 'propertyName', 'editable'],
data() { data() {
return { return {
nodeScheme: nodeScheme, nodeScheme: nodeScheme,
...@@ -76,6 +78,7 @@ ...@@ -76,6 +78,7 @@
label: 'name' label: 'name'
}, },
nodePath: '', nodePath: '',
expandedKeys: [],
} }
}, },
watch: { watch: {
...@@ -123,7 +126,12 @@ ...@@ -123,7 +126,12 @@
} }
}, },
filterNodeMethod(value, data) { filterNodeMethod(value, data) {
if(value.startsWith(':uuid|')){
let targetUUID = value.replace(':uuid|', '');
return data.uuid === targetUUID;
}else{
return data.name.toLowerCase().includes(value.toLowerCase()); return data.name.toLowerCase().includes(value.toLowerCase());
}
}, },
onInput(v, oldValue) { onInput(v, oldValue) {
if (v !== this.value) { if (v !== this.value) {
...@@ -135,6 +143,7 @@ ...@@ -135,6 +143,7 @@
}, },
onClickEdit() { onClickEdit() {
this.popoverVisible = !this.popoverVisible; this.popoverVisible = !this.popoverVisible;
}, },
onClickClean() { onClickClean() {
this.nodePath = ''; this.nodePath = '';
...@@ -152,6 +161,16 @@ ...@@ -152,6 +161,16 @@
handleNodeClick(data, node) { handleNodeClick(data, node) {
this.selectedNodeUUID = data.uuid; this.selectedNodeUUID = data.uuid;
}, },
onPopoverShow(){
let uuid = this.editValue;
if(uuid){
this.filterText = ':uuid|' + uuid;
this.updateFilter();
this.$refs.tree.setCurrentKey(uuid);
this.expandedKeys = [uuid];
this.selectedNodeUUID = uuid;
}
},
}, },
} }
</script> </script>
......
<template> <template>
<input-wrapper :editable="editable" :linkable="linkable" :value="value" :container="container" :property="property" :propertyName="propertyName"> <el-input-number :disabled="!editable" :value="editValue" @change="onInput" controls-position="right"
<el-input-number :disabled="!editable" :value="editValue" @input="onInput" controls-position="right"
:placeholder="defaultValue"></el-input-number> :placeholder="defaultValue"></el-input-number>
</input-wrapper>
</template> </template>
<script> <script>
import InputWrapper from "./InputWrapper"; import LinkableInputWrapper from "./LinkableInputWrapper";
import CmdInputWrapper from "./CmdInputWrapper";
import {getInputDefaultValue} from "../../utils"; import {getInputDefaultValue} from "../../utils";
export default { export default {
name: "NumberInput", name: "NumberInput",
components: {InputWrapper,}, components: {LinkableInputWrapper, CmdInputWrapper},
props: ['value', 'container', 'property', 'propertyName', 'editable', 'linkable'], props: ['value', 'container', 'property', 'propertyName', 'editable'],
computed: { computed: {
editValue() { editValue() {
return this.value === undefined ? this.property.default : this.value; return this.value === undefined ? this.property.default : this.value;
......
<template>
<el-form-item class="input-wrapper" :label="propertyName" content-float="right"
:content-width="contentWidth" :labelOffsetTop="labelOffsetTop">
<el-tooltip placement="left" class="label" slot="label" trigger="hover" :open-delay="500" :enterable="false">
<div slot="content" class="property-name-popover">
<p>{{$t('Alias')}}{{property.alias}}</p>
<p>{{$t('Name')}}{{propertyName}}</p>
</div>
<div>
<p class="alias">{{property.alias||propertyName}}</p>
<p class="property-name">{{propertyName}}</p>
</div>
</el-tooltip>
<template>
<slot></slot>
</template>
</el-form-item>
</template>
<script>
import camelcase from 'camelcase'
import ElFormItem from "./form-item";
export default {
name: "SampleInputWrapper",
components: {ElFormItem},
props: {
property: Object,
value: {},
container: {},
propertyName: String,
editable: Boolean,
switchable: Boolean,
contentWidth: {
type: String,
default: '65%',
},
labelOffsetTop: {
type: Number,
default: 0,
},
},
data() {
return {}
},
watch: {
},
computed: {
},
methods: {
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<el-popover
placement="top"
trigger="hover"
width="auto"
:disabled="!legalUrl"
:content="url"
class="source-input"
popper-class="source-input-popover"
>
<div class="wrapper">
<img style="max-width: 200px;" class="thumbnail alpha-image-background" v-if="!url.endsWith('.svga')" :src="url" alt=""/>
<svga-preview-view :max-width="200" class="thumbnail alpha-image-background" :max-height="200" v-if="url.endsWith('.svga')" :src="url" alt=""/>
<span>{{assetSize(url)}}</span>
</div>
<el-input slot="reference" :disabled="!editable" v-model="editValue" controls-position="right" :placeholder="defaultValue"
@change="onChange" @drop.native="drop" @dragover.native="dragOver">
<el-button slot="append" icon="el-icon-aim" @click="locateAsset"></el-button>
</el-input>
</el-popover>
</template>
<script>
import {mapGetters} from 'vuex'
import LinkableInputWrapper from "./LinkableInputWrapper";
import CmdInputWrapper from "./CmdInputWrapper";
import {assetScheme, getInputDefaultValue} from "../../utils";
import events from "@/global-events.js"
import SvgaPreviewView from "../SvgaPreviewView";
export default {
name: "SourceInput",
components: {SvgaPreviewView, LinkableInputWrapper, CmdInputWrapper},
props: ['value', 'container', 'property', 'propertyName', 'editable'],
data(){
return {
editValue: this.getEditValue(),
}
},
mounted(){
this.editValue = this.getEditValue();
},
watch:{
value(){
this.editValue = this.getEditValue();
}
},
computed: {
defaultValue(){
return getInputDefaultValue(this.property);
},
url: function () {
if (this.value) {
if (this.value.startsWith(assetScheme)) {
let uuid = this.value.replace(assetScheme, '');
let _ass = this.assets.find(a => a.uuid === uuid);
return _ass ? _ass.url : '';
} else {
return this.value;
}
} else {
return '';
}
},
legalUrl: function () {
return this.value && this.value.startsWith(assetScheme);
},
...mapGetters(['assets', 'assetSize']),
},
methods: {
getEditValue() {
return this.value === undefined ? this.property.default : this.value;
},
onChange(v) {
if(v !== this.value){
this.$emit('input', v, this.container, this.propertyName, this.value);
}
},
drop(e) {
if (this.$store.state.project.dragUUID) {
console.log('native drop', this.$store.state);
this.editValue = assetScheme + this.$store.state.project.dragUUID;
this.onChange(this.editValue)
}
},
dragOver(e) {
if(this.editable){
e.preventDefault();
}
},
locateAsset() {
let uuid = this.value ? this.value.replace(assetScheme, '') : null;
if (uuid) {
let asset = this.assets.find(a => a.uuid === uuid);
if (asset) {
events.$emit('select-asset-item', asset);
}
}
},
},
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template> <template>
<input-wrapper :editable="editable" :linkable="linkable" :value="value" :container="container" :property="property" :propertyName="propertyName">
<div style="display: flex;flex: 1;"> <div style="display: flex;flex: 1;">
<el-popover <el-popover
placement="top" placement="top"
...@@ -34,17 +33,17 @@ ...@@ -34,17 +33,17 @@
<el-button icon="el-icon-delete" @click="onClickClean" :disabled="!editable"></el-button> <el-button icon="el-icon-delete" @click="onClickClean" :disabled="!editable"></el-button>
</el-button-group> </el-button-group>
</div> </div>
</input-wrapper>
</template> </template>
<script> <script>
import InputWrapper from "./InputWrapper"; import LinkableInputWrapper from "./LinkableInputWrapper";
import CmdInputWrapper from "./CmdInputWrapper";
import {getInputDefaultValue} from "../../utils"; import {getInputDefaultValue} from "../../utils";
export default { export default {
name: "StringInput", name: "StringInput",
components: {InputWrapper,}, components: {LinkableInputWrapper, CmdInputWrapper},
props: ['value', 'container', 'property', 'propertyName', 'editable', 'linkable'], props: ['value', 'container', 'property', 'propertyName', 'editable'],
data() { data() {
return { return {
editValueOrigin: this.value, editValueOrigin: this.value,
......
<template>
<div style="display: flex;flex: 1;">
<el-input :value="value" readonly/>
</div>
</template>
<script>
import LinkableInputWrapper from "./LinkableInputWrapper";
import CmdInputWrapper from "./CmdInputWrapper";
import {getInputDefaultValue} from "../../utils";
export default {
name: "TextInput",
components: {LinkableInputWrapper, CmdInputWrapper},
props: ['value', 'container', 'property', 'propertyName', 'editable'],
data() {
return {
}
},
computed: {
},
watch: {
},
methods: {
},
}
</script>
<style scoped>
.bottom-bar {
margin-top: 5px;
display: flex;
align-items: center;
justify-content: space-between;
}
</style>
<template> <template>
<input-wrapper :editable="editable" :linkable="linkable" :value="value" :container="container" :property="property" <div class="vector2-input">
:propertyName="propertyName">
<span class="field-label">x</span> <span class="field-label">x</span>
<el-input-number :disabled="!editable" :value="editValue.x" @input="v=>onInput(v, 'x')" controls-position="right" <el-input-number style="flex: 1;" :disabled="!editable" v-model="editValue.x" @change="v=>onInput(v, 'x')" controls-position="right"
:placeholder="defaultValue.x"></el-input-number> :placeholder="defaultValue.x"></el-input-number>
<span class="field-label">y</span> <span class="field-label">y</span>
<el-input-number :disabled="!editable" :value="editValue.y" @input="v=>onInput(v, 'y')" controls-position="right" <el-input-number style="flex: 1;" :disabled="!editable" v-model="editValue.y" @change="v=>onInput(v, 'y')" controls-position="right"
:placeholder="defaultValue.y"></el-input-number> :placeholder="defaultValue.y"></el-input-number>
</input-wrapper> </div>
</template> </template>
<script> <script>
import {parseVector2} from "props-compute"; import {parseVector2} from "props-compute";
import InputWrapper from "./InputWrapper"; import LinkableInputWrapper from "./LinkableInputWrapper";
import CmdInputWrapper from "./CmdInputWrapper";
export default { export default {
name: "Vector2Input", name: "Vector2Input",
components: {InputWrapper,}, components: {LinkableInputWrapper, CmdInputWrapper},
props: ['value', 'container', 'property', 'propertyName', 'editable', 'linkable'], props: ['value', 'container', 'property', 'propertyName', 'editable'],
data() { data() {
return { return {
editValue: {}, //editValue: {},
} }
}, },
watch: { watch: {
value(v) { value(v) {
let editValue = v === undefined ? this.property.default : v; //let editValue = v === undefined ? this.property.default : v;
this.editValue = parseVector2(editValue); //this.editValue = parseVector2(editValue);
} }
}, },
computed: { computed: {
/*editValue() { editValue() {
return this.value === undefined ? this.property.default : this.value; return this.value === undefined ? this.defaultValue : parseVector2(this.value);
},*/ },
defaultValue() { defaultValue() {
let value = this.property.default; let value = this.property.default;
let placeholder = {}; let placeholder = {};
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
export {default as NumberInput} from './NumberInput'; export {default as NumberInput} from './NumberInput';
export {default as StringInput} from './StringInput'; export {default as StringInput} from './StringInput';
export {default as TextInput} from './TextInput';
export {default as EnumInput} from './EnumInput'; export {default as EnumInput} from './EnumInput';
export {default as BooleanInput} from './BooleanInput'; export {default as BooleanInput} from './BooleanInput';
export {default as ColorInput} from './ColorInput'; export {default as ColorInput} from './ColorInput';
...@@ -12,3 +13,4 @@ export {default as NodeSelectInput} from './NodeSelectInput'; ...@@ -12,3 +13,4 @@ export {default as NodeSelectInput} from './NodeSelectInput';
export {default as MapInput} from './MapInput'; export {default as MapInput} from './MapInput';
export {default as DynamicInput} from './DynamicInput'; export {default as DynamicInput} from './DynamicInput';
export {default as Vector2Input} from './Vector2Input'; export {default as Vector2Input} from './Vector2Input';
export {default as SourceInput} from './SourceInput';
...@@ -23,7 +23,7 @@ export const SSO_VERIFY_PAGE_URL = '/sso/logout'; ...@@ -23,7 +23,7 @@ export const SSO_VERIFY_PAGE_URL = '/sso/logout';
export const DOCK_POINT_OFFSET = 4; export const DOCK_POINT_OFFSET = 4;
export const PROJECT_PAGE_SIZE = 10; export const PROJECT_PAGE_SIZE = 20;
export const HISTORY_PAGE_SIZE = 20; export const HISTORY_PAGE_SIZE = 20;
//文件类型图标 t表示展示缩略图 //文件类型图标 t表示展示缩略图
......
...@@ -213,10 +213,19 @@ ...@@ -213,10 +213,19 @@
"Name required": "名字必填", "Name required": "名字必填",
"Index page exists": "已存在首页", "Index page exists": "已存在首页",
"Please config projectID": "请先配置{env}环境下的projectId", "Please config projectID": "请先配置{env}环境下的projectId",
"Online ticket is invalid": "线上tickct失效,请联系管理员修改", "SSO is invalid": "SSO失效,请重新验证",
"Are you sure to transform process?": "你确定将此转化为{inlineType}过程吗?", "Are you sure to transform process?": "你确定将此转化为{inlineType}过程吗?",
"Input custom process name": "请输入自定义过程名称", "Input custom process name": "请输入自定义过程名称",
"Invalid name": "无效名称", "Invalid name": "无效名称",
"Function cmd": "功能指令",
"Edit store": "编辑数据",
"Edit computed": "计算属性",
"Are you sure to delete this cmd?": "确定删除这个指令吗?",
"Store editor": "数据编辑器",
"Store": "数据",
"Operate": "操作",
"Computed": "计算属性",
"Are you sure to close?": "确定关闭吗?",
"eventGroup": { "eventGroup": {
"in": "接收", "in": "接收",
"out": "派发" "out": "派发"
...@@ -237,6 +246,7 @@ ...@@ -237,6 +246,7 @@
"pack": { "pack": {
"label": "打包", "label": "打包",
"sub": { "sub": {
"pack-debug-mode": "调试打包",
"pack-manager": "打包管理" "pack-manager": "打包管理"
} }
}, },
...@@ -367,5 +377,9 @@ ...@@ -367,5 +377,9 @@
"rename": "重命名", "rename": "重命名",
"replace": "替换", "replace": "替换",
"combine": "合并" "combine": "合并"
},
"customCmds": {
"z-for": "循环",
"z-if": "存在"
} }
} }
\ No newline at end of file
...@@ -4,15 +4,18 @@ ...@@ -4,15 +4,18 @@
* 环境 * 环境
*/ */
import Vue from "vue";
import {envApi} from "../../api"; import {envApi} from "../../api";
import {Parser} from "svgaplayerweb";
const storeKey = 'code-sync-serve-config'; const storeKey = 'code-sync-serve-config';
const svgaParser = new Parser();
export const editorStore = { export const editorStore = {
state: { state: {
initialized: false, initialized: false,
name: 'Zeroing Editor', name: 'Zeroing Editor',
version: '1.0.3', version: '0.1.0',
templates: { templates: {
builtin: ['blank'], builtin: ['blank'],
custom: [], custom: [],
...@@ -21,7 +24,10 @@ export const editorStore = { ...@@ -21,7 +24,10 @@ export const editorStore = {
autoLaunch: false, autoLaunch: false,
ip: 'localhost', ip: 'localhost',
port: 7788, port: 7788,
} },
svgaCache: {},
svgaLoadingQueue: {},
assetSizeCache: {},
}, },
mutations: { mutations: {
updateEnv(state, env) { updateEnv(state, env) {
...@@ -40,6 +46,13 @@ export const editorStore = { ...@@ -40,6 +46,13 @@ export const editorStore = {
}, },
}, },
getters: { getters: {
assetSize: state => url => {
let size = state.assetSizeCache[url];
if(size){
return `${size.width}x${size.height}`
}
return '0x0';
}
}, },
actions: { actions: {
async updateEnv({state, commit}) { async updateEnv({state, commit}) {
...@@ -48,5 +61,67 @@ export const editorStore = { ...@@ -48,5 +61,67 @@ export const editorStore = {
commit('updateEnv', env); commit('updateEnv', env);
} }
}, },
loadSvga({state, commit}, url) {
const {svgaCache, svgaLoadingQueue} = state;
return new Promise((resolve, reject) => {
let videoItem = svgaCache[url];
if (videoItem) {
resolve(videoItem);
} else if (svgaLoadingQueue[url]) {
svgaLoadingQueue[url].push({resolve, reject});
} else {
svgaLoadingQueue[url] = [{resolve, reject}];
svgaParser.load(url, (videoItem) => {
let queue = svgaLoadingQueue[url];
svgaCache[url] = videoItem;
while (queue.length > 0) {
let item = queue.shift();
item.resolve(videoItem);
}
delete svgaLoadingQueue[url];
}, (e) => {
let queue = svgaLoadingQueue[url];
while (queue.length > 0) {
let item = queue.shift();
item.reject(e);
}
delete svgaLoadingQueue[url];
}
)
}
})
},
async updateAssetSize({state, commit, dispatch}, url) {
let size = state.assetSizeCache[url];
if (!size) {
let extname = url.substr(url.lastIndexOf('.'));
switch (extname) {
case '.svga':
let data = await dispatch('loadSvga', url);
Vue.set(state.assetSizeCache, url, data.videoSize);
break;
case '.jpg':
case '.png':
case '.gif':
case '.svg':
await new Promise((resolve, reject) => {
let img = new Image();
img.onload = function () {
let size = {
width: img.width,
height: img.height,
};
Vue.set(state.assetSizeCache, url, size);
resolve(size);
};
img.onerror = function (e) {
reject(e);
};
img.src = url;
});
break;
}
}
},
} }
}; };
...@@ -96,6 +96,8 @@ export const projectStore = { ...@@ -96,6 +96,8 @@ export const projectStore = {
id: '', id: '',
name: '', name: '',
creator: '', creator: '',
operator: '',
operators: '',
data: { data: {
options: {}, options: {},
views: [], views: [],
...@@ -246,7 +248,7 @@ export const projectStore = { ...@@ -246,7 +248,7 @@ export const projectStore = {
if (view.type) { if (view.type) {
// view.type有值说明修改了节点的类型 // view.type有值说明修改了节点的类型
// 如果修改了节点类型,需要删除无用的属性 // 如果修改了节点类型,需要删除无用的属性
let defaultProps = Object.keys(getCmpProps(view.type)); let defaultProps = Object.keys(getCmpProps(view.type).props);
_.forIn(newView.properties, (value, key) => { _.forIn(newView.properties, (value, key) => {
if (defaultProps.indexOf(key) === -1) { if (defaultProps.indexOf(key) === -1) {
...@@ -481,7 +483,22 @@ export const projectStore = { ...@@ -481,7 +483,22 @@ export const projectStore = {
setMockServeEnabled(state, enabled) { setMockServeEnabled(state, enabled) {
state.mockServeEnabled = enabled; state.mockServeEnabled = enabled;
} },
modifyViewStore(state, {view, store}){
view.store = store;
this.commit('makeProjectDirty');
},
addCmd(state, cmd){
Vue.set(state.activeComponent.properties, cmd, '');
this.commit('makeProjectDirty');
},
deleteCmd(state, cmd){
Vue.delete(state.activeComponent.properties, cmd);
this.commit('makeProjectDirty');
},
}, },
getters: { getters: {
project(state) { project(state) {
...@@ -676,15 +693,25 @@ export const projectStore = { ...@@ -676,15 +693,25 @@ export const projectStore = {
return getTopView(node.parent); return getTopView(node.parent);
} }
}; };
let _view = getTopView(data.node);
if (!data.fromPlayground) { if (!data.fromPlayground) {
// 点击视图区域选中节点 // 点击视图区域选中节点
// 则需要切换当前节点所在的最顶层视图 // 则需要切换当前节点所在的最顶层视图
let _view = getTopView(data.node);
if (_view && _view.data) { if (_view && _view.data) {
context.state.activeViews = _view.data.uuid; context.state.activeViews = _view.data.uuid;
} }
} }
if(_view.data === data.data){
if(!data.data.hasOwnProperty('$isRootView')){
Object.defineProperty(data.data, '$isRootView', {
get(){
return true;
}
})
}
}
context.commit('activeComponent', data.data); context.commit('activeComponent', data.data);
}, },
/** /**
...@@ -809,11 +836,11 @@ export const projectStore = { ...@@ -809,11 +836,11 @@ export const projectStore = {
return failedList; return failedList;
}, },
async packProject({state, dispatch}, params) { async packProject({state, dispatch}, params) {
let debug = false; 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);
console.log(packResult); console.log(packResult);
......
...@@ -94,6 +94,10 @@ $dock-pin-width: 9px; ...@@ -94,6 +94,10 @@ $dock-pin-width: 9px;
stroke: $--color-primary; stroke: $--color-primary;
stroke-dasharray: 5, 1; stroke-dasharray: 5, 1;
} }
&.contact {
stroke: $--color-primary;
}
} }
.node { .node {
...@@ -281,7 +285,6 @@ $dock-pin-width: 9px; ...@@ -281,7 +285,6 @@ $dock-pin-width: 9px;
flex-direction: column; flex-direction: column;
.wrapper { .wrapper {
padding: 5px; padding: 5px;
flex: 1; flex: 1;
...@@ -302,19 +305,20 @@ $dock-pin-width: 9px; ...@@ -302,19 +305,20 @@ $dock-pin-width: 9px;
} }
} }
.inside-code{ .inside-code {
flex: 1; flex: 1;
height: 0; height: 0;
border-top: 1px solid $--border-color-base; border-top: 1px solid $--border-color-base;
.scrollbar { .scrollbar {
height: 100%; height: 100%;
.code-body{
.code-body {
tab-size: 1.5em; tab-size: 1.5em;
width: 100%; width: 100%;
margin: 0; margin: 0;
font-size: 12px; font-size: 12px;
white-space:pre-wrap; white-space: pre-wrap;
} }
} }
} }
...@@ -394,7 +398,7 @@ $dock-pin-width: 9px; ...@@ -394,7 +398,7 @@ $dock-pin-width: 9px;
} }
} }
.property-name-popover{ .property-name-popover {
p { p {
margin: 0; margin: 0;
//text-overflow: ellipsis; //text-overflow: ellipsis;
...@@ -414,7 +418,7 @@ $dock-pin-width: 9px; ...@@ -414,7 +418,7 @@ $dock-pin-width: 9px;
} }
} }
.props-editor{ .props-editor {
.linked { .linked {
display: block; display: block;
height: 26px; height: 26px;
...@@ -455,22 +459,37 @@ $dock-pin-width: 9px; ...@@ -455,22 +459,37 @@ $dock-pin-width: 9px;
color: $--color-text-secondary; color: $--color-text-secondary;
} }
} }
.field-label{
.field-label {
padding: 0 5px; padding: 0 5px;
color: $--color-text-secondary; color: $--color-text-secondary;
} }
} }
.el-form-item__content { .source-input {
display: flex;
justify-content: flex-end;
.el-input-number--mini {
flex: 1; flex: 1;
} }
.vector2-input {
flex: 1;
display: flex;
width: 0;
} }
.node-select-container { .node-select-container {
flex: 1; flex: 1;
} }
} }
.source-input-popover {
.wrapper {
display: flex;
flex-direction: column;
align-items: center;
}
}
.enum-input-comment {
float: right;
color: $--color-text-secondary;
}
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
margin-bottom: 1px; margin-bottom: 1px;
padding: 5px 10px; padding: 5px 10px;
font-size: 13px; font-size: 13px;
justify-content: space-between;
.menu { .menu {
flex: 1; flex: 1;
...@@ -47,6 +48,38 @@ ...@@ -47,6 +48,38 @@
background-color: $--pane-background-color; background-color: $--pane-background-color;
} }
.package-list{
display: flex;
flex-direction: column;
.list {
display: flex;
flex-direction: column;
flex: 1;
margin-bottom: 5px;
.item + .item {
}
.item {
display: flex;
align-items: center;
padding-top: 5px;
&:hover {
& > .delete-button {
visibility: visible;
}
}
&:nth-child(odd){
background-color: #FAFAFA;
}
}
}
}
.mapping-list { .mapping-list {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
...@@ -309,6 +342,43 @@ ...@@ -309,6 +342,43 @@
} }
} }
.store-editor-dialog {
.wrapper {
height: 50vh;
.tabs {
height: 100%;
display: flex;
flex-direction: column;
.el-tabs__content {
flex: 1;
& > div {
height: 100%;
}
.editor {
height: 100%;
}
.computed-editor{
.editor{
height: 200px;
}
}
}
}
}
.dialog-footer{
.save-button{
margin-left: 10px;
}
}
}
.px-publish-view { .px-publish-view {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
......
...@@ -48,6 +48,10 @@ ...@@ -48,6 +48,10 @@
overflow-y: hidden; overflow-y: hidden;
} }
.pr-10px{
padding-right: 10px;
}
.el-form-item--mini.el-form-item { .el-form-item--mini.el-form-item {
margin-bottom: 3px; margin-bottom: 3px;
} }
...@@ -76,8 +80,12 @@ ...@@ -76,8 +80,12 @@
line-height: 30px; line-height: 30px;
} }
.el-collapse-item__content{
padding-bottom: 5px;
}
.el-tabs--border-card > .el-tabs__content { .el-tabs--border-card > .el-tabs__content {
padding: 5px 0 5px 5px; padding: 5px;
} }
.el-input-number.is-controls-right .el-input__inner { .el-input-number.is-controls-right .el-input__inner {
...@@ -98,3 +106,26 @@ ...@@ -98,3 +106,26 @@
padding: 3px; padding: 3px;
align-self: center; align-self: center;
} }
.el-tabs__item {
height: 25px;
line-height: 25px;
}
.el-tab-pane {
height: 100%;
}
.el-form-item__content {
display: flex;
//justify-content: flex-end;
.el-input-number--mini {
flex: 1;
}
.el-button{
padding-left: 5px;
padding-right: 5px;
}
}
...@@ -6,45 +6,39 @@ ...@@ -6,45 +6,39 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
&>:last-child{ & > :last-child {
flex: 1; flex: 1;
height: 0; height: 0;
} }
.el-tabs__item {
height: 25px;
line-height: 25px;
}
.el-tab-pane{
height: 100%;
}
.zero-inspector-props-form { .zero-inspector-props-form {
height: 100%; height: 100%;
.el-form{ .form {
padding-right: 10px; height: 100%;
display: flex;
flex-direction: column;
} }
.el-input-number.el-input-number--mini, .el-select.el-select--mini { .top-bar {
width: 100%; padding: 5px;
} }
.el-slider.zero-slider { .scrollbar {
width: 180px; flex: 1;
margin-right: -5px;
} }
.zero-slider .el-slider__runway.show-input { .cmd-input {
width: 100px; .el-input__inner {
color: $--color-primary;
} }
.zero-slider > .el-slider__input {
width: 60px;
} }
.scrollbar{ .add-item-bar {
height: 100%; padding-top: 10px;
padding-bottom: 6px;
text-align: center;
} }
} }
...@@ -53,11 +47,11 @@ ...@@ -53,11 +47,11 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.add-trigger{ .add-trigger {
align-self: flex-start; align-self: flex-start;
} }
.scrollbar{ .scrollbar {
margin-top: 5px; margin-top: 5px;
height: 100%; height: 100%;
} }
...@@ -66,7 +60,7 @@ ...@@ -66,7 +60,7 @@
margin-left: 5px; margin-left: 5px;
} }
.trigger-list{ .trigger-list {
color: $--color-text-regular; color: $--color-text-regular;
font-size: 12px; font-size: 12px;
padding-right: 10px; padding-right: 10px;
...@@ -74,21 +68,22 @@ ...@@ -74,21 +68,22 @@
.trigger-item + .trigger-item { .trigger-item + .trigger-item {
margin-top: 5px; margin-top: 5px;
} }
.trigger-item { .trigger-item {
border: 1px solid lightgray; border: 1px solid lightgray;
border-radius: 3px; border-radius: 3px;
padding: 3px; padding: 3px;
.el-button{ .el-button {
padding: 3px; padding: 3px;
} }
.top-bar{ .top-bar {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
.name{ .name {
color: $--color-primary; color: $--color-primary;
font-size: 14px; font-size: 14px;
font-weight: bold; font-weight: bold;
...@@ -111,12 +106,12 @@ ...@@ -111,12 +106,12 @@
align-items: center; align-items: center;
margin-top: 2px; margin-top: 2px;
.name-field{ .name-field {
flex: 1; flex: 1;
margin-left: 3px; margin-left: 3px;
} }
.missing-behavior{ .missing-behavior {
color: $--color-danger; color: $--color-danger;
} }
......
...@@ -161,7 +161,7 @@ function completeSelfProps(component) { ...@@ -161,7 +161,7 @@ function completeSelfProps(component) {
let defaultProps = getCmpProps(component.type); let defaultProps = getCmpProps(component.type);
// 把这些属性格式转换成key: value // 把这些属性格式转换成key: value
defaultProps = _.mapValues(defaultProps, o => (o.value)); defaultProps = _.mapValues(defaultProps.props, o => (o.default));
return _.merge(defaultProps, component.properties); return _.merge(defaultProps, component.properties);
} }
...@@ -320,26 +320,25 @@ export const styles = { ...@@ -320,26 +320,25 @@ export const styles = {
} }
} }
const cmpPropsCache = {}; const cmpMetaCache = {};
export function getCmpProps(type) { export function getCmpProps(type) {
if (!type) { if (!type) {
return {} return {}
} else { } else {
let cmpProps = cmpPropsCache[type]; let cmpProps = cmpMetaCache[type];
if (cmpProps) { if (cmpProps) {
cmpProps = _.cloneDeep(cmpProps); cmpProps = _.cloneDeep(cmpProps);
} else { } else {
let typeProps = properties[type]; let typeMeta = _.cloneDeep(properties[type]);
let inherits = [_.cloneDeep(typeProps)]; let inherits = [typeMeta.props];
while (typeProps.base) { let tempMeta = typeMeta;
typeProps = cmpPropsCache.hasOwnProperty(typeProps.base) ? cmpPropsCache[typeProps.base] : properties[typeProps.base]; while (tempMeta.base) {
inherits.unshift(_.cloneDeep(typeProps)); tempMeta = cmpMetaCache.hasOwnProperty(tempMeta.base) ? cmpMetaCache[tempMeta.base] : properties[tempMeta.base];
inherits.unshift(_.cloneDeep(tempMeta.props));
} }
let result = Object.assign({}, ...inherits); typeMeta.props = Object.assign({}, ...inherits);
cmpProps = cmpPropsCache[type] = result; cmpProps = cmpMetaCache[type] = typeMeta;
delete result.base;
delete result.groupName;
} }
return cmpProps; return cmpProps;
......
...@@ -32,6 +32,14 @@ export const pxHostMapping = { ...@@ -32,6 +32,14 @@ export const pxHostMapping = {
prod: "https://activity.m.duiba.com.cn" prod: "https://activity.m.duiba.com.cn"
}; };
export const monacoEditorOptions = {
tabSize: 2,
insertSpaces: false
};
export const cmdPrefix = 'z-';
export const cmdOldPrefix = '//z-';
/** /**
* 节点方案 * 节点方案
* @type {string} * @type {string}
......
This diff is collapsed.
...@@ -122,8 +122,8 @@ ...@@ -122,8 +122,8 @@
methods: { methods: {
prepare() { prepare() {
return Promise.all([ return Promise.all([
this.updateEnv(),
db.open('store'), db.open('store'),
this.updateEnv(),
]) ])
}, },
onKeyPress(e) { onKeyPress(e) {
...@@ -234,6 +234,9 @@ ...@@ -234,6 +234,9 @@
case 'pack': case 'pack':
await this.pack(); await this.pack();
break; break;
case 'pack-debug-mode':
await this.pack(true);
break;
case 'pack-manager': case 'pack-manager':
this.$refs.packManagerDialog.show(); this.$refs.packManagerDialog.show();
break; break;
...@@ -274,7 +277,7 @@ ...@@ -274,7 +277,7 @@
break; break;
} }
}, },
async pack() { async pack(debug) {
let cancel; let cancel;
cancel = await this.saveProject(false); cancel = await this.saveProject(false);
if (cancel) { if (cancel) {
...@@ -286,6 +289,7 @@ ...@@ -286,6 +289,7 @@
}); });
try { try {
await this.packProject({ await this.packProject({
debug: debug || false,
remark: this.lastSaveRemark, remark: this.lastSaveRemark,
}); });
this.$message({ this.$message({
......
...@@ -13,6 +13,10 @@ ...@@ -13,6 +13,10 @@
</div> </div>
<div class="item"> <div class="item">
<p>
<span>size</span>:
<span>{{assetSize(currentItem.url)}}</span>
</p>
<p v-for="(field, index) in showFields" :key="index"> <p v-for="(field, index) in showFields" :key="index">
<span>{{field}}</span>: <span>{{field}}</span>:
<span>{{currentItem[field]}}</span> <span>{{currentItem[field]}}</span>
...@@ -57,13 +61,13 @@ ...@@ -57,13 +61,13 @@
} }
}, },
computed: { computed: {
...mapGetters(['assets']), ...mapGetters(['assets', 'assetSize']),
}, },
mounted() { mounted() {
this.currentItem = null; this.currentItem = null;
events.$on('select-asset-item', this.selectAssetItem); events.$on('select-asset-item', this.selectAssetItem);
}, },
destroyed(){ destroyed() {
events.$off('select-asset-item', this.selectAssetItem); events.$off('select-asset-item', this.selectAssetItem);
}, },
methods: { methods: {
...@@ -93,6 +97,7 @@ ...@@ -93,6 +97,7 @@
this.$refs.assetsShow.show(asset); this.$refs.assetsShow.show(asset);
}, },
onItemClick(asset) { onItemClick(asset) {
this.updateAssetSize(asset.url);
this.currentItem = asset; this.currentItem = asset;
}, },
deleteAll() { deleteAll() {
...@@ -105,7 +110,8 @@ ...@@ -105,7 +110,8 @@
}).catch((e) => { }).catch((e) => {
}); });
}, },
selectAssetItem(asset){ selectAssetItem(asset) {
this.updateAssetSize(asset.url);
this.currentItem = asset; this.currentItem = asset;
this.$refs.assetList.selectItem(asset); this.$refs.assetList.selectItem(asset);
}, },
...@@ -114,6 +120,7 @@ ...@@ -114,6 +120,7 @@
]), ]),
...mapActions([ ...mapActions([
'uploadFiles', 'uploadFiles',
'updateAssetSize',
]), ]),
} }
} }
......
<template> <template>
<div class="file-item" @click="$emit('click', $event)"> <div class="file-item" @click="$emit('click', $event)">
<div class="icon"> <div class="icon">
<i @dragstart="assetDragStart(data)" v-if="!showThumbnail" draggable="true" class="file-icon" <i @dragstart="assetDragStart(data)" v-if="showIcon" draggable="true" class="file-icon"
:class="fileIcon"></i> :class="fileIcon"></i>
<img @dragstart="assetDragStart(data)" v-if="showThumbnail" draggable="true" <img @dragstart="assetDragStart(data)" v-if="showThumbnail" draggable="true"
class="thumbnail alpha-image-background" :src="thumbnailUrl" class="thumbnail alpha-image-background" :src="thumbnailUrl"
alt="thumb" @dblclick="onDbclick()"> alt="thumb" @dblclick="onDbclick()">
<svga-preview-view @dragstart="assetDragStart(data)" draggable class="alpha-image-background" v-if="showSvga"
:max-width="60"
:max-height="60"
:src="thumbnailUrl"></svga-preview-view>
<div v-if="editable" class="operate-bar"> <div v-if="editable" class="operate-bar">
<!--<el-button class="micro" circle plain size="mini" type="success" icon="icon-upload" @dblclick.native.stop <!--<el-button class="micro" circle plain size="mini" type="success" icon="icon-upload" @dblclick.native.stop
@click="onClickReplace"/>--> @click="onClickReplace"/>-->
...@@ -46,9 +50,11 @@ ...@@ -46,9 +50,11 @@
import {mapMutations, mapActions} from "vuex"; import {mapMutations, mapActions} from "vuex";
import {fileTypeIcon} from "../../../config"; import {fileTypeIcon} from "../../../config";
import {selectFile, strEllipsis} from "../../../utils"; import {selectFile, strEllipsis} from "../../../utils";
import SvgaPreviewView from "../../../components/SvgaPreviewView";
export default { export default {
name: "FileItem", name: "FileItem",
components: {SvgaPreviewView},
props: { props: {
data: {type: Object}, data: {type: Object},
editable: {type: Boolean, default: false}, editable: {type: Boolean, default: false},
...@@ -68,6 +74,12 @@ ...@@ -68,6 +74,12 @@
showThumbnail() { showThumbnail() {
return fileTypeIcon[this.data.ext] === 't'; return fileTypeIcon[this.data.ext] === 't';
}, },
showSvga() {
return this.data.ext === '.svga';
},
showIcon() {
return !this.showThumbnail && !this.showSvga;
},
thumbnailUrl() { thumbnailUrl() {
return this.data.url; return this.data.url;
}, },
......
<template> <template>
<div class="zero-inspector-props-form" v-if="activeComponent.uuid"> <div class="zero-inspector-props-form" v-if="activeComponent.uuid">
<el-scrollbar class="scrollbar" wrap-class="wrap-x-hidden"> <el-form class="form" ref="form" size="mini" :model="form" label-width="100px" @submit.native.prevent>
<el-form ref="form" size="mini" :model="form" label-width="100px" @submit.native.prevent> <div class="top-bar" v-if="activeComponent.$isRootView">
<el-form-item label="名称"> <el-button size="mini" @click="clickEditStoreExp">{{$t('Edit store')}}</el-button>
<el-button size="mini" @click="clickEditStoreComputed">{{$t('Edit computed')}}</el-button>
</div>
<el-form-item :label="$t('Name')">
<el-input v-model="form.name" @input="v => handleChange('name', v)"></el-input> <el-input v-model="form.name" @input="v => handleChange('name', v)"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="类型"> <el-form-item :label="$t('Type')">
<el-select v-model="form.type" @change="v => handleChange('type', v)" placeholder="请选择类型"> <el-select style="flex:1;" v-model="form.type" @change="v => handleChange('type', v)" placeholder="请选择类型">
<el-option v-for="(cmp, key) in componentsMap" :key="key" :label="cmp" :value="key"></el-option> <el-option v-for="(cmp, key) in componentsMap" :key="key" :label="cmp" :value="key"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<template v-for="(p, key) in cmpProps"> <el-scrollbar class="scrollbar" wrap-class="wrap-x-hidden" view-class="pr-10px">
<el-form-item v-if="key !== 'groupName'" :id="activeComponent.uuid + '-' + key" :key="activeComponent.uuid + key" :label="p.title"> <el-collapse v-model="activeNames">
<!-- {{key}} --> <el-collapse-item :title="$t('Props')" name="props">
<el-tooltip :disabled="!p.desc" placement="top-start"> <props-editor
<div slot="content">{{p.desc}}</div> ref="propsEditor"
<div> :editable="true"
<dynamic-component :component-value="getPropValue(p, key)" :component-props="getPropProps(p)" :component-type="getPropCmpType(p)" @onChange="v => handlePropertiesChange(key, v)"></dynamic-component> :switchable="true"
</div> mode="cmd"
</el-tooltip> :data="form.properties"
:meta="propsMeta"
@input="onInput"
/>
</el-collapse-item>
<el-collapse-item :title="$t('Function cmd') + `(${customCmdKeys.length})`" name="cmd">
<el-form-item v-for="key in customCmdKeys" :label="customCmdNames[key]" :key="key" label-width="50px">
<el-input class="cmd-input" v-model="activeComponent.properties[key]" @change="makeProjectDirty"/>
<el-popconfirm :title="$t('Are you sure to delete this cmd?')" @onConfirm="deleteCmd(key)">
<el-button slot="reference" plain icon="el-icon-delete"/>
</el-popconfirm>
</el-form-item> </el-form-item>
</template> <div class="add-item-bar">
</el-form> <el-dropdown trigger="click" @command="addCmd" placement="bottom" size="small">
<el-button size="mini" type="primary" plain>{{$t('Add')}}</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
v-for="(cmd, key) of customCmdNames"
:command="key"
:key="key"
:disabled="customCmdKeys.includes(key)"
>{{cmd}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</el-collapse-item>
</el-collapse>
</el-scrollbar> </el-scrollbar>
</el-form>
<store-editor-dialog ref="storeEditorDialog"/>
</div> </div>
</template> </template>
<script> <script>
import { mapGetters, mapState } from 'vuex'; import {mapGetters, mapMutations} from 'vuex';
import _ from 'lodash'; import PropsEditor from "../../../components/PropsEditor";
import { getCmpProps } from '../../../utils/common'; import {getCmpProps} from "../../../utils/common";
import dynamicComponent from '../components/dynamicComponent'; import StoreEditorDialog from "./PropsTab/StoreEditorDialog";
import ElFormItem from "../../../components/inputs/form-item";
const componentMapper = {
switch: {
component: 'el-switch',
props: {
width: 100
}
},
select: {
component: 'el-select',
props: {
slotComponent: 'el-option'
}
},
swSelect: {
component: 'sw-select' // 无需传入options
},
source: {
component: 'sw-source'
},
slider: {
component: 'sw-slider'
},
inputNumber: {
component: 'el-input-number',
props: {
size: 'mini',
'controls-position': 'right'
}
},
textArea: {
component: 'el-input',
props: {
type: 'textarea',
autosize: {
minRows: 3,
maxRows: 10
}
}
},
input: {
component: 'el-input'
},
colorPicker: {
component: 'el-color-picker',
props: {
'show-alpha': true
}
}
};
export default { export default {
name: 'PropsTab', name: 'PropsTab',
components: { 'dynamic-component': dynamicComponent }, components: {ElFormItem, StoreEditorDialog, PropsEditor},
data() { data() {
const componentsMap = this.$t('view_node_menu'); const componentsMap = this.$t('view_node_menu');
const customCmdNames = this.$t('customCmds');
return { return {
activeNames: 'props',
componentsMap, componentsMap,
customCmdNames,
form: { form: {
name: '', name: '',
type: '', type: '',
...@@ -98,15 +81,24 @@ export default { ...@@ -98,15 +81,24 @@ export default {
}, },
computed: { computed: {
...mapGetters(['activeComponent', 'activeComponentCopy', 'componentList']), ...mapGetters(['activeComponent', 'activeComponentCopy', 'componentList']),
cmpProps: function() { propsMeta() {
// 获取properties.js中的默认配置
return getCmpProps(this.activeComponent.type); return getCmpProps(this.activeComponent.type);
}, },
customCmdKeys() {
let cmdNames = Object.keys(this.customCmdNames);
let keys = [];
for (let key in this.activeComponent.properties) {
if (cmdNames.includes(key)) {
keys.push(key);
}
}
return keys;
}
}, },
watch: { watch: {
activeComponent: { activeComponent: {
deep: true, deep: true,
handler: function(val) { handler: function (val) {
this.form.name = val.name || ''; this.form.name = val.name || '';
this.form.type = val.type || ''; this.form.type = val.type || '';
this.form.properties = val.properties || {}; this.form.properties = val.properties || {};
...@@ -119,57 +111,24 @@ export default { ...@@ -119,57 +111,24 @@ export default {
_view[label] = v; _view[label] = v;
this.$store.dispatch('modifyActiveView', _view); this.$store.dispatch('modifyActiveView', _view);
}, },
/** onInput(value, container, propName, oldValue) {
* 基础属性发生改变 console.log('propsChange', propName, value);
*/
handlePropertiesChange(key, v) {
console.log('handlePropertiesChange', key, v);
let _prop = {}; let _prop = {};
_prop[key] = v; _prop[propName] = value;
this.$store.dispatch('modifyProperties', _prop); this.$store.dispatch('modifyProperties', _prop);
}, },
/** clickEditStoreExp() {
* 获取动态组件的类型 this.$refs.storeEditorDialog.edit('exp', this.activeComponent);
*/
getPropCmpType(item) {
return componentMapper[item.type].component;
},
/**
* 获取动态组件的属性v-bind
*/
getPropProps(item) {
let _cmp = componentMapper[item.type];
return {
size: 'mini',
...(_cmp.props || {}),
...item.props,
options: item.options || {}
};
}, },
/** clickEditStoreComputed() {
* 获取当前选中节点对应的属性的值 this.$refs.storeEditorDialog.edit('computed', this.activeComponent);
*/
getPropValue(item, key) {
let _properties = this.activeComponentCopy.properties;
return _properties[key] === undefined || _properties[key] === null ? item.value : _properties[key];
}, },
...mapMutations(['makeProjectDirty', 'addCmd', 'deleteCmd']),
} }
}; };
</script> </script>
<style lang="scss"> <style lang="scss">
.zero-inspector-props-form {
width: 100%;
padding-right: 10px;
.el-divider__text {
background-color: #e9e9e9;
}
.zero-inspector-props-group {
max-height: 500px;
}
}
.script-config-dialog {
height: 350px;
}
</style> </style>
\ No newline at end of file
<template>
<el-dialog
:title="$t('Store editor')"
width="80vw"
:visible.sync="visible"
:append-to-body="true"
:close-on-click-modal="false"
:show-close="false"
:close-on-press-escape="false"
custom-class="store-editor-dialog"
>
<div class="wrapper">
<el-tabs v-model="tab" type="border-card" class="tabs">
<el-tab-pane :label="$t('Store')" name="exp">
<monaco-editor
v-if="showEditor && tab === 'exp'"
class="editor"
v-model="store.exp"
language="javascript"
:options="monacoEditorOptions"
/>
</el-tab-pane>
<el-tab-pane :label="$t('Computed')" name="computed">
<el-table class="computed-editor" :data="store.computed" height="100%" stripe size="mini">
<el-table-column type="expand">
<template slot-scope="scope">
<monaco-editor
class="editor"
v-model="scope.row.script"
language="javascript"
:options="monacoEditorOptions"
/>
</template>
</el-table-column>
<el-table-column
prop="name"
:label="$t('Name')">
<template slot-scope="scope">
<el-input v-model="scope.row.name" size="mini"/>
</template>
</el-table-column>
<el-table-column
width="50"
:label="$t('Operate')">
<template slot-scope="scope">
<el-button circle size="mini" type="danger" icon="el-icon-delete" plain
@click="toDeleteItem(scope.$index)"/>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
</div>
<div slot="footer" class="dialog-footer">
<div>
<el-button v-show="tab === 'computed'" size="mini" @click="onAdd">{{$t('Add')}}</el-button>
</div>
<div>
<el-popconfirm @onConfirm="clickClose" placement="top"
:title="$t('Are you sure to close?')">
<el-button slot="reference" size="mini">{{ $t("Close") }}</el-button>
</el-popconfirm>
<el-button class="save-button" type="primary" size="mini" @click="clickSave">{{ $t("Save") }}
</el-button>
</div>
</div>
</el-dialog>
</template>
<script>
import {mapMutations} from 'vuex';
import MonacoEditor from "vue-monaco";
import {clonePureObj, monacoEditorOptions} from "../../../../utils";
const storeExp = `return {
}
`;
export default {
name: "StoreEditorDialog",
components: {MonacoEditor},
data() {
return {
visible: false,
tab: 'exp',
monacoEditorOptions,
showEditor: false,
store: {},
}
},
computed: {
},
methods: {
async edit(type, view) {
this.view = view;
console.log(view.storeExp);
this.store = view.store ? clonePureObj(view.store) : {
exp: storeExp,
computed: [],
};
this.visible = true;
this.$nextTick(()=>{
this.showEditor = true;
this.tab = type;
});
},
onAdd() {
this.store.computed.push({
name: '',
script: '',
});
},
onDelete(index) {
this.store.computed.splice(index, 1);
},
toDeleteItem(index) {
this.$confirm(this.$t('Are you sure to delete this item'), this.$t('Alert'), {
confirmButtonText: this.$t('Confirm'),
cancelButtonText: this.$t('Cancel'),
type: 'warning'
}).then(() => {
this.onDelete(index);
}).catch((e) => {
});
},
clickSave() {
this.modifyViewStore({
view: this.view,
store: this.store,
});
this.visible = false;
},
clickClose() {
this.visible = false;
},
...mapMutations(['modifyViewStore'])
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<div class="scripts-config-dialog"></div>
</template>
<script>
export default {
}
</script>
<style lang="scss">
.scripts-config-dialog{
position: absolute;
width: 100%;
}
</style>
<template> <template>
<div class="zero-inspector-props-form" v-if="activeComponent.uuid"> <div class="zero-inspector-props-form" v-if="activeComponent.uuid">
<el-scrollbar class="scrollbar" wrap-class="wrap-x-hidden"> <el-form class="form" ref="form" size="mini" :model="form" label-width="100px" @submit.native.prevent>
<el-form ref="form" size="mini" :model="form" label-width="100px" @submit.native.prevent> <el-scrollbar class="scrollbar" wrap-class="wrap-x-hidden" view-class="pr-10px">
<el-collapse accordion v-if="activeComponent.scripts && activeComponent.scripts.length"> <el-collapse accordion v-if="activeComponent.scripts && activeComponent.scripts.length">
<template v-for="(script, index) in activeComponent.scripts"> <template v-for="(script, index) in activeComponent.scripts">
<el-collapse-item :title="getScriptName(script.script)" :key="script + index"> <el-collapse-item :title="getScriptName(script.script)" :key="script + index">
<template v-for="(p, key) in getScriptOptions(script.script)"> <props-editor
<el-form-item :key="activeComponent.uuid + index + key" :label="p.alias|| key"> ref="propsEditor"
<dynamic-component :component-value="getScriptValue(p, key, index)" :component-props="getScriptProps(p, index)" :component-type="getScriptType(p, index)" @onChange="v => handleScriptChange(index, key, v)"></dynamic-component> :editable="true"
</el-form-item> :data="script.props"
</template> :meta="getScriptOptions(script.script)"
@input="(value, container, propName)=>onInput(index, value, propName)"
/>
<el-form-item label=""> <el-form-item label="">
<el-button @click="deleteNodeScript(index)">删除</el-button> <el-button @click="deleteNodeScript(index)" type="danger" plain>删除</el-button>
</el-form-item> </el-form-item>
</el-collapse-item> </el-collapse-item>
</template> </template>
</el-collapse> </el-collapse>
<div style="padding-top: 15px;text-align: center;"> <div class="add-item-bar">
<el-dropdown trigger="click" @command="handleAddScript" placement="top" size="small"> <el-dropdown trigger="click" @command="handleAddScript" placement="bottom" size="small">
<el-button size="mini">{{$t('Add')}}</el-button> <el-button size="mini" type="primary" plain>{{$t('Add')}}</el-button>
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="(script, key) of scriptPackages" :command="script.id" :key="key">{{script.name}}</el-dropdown-item> <el-dropdown-item v-for="(script, key) of scriptPackages" :command="script.id" :key="key">
{{script.name}}
</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</div> </div>
</el-form>
</el-scrollbar> </el-scrollbar>
</el-form>
</div> </div>
</template> </template>
<script> <script>
import { mapGetters, mapState } from 'vuex'; import {mapGetters, mapState} from 'vuex';
import _ from 'lodash'; import _ from 'lodash';
import dynamicComponent from '../components/dynamicComponent'; import PropsEditor from "../../../components/PropsEditor";
const scriptTypeMap = { export default {
number: {
component: 'el-input-number',
props: {
size: 'mini'
}
},
string: {
component: 'el-input'
},
boolean: {
component: 'el-switch',
props: {
width: 40
}
},
color: {
component: 'el-color-picker',
props: {
'show-alpha': true
}
},
select: {
component: 'el-select',
props: {
slotComponent: 'el-option'
}
}
};
export default {
name: 'ScriptsTab', name: 'ScriptsTab',
components: { 'dynamic-component': dynamicComponent }, components: {PropsEditor},
data() { data() {
return { return {
form: { form: {
...@@ -77,9 +51,7 @@ export default { ...@@ -77,9 +51,7 @@ export default {
}, },
computed: { computed: {
...mapGetters(['activeComponent', 'activeComponentCopy', 'componentList', 'scriptPackages']), ...mapGetters(['activeComponent', 'activeComponentCopy', 'componentList', 'scriptPackages']),
...mapState({ ...mapState({}),
}),
}, },
methods: { methods: {
/** /**
...@@ -92,7 +64,7 @@ export default { ...@@ -92,7 +64,7 @@ export default {
/** /**
* 事件属性发生改变 * 事件属性发生改变
*/ */
handleScriptChange(index, key, v) { onInput(index, v, key) {
let _props = {}; let _props = {};
_props[key] = v; _props[key] = v;
let _scripts = _.cloneDeep(this.activeComponent.scripts); let _scripts = _.cloneDeep(this.activeComponent.scripts);
...@@ -143,7 +115,7 @@ export default { ...@@ -143,7 +115,7 @@ export default {
}, },
getScriptOptions(id) { getScriptOptions(id) {
let _script = this.scriptPackages[id]; let _script = this.scriptPackages[id];
return _script ? _script.props : {}; return _script ? _script : {};
}, },
/** /**
* 删除节点脚本 * 删除节点脚本
...@@ -159,21 +131,9 @@ export default { ...@@ -159,21 +131,9 @@ export default {
}); });
} }
} }
}; };
</script> </script>
<style lang="scss"> <style lang="scss">
.zero-inspector-props-form {
width: 100%;
padding-right: 10px;
.el-divider__text {
background-color: #e9e9e9;
}
.zero-inspector-props-group {
max-height: 500px;
}
}
.script-config-dialog {
height: 350px;
}
</style> </style>
\ No newline at end of file
<template> <template>
<div class="tool-bar"> <div class="tool-bar">
<sample-menu :data="menu" @click-menu="clickMenu"/> <sample-menu :data="menu" @click-menu="clickMenu"/>
<div style="flex: 1"></div>
<div class="right-part"> <div class="right-part">
<span> <span>
[{{project.name}}] [{{project.name}}]
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
ref="tree" ref="tree"
:data="views" :data="views"
:props="defaultProps" :props="defaultProps"
:expand-on-click-node="false" :expand-on-click-node="true"
:default-expanded-keys="expandedKeys" :default-expanded-keys="expandedKeys"
draggable draggable
node-key="uuid" node-key="uuid"
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
> >
<div slot-scope="{ node, data }" class="tree-node"> <div slot-scope="{ node, data }" class="tree-node">
<div class="node-name" > <div class="node-name" >
<i v-show="Object.keys(iconMap).includes(data.type)" :class="iconMap[data.type]" style="color:#9b82e3"></i>
{{data.name}} {{data.name}}
</div> </div>
...@@ -92,6 +93,10 @@ ...@@ -92,6 +93,10 @@
}, },
expandedKeys: [], expandedKeys: [],
nodeFilterPresets: this.$t('nodeFilterPresets'), nodeFilterPresets: this.$t('nodeFilterPresets'),
iconMap: {
image: 'el-icon-picture',
label: 'el-icon-edit-outline'
}
}; };
}, },
mounted() { mounted() {
...@@ -217,6 +222,8 @@ ...@@ -217,6 +222,8 @@
* 点击左侧视图列表 * 点击左侧视图列表
*/ */
handleNodeClick(data, node) { handleNodeClick(data, node) {
console.log('handleNodeClick');
this.$store.dispatch('activeComponent', {data, node}); this.$store.dispatch('activeComponent', {data, node});
}, },
toAddView() { toAddView() {
......
...@@ -434,12 +434,43 @@ ...@@ -434,12 +434,43 @@
let hint = 'pn_' + process.uuid === key; let hint = 'pn_' + process.uuid === key;
processNode.setActive(hint); processNode.setActive(hint);
if (hint && this.selectedProcessNode !== processNode) { if (hint && this.selectedProcessNode !== processNode) {
// 相关联的线点亮
this.setContactLine(process);
this.selectedProcessNode = processNode; this.selectedProcessNode = processNode;
this.$emit('select-process-node', process); this.$emit('select-process-node', process);
} }
} }
} }
} }
},
setContactLine(process) {
let preArr = [];
let _fetchNode = (_uuid, type) => {
Object.keys(this.lines).filter(_sliceKey => !preArr.includes(_sliceKey)).map(key => {
let itemLine = this.lines[key];
if(type === 'pre') {
if(itemLine.next && itemLine.next.uuid === _uuid) {
preArr.push(key)
if(itemLine.prev && itemLine.prev.uuid) {
_fetchNode(itemLine.prev.uuid, 'pre')
}
}
} else if(type === 'next'){
if(itemLine.prev && itemLine.prev.uuid === _uuid) {
preArr.push(key)
if(itemLine.next && itemLine.next.uuid) {
_fetchNode(itemLine.next.uuid, 'next')
}
}
}
})
}
_fetchNode(process._data.uuid, 'pre');
_fetchNode(process._data.uuid, 'next');
Object.keys(this.lines).map(key => {
this.$set(this.lines, key, { ...this.lines[key], onContact: preArr.includes(key)})
})
}, },
updateProcessNode(metaID) { updateProcessNode(metaID) {
this.$nextTick(() => { this.$nextTick(() => {
......
<template> <template>
<path class="line" :d="transPath" @dblclick="onDblClick"></path> <path :class="['line', {'contact': onContact}]" :d="transPath" @dblclick="onDblClick"></path>
</template> </template>
<script> <script>
...@@ -8,12 +8,15 @@ ...@@ -8,12 +8,15 @@
export default { export default {
name: "LinkLine", name: "LinkLine",
props: ['data'], props: ['data'],
created() {
this.onContact = false
},
mounted() { mounted() {
console.log(); console.log();
}, },
watch: { watch: {
'data': function (v) { 'data': function (v) {
this.onContact = v.onContact;
} }
}, },
computed: { computed: {
......
...@@ -59,6 +59,8 @@ ...@@ -59,6 +59,8 @@
@mousedown="onPinDown" @mousedown="onPinDown"
></dock-pin> ></dock-pin>
</div> </div>
<!-- 判断是否有子节点 -->
<i class="sub-mark el-icon-s-tools" v-show="meta.sub && meta.from === 'custom' && Object.keys(meta.sub).length > 0" style="color:#9b82e3;text-align: center;"></i>
</div> </div>
</foreignObject> </foreignObject>
</template> </template>
......
...@@ -4,13 +4,14 @@ ...@@ -4,13 +4,14 @@
ref="editor" ref="editor"
v-model="meta.script" v-model="meta.script"
language="javascript" language="javascript"
:options="monacoConfig" :options="monacoEditorOptions"
@editorWillMount="editorWillMount" @editorWillMount="editorWillMount"
/> />
</template> </template>
<script> <script>
import MonacoEditor from "vue-monaco"; import MonacoEditor from "vue-monaco";
import {monacoEditorOptions} from "../../../utils";
const typesUrl = [ const typesUrl = [
"http://yun.duiba.com.cn/editor/zeroing/types/types.v2.d.ts", "http://yun.duiba.com.cn/editor/zeroing/types/types.v2.d.ts",
...@@ -36,7 +37,7 @@ $ENV_PROPS$ ...@@ -36,7 +37,7 @@ $ENV_PROPS$
props: ['meta'], props: ['meta'],
data() { data() {
return { return {
monacoConfig: {}, monacoEditorOptions,
} }
}, },
mounted() { mounted() {
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<template slot="prepend">{{$t('Name')}}</template> <template slot="prepend">{{$t('Name')}}</template>
</el-input> </el-input>
<el-scrollbar class="scrollbar" wrap-class="wrap-x-hidden" view-class="scrollbar-view"> <el-scrollbar class="scrollbar" wrap-class="wrap-x-hidden" view-class="scrollbar-view">
<props-editor ref="propsEditor" :editable="editable" :linkable="true" :data="process.data" :meta="process.meta"/> <props-editor ref="propsEditor" :editable="editable" :switchable="true" mode="linkable" :data="process.data.props" :meta="process.meta"/>
</el-scrollbar> </el-scrollbar>
<div class="inside-code"> <div class="inside-code">
<el-scrollbar class="scrollbar" wrap-class="wrap-x-hidden" view-class="scrollbar-view"> <el-scrollbar class="scrollbar" wrap-class="wrap-x-hidden" view-class="scrollbar-view">
......
<template>
<component v-if="cmpValue !== null" :is="componentType" v-model="cmpValue" v-bind="componentProps" @change="v => handleChange(v)" @input="v=>handleInput(v)">
<d-slot
v-for="oitem in componentProps.options"
:is="componentProps.slotComponent"
:key="oitem.value"
:label="oitem.label || oitem.value"
:value="oitem.value"
>
</d-slot>
</component>
</template>
<script>
import swSlider from '../../../components/customSettings/slider';
import swSelect from '../../../components/customSettings/selector';
import swSource from '../../../components/customSettings/source';
export default {
components: {
swSlider,
swSelect,
swSource
},
props: {
componentValue: [String, Number, Boolean],
componentType: {
type: String,
default: ''
},
componentProps: {
type: Object,
default: () => {}
}
},
data() {
return {
cmpValue: null
};
},
mounted() {
this.cmpValue = this.componentValue;
},
watch: {
componentValue: function(val) {
this.cmpValue = val;
}
},
methods: {
/**
* 组件值发生改变
*/
handleChange(v) {
// console.log('handleChange', v);
this.$emit('onChange', v);
// let _prop = {};
// _prop[this.label] = v;
// this.$store.dispatch('modifyProperties', _prop);
},
handleInput(v) {
if (this.componentType === 'el-input') {
this.handleChange(v);
}
}
}
};
</script>
...@@ -55,13 +55,13 @@ export default { ...@@ -55,13 +55,13 @@ export default {
}, },
position() { position() {
let _props = this.activeComponentCopy.properties || {}; let _props = this.activeComponentCopy.properties || {};
const _node = properties.node; const props = properties.node.props;
// console.log('********', _props); // console.log('********', _props);
let result = { let result = {
x: _props.x || _node.x.value, x: _props.x || props.x.default,
y: _props.y || _node.y.value, y: _props.y || props.y.default,
w: _props.width || _node.width.value, w: _props.width || props.width.default,
h: _props.height || _node.height.value h: _props.height || props.height.default,
}; };
// console.log('####position', result); // console.log('####position', result);
......
...@@ -127,10 +127,10 @@ export default { ...@@ -127,10 +127,10 @@ export default {
const _node = properties.node; const _node = properties.node;
// console.log('********', _props); // console.log('********', _props);
let result = { let result = {
x: _props.x || _node.x.value, x: _props.x || _node.x.default,
y: _props.y || _node.y.value, y: _props.y || _node.y.default,
w: _props.width || _node.width.value, w: _props.width || _node.width.default,
h: _props.height || _node.height.value h: _props.height || _node.height.default
}; };
console.log('####position', result); console.log('####position', result);
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
class="editor" class="editor"
v-model="props.row.data" v-model="props.row.data"
language="json" language="json"
:options="monacoConfig" :options="monacoEditorOptions"
/> />
</template> </template>
</el-table-column> </el-table-column>
...@@ -84,7 +84,7 @@ ...@@ -84,7 +84,7 @@
<script> <script>
import {mapState, mapMutations, mapActions} from 'vuex' import {mapState, mapMutations, mapActions} from 'vuex'
import EnabledSetter from "../components/EnabledSetter"; import EnabledSetter from "../components/EnabledSetter";
import {clonePureObj} from "../../../utils"; import {clonePureObj, monacoEditorOptions} from "../../../utils";
import MonacoEditor from "vue-monaco"; import MonacoEditor from "vue-monaco";
export default { export default {
...@@ -94,9 +94,7 @@ ...@@ -94,9 +94,7 @@
return { return {
visible: false, visible: false,
mocks: [], mocks: [],
monacoConfig: { monacoEditorOptions,
}
} }
}, },
mounted() { mounted() {
......
<template> <template>
<el-dialog :title="$t('Process Search')" width="80%" :visible.sync="visible" <el-dialog :title="$t('Process Search')" width="80%" :visible.sync="visible"
:append-to-body="true" :append-to-body="true"
:close-on-click-modal="false"
custom-class="meta-search-dialog" custom-class="meta-search-dialog"
> >
<div class="wrapper"> <div class="wrapper">
......
...@@ -55,10 +55,8 @@ ...@@ -55,10 +55,8 @@
import {mapGetters} from "vuex"; import {mapGetters} from "vuex";
import copy from "copy-to-clipboard"; import copy from "copy-to-clipboard";
import { import {
getProjectSkins, getSkins,
saveSkins, saveSkin,
getTestEnvTicket,
getProdTicket,
sendDingTalk sendDingTalk
} from "../../../../src/api/polaris"; } from "../../../../src/api/polaris";
import {pxHostMapping} from "../../../utils"; import {pxHostMapping} from "../../../utils";
...@@ -109,12 +107,6 @@ ...@@ -109,12 +107,6 @@
async getSkinsList() { async getSkinsList() {
const {env} = this; const {env} = this;
if (env === "test") {
await this.getTicket(getTestEnvTicket);
} else if (env === "prod") {
await this.getTicket(getProdTicket, "prod_ticket");
}
const {pxEnv} = this.options; const {pxEnv} = this.options;
const pxPid = this.pxPid = pxEnv[env]; const pxPid = this.pxPid = pxEnv[env];
...@@ -126,7 +118,7 @@ ...@@ -126,7 +118,7 @@
return; return;
} }
try { try {
const data = await getProjectSkins(pxPid, env); const data = await getSkins(pxPid, env);
if (data.success !== false) { if (data.success !== false) {
this.pxProjectName = data.name; this.pxProjectName = data.name;
this.skins = data.skins; this.skins = data.skins;
...@@ -134,7 +126,6 @@ ...@@ -134,7 +126,6 @@
// 如果是测试环境,ticket过期,则重新获取ticket // 如果是测试环境,ticket过期,则重新获取ticket
if (env === "test" && data.notLogin) { if (env === "test" && data.notLogin) {
localStorage.setItem("ticket", ""); localStorage.setItem("ticket", "");
await this.getTicket(getTestEnvTicket);
this.getSkinsList(this.pxPid); this.getSkinsList(this.pxPid);
} else if (env === "prod" && data.notLogin) { } else if (env === "prod" && data.notLogin) {
localStorage.setItem("prod_ticket", ""); localStorage.setItem("prod_ticket", "");
...@@ -194,10 +185,7 @@ ...@@ -194,10 +185,7 @@
name, name,
env: env env: env
}; };
this.$refs.SelectQADialog.show(); const {ret} = await saveSkin(data);
return;
const {ret} = await saveSkins(data);
if (ret.success !== false) { if (ret.success !== false) {
this.$message({ this.$message({
message: `操作成功`, message: `操作成功`,
...@@ -233,13 +221,6 @@ ...@@ -233,13 +221,6 @@
type: "success" type: "success"
}); });
}, },
async getTicket(fn, name = "ticket") {
let ticket = localStorage.getItem(name);
if (!ticket) {
ticket = await fn();
localStorage.setItem(name, ticket);
}
},
/*getTpl(id) { /*getTpl(id) {
const {skins} = this; const {skins} = this;
let tpl = ""; let tpl = "";
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
class="editor" class="editor"
v-model="skin.html" v-model="skin.html"
language="html" language="html"
:options="monacoEditorOptions"
/> />
</el-form-item> </el-form-item>
</el-form> </el-form>
...@@ -49,7 +50,7 @@ ...@@ -49,7 +50,7 @@
<script> <script>
import MonacoEditor from "vue-monaco"; import MonacoEditor from "vue-monaco";
import {clonePureObj} from "../../../utils"; import {clonePureObj, monacoEditorOptions} from "../../../utils";
import ElFormItem from "../../../components/inputs/form-item"; import ElFormItem from "../../../components/inputs/form-item";
export default { export default {
...@@ -63,6 +64,7 @@ ...@@ -63,6 +64,7 @@
pxProjectName: '', pxProjectName: '',
skin: null, skin: null,
operate: 0, operate: 0,
monacoEditorOptions,
rules: { rules: {
name: [ name: [
{required: true, message: this.$t('Skin name required'), trigger: 'blur'}, {required: true, message: this.$t('Skin name required'), trigger: 'blur'},
......
...@@ -89,7 +89,7 @@ ...@@ -89,7 +89,7 @@
import EnabledSetter from "../components/EnabledSetter"; import EnabledSetter from "../components/EnabledSetter";
import MonacoEditor from "vue-monaco"; import MonacoEditor from "vue-monaco";
import PxConfigPopover from "../components/PxConfigPopover"; import PxConfigPopover from "../components/PxConfigPopover";
import {getProdTicket, getProjectSkins, getTestEnvTicket, saveSkins} from "../../../api/polaris"; import {getSkins, saveSkin} from "../../../api/polaris";
import {playWaiting, pxHostMapping} from "../../../utils"; import {playWaiting, pxHostMapping} from "../../../utils";
import copy from "copy-to-clipboard"; import copy from "copy-to-clipboard";
import PxSkinEditor from "./PxSkinEditor"; import PxSkinEditor from "./PxSkinEditor";
...@@ -171,12 +171,6 @@ ...@@ -171,12 +171,6 @@
async getSkinsList() { async getSkinsList() {
const {env} = this; const {env} = this;
if (env === "test") {
await this.getTicket(getTestEnvTicket);
} else if (env === "prod") {
await this.getTicket(getProdTicket, "prod_ticket");
}
const {pxEnv} = this.options; const {pxEnv} = this.options;
const pxPid = this.pxPid = pxEnv[env]; const pxPid = this.pxPid = pxEnv[env];
...@@ -188,45 +182,19 @@ ...@@ -188,45 +182,19 @@
return; return;
} }
try { try {
const data = await getProjectSkins(pxPid, env); const data = await getSkins(pxPid, env);
if (data.success !== false) {
this.pxProjectName = data.name; this.pxProjectName = data.name;
this.skins = data.skins; this.skins = data.skins;
} else {
// 如果是测试环境,ticket过期,则重新获取ticket
if (env === "test" && data.notLogin) {
localStorage.setItem("ticket", "");
await this.getTicket(getTestEnvTicket);
this.getSkinsList(this.projectId);
} else if (env === "prod" && data.notLogin) {
localStorage.setItem("prod_ticket", "");
this.$message({
message: this.$t('Online ticket is invalid'),
type: "info"
});
this.pxProjectName = '';
this.skins = [];
} else {
this.$message({
message: data.message,
type: "error"
});
this.pxProjectName = '';
this.skins = [];
}
}
} catch (e) { } catch (e) {
this.pxProjectName = ''; this.invalidTicketNotice();
this.skins = [];
throw new Error(e.message);
} }
}, },
async getTicket(fn, name = "ticket") { async invalidTicketNotice(){
let ticket = localStorage.getItem(name); const {env} = this;
if (!ticket) { this.pxProjectName = '';
ticket = await fn(); this.skins = [];
localStorage.setItem(name, ticket); await this.$alert(this.$t('SSO is invalid'));
} window.open('/sso/login?env=' + env, '_blank');
}, },
async saveSkin(skin, operate) { async saveSkin(skin, operate) {
const { const {
...@@ -234,16 +202,18 @@ ...@@ -234,16 +202,18 @@
pxPid, pxPid,
} = this; } = this;
const {id, html, name, type} = skin; const {id, html, name, type} = skin;
const data = { const params = {
projectId: pxPid, projectId: pxPid,
type: (operate + 1).toString(), operate: operate + 1,
currentHtmlType: type, type,
skinId: id, id,
tpl: html, html,
name, name,
env, env,
isProd: true,
qas: [921],
}; };
const {ret} = await playWaiting(saveSkins(data), this.$t('In processing')); const {ret} = await playWaiting(saveSkin(params), this.$t('In processing'));
if (ret.success !== false) { if (ret.success !== false) {
this.$message({ this.$message({
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
<div class="mapping-list"> <div class="mapping-list">
<div class="list" v-if="customMeta"> <div class="list" v-if="customMeta">
<div class="item" v-for="(item, index) in customMeta.assets" :key="index"> <div class="item" v-for="(item, index) in customMeta.assets" :key="index">
<span class="name">{{item.name}}</span> <span class="name">{{item.name}}({{assetSize(item.url)}})</span>
<div class="diff"> <div class="diff">
<div class="side left"> <div class="side left">
<span class="extname"> <span class="extname">
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
</span> </span>
<div class="thumbnail"> <div class="thumbnail">
<img class="alpha-image-background" v-if="showThumbnail(item.ext)" :src="item.url"> <img class="alpha-image-background" v-if="showThumbnail(item.ext)" :src="item.url">
<svga-preview-view class="alpha-image-background" v-if="item.ext === '.svga'"
:max-width="100"
:max-height="100"
:src="item.url"></svga-preview-view>
</div> </div>
<el-input size="mini" v-model="item.url" readonly/> <el-input size="mini" v-model="item.url" readonly/>
</div> </div>
...@@ -28,7 +32,11 @@ ...@@ -28,7 +32,11 @@
</span>--> </span>-->
<div class="thumbnail"> <div class="thumbnail">
<img class="alpha-image-background" v-if="item.replace && showThumbnail(item.ext)" <img class="alpha-image-background" v-if="item.replace && showThumbnail(item.ext)"
:src="resolveImg(item)"> :src="resolveSrc(item)">
<svga-preview-view class="alpha-image-background" v-if="item.replace && item.ext === '.svga'"
:max-width="100"
:max-height="100"
:src="resolveSrc(item)"></svga-preview-view>
</div> </div>
<el-input size="mini" v-model="item.replace" clearable> <el-input size="mini" v-model="item.replace" clearable>
<el-button slot="append" icon="el-icon-brush" @click="onClickReplace(item)"/> <el-button slot="append" icon="el-icon-brush" @click="onClickReplace(item)"/>
...@@ -51,16 +59,17 @@ ...@@ -51,16 +59,17 @@
</template> </template>
<script> <script>
import {mapMutations, mapState, mapGetters} from 'vuex'; import {mapMutations, mapState, mapGetters, mapActions} from 'vuex';
import {fileTypeIcon} from "../../../../config"; import {fileTypeIcon} from "../../../../config";
import SelectAssetDialog from "../SelectAssetDialog"; import SelectAssetDialog from "../SelectAssetDialog";
import {clonePureObj} from "../../../../utils"; import {clonePureObj} from "../../../../utils";
import SvgaPreviewView from "../../../../components/SvgaPreviewView";
const linkScheme = 'link://'; const linkScheme = 'link://';
export default { export default {
name: "AssetMappingEditorDialog", name: "AssetMappingEditorDialog",
components: {SelectAssetDialog}, components: {SvgaPreviewView, SelectAssetDialog},
data() { data() {
return { return {
visible: false, visible: false,
...@@ -75,13 +84,14 @@ ...@@ -75,13 +84,14 @@
...mapGetters([ ...mapGetters([
'assets', 'assets',
'customPackages', 'customPackages',
'assetSize',
]) ])
}, },
methods: { methods: {
showThumbnail(ext) { showThumbnail(ext) {
return fileTypeIcon[ext] === 't'; return fileTypeIcon[ext] === 't';
}, },
resolveImg(item) { resolveSrc(item) {
let url; let url;
const replace = item.replace; const replace = item.replace;
if (replace.startsWith(linkScheme)) { if (replace.startsWith(linkScheme)) {
...@@ -107,6 +117,9 @@ ...@@ -107,6 +117,9 @@
show(data) { show(data) {
this.mid = data.id; this.mid = data.id;
this.customMeta = clonePureObj(this.customPackages[this.mid]); this.customMeta = clonePureObj(this.customPackages[this.mid]);
for(let asset of this.customMeta.assets){
this.updateAssetSize(asset.url);
}
for (let uuid in data.assetMapping) { for (let uuid in data.assetMapping) {
let asset = this.customMeta.assets.find(item => item.uuid === uuid); let asset = this.customMeta.assets.find(item => item.uuid === uuid);
...@@ -135,6 +148,7 @@ ...@@ -135,6 +148,7 @@
}, },
...mapMutations([]), ...mapMutations([]),
...mapActions(['updateAssetSize']),
} }
} }
</script> </script>
...@@ -153,11 +167,11 @@ ...@@ -153,11 +167,11 @@
flex-direction: column; flex-direction: column;
align-items: stretch; align-items: stretch;
.name{ .name {
text-align: center; text-align: center;
} }
.diff{ .diff {
position: relative; position: relative;
border: 1px solid lightgray; border: 1px solid lightgray;
border-radius: 5px; border-radius: 5px;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
<el-scrollbar class="scrollbar" wrap-class="wrap-x-hidden" <el-scrollbar class="scrollbar" wrap-class="wrap-x-hidden"
view-class="scrollbar-view"> view-class="scrollbar-view">
<props-editor v-if="data" ref="propsEditor" :data="data" :meta="meta" label-width="180px" :linkable="false"/> <props-editor v-if="data" ref="propsEditor" :data="data.props" :meta="meta" label-width="180px"/>
</el-scrollbar> </el-scrollbar>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<div></div> <div></div>
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<el-tabs style="flex: 1;height: 0;" class="tabs" v-model="activeName"> <el-tabs style="flex: 1;height: 0;" class="tabs" v-model="activeName">
<el-tab-pane v-for="(group, key, index) in packageInfos" :label="$t('dependenciesTypes')[key]" :name="key" :key="key"> <el-tab-pane v-for="(group, key, index) in packageInfos" :label="$t('dependenciesTypes')[key]" :name="key" :key="key">
<el-scrollbar v-if="editData" class="scrollbar" wrap-class="wrap-x-hidden" view-class="view package-manager"> <el-scrollbar v-if="editData" class="scrollbar" wrap-class="wrap-x-hidden" view-class="view package-manager">
<div class="mapping-list"> <div class="package-list">
<div class="list"> <div class="list">
<div class="item" v-for="packageInfo in group" :key="packageInfo.id"> <div class="item" v-for="packageInfo in group" :key="packageInfo.id">
<div style="flex: 1;"> <div style="flex: 1;">
......
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
class="editor" class="editor"
v-model="editData.tpl" v-model="editData.tpl"
language="html" language="html"
:options="monacoConfig" :options="monacoEditorOptions"
/> />
</el-form-item> </el-form-item>
</el-form> </el-form>
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
<script> <script>
import {mapState, mapGetters, mapMutations} from 'vuex'; import {mapState, mapGetters, mapMutations} from 'vuex';
import {clonePureObj} from "../../../../utils"; import {clonePureObj, monacoEditorOptions} from "../../../../utils";
import MonacoEditor from "vue-monaco"; import MonacoEditor from "vue-monaco";
export default { export default {
...@@ -72,9 +72,7 @@ ...@@ -72,9 +72,7 @@
editData: null, editData: null,
scaleMode, scaleMode,
rendererType, rendererType,
monacoConfig: { monacoEditorOptions,
},
} }
}, },
computed: { computed: {
......
...@@ -92,7 +92,6 @@ ...@@ -92,7 +92,6 @@
components: {ElFormItem, ProjectHistoryDialog, DuplicateProjectDialog, CreateProjectDialog}, components: {ElFormItem, ProjectHistoryDialog, DuplicateProjectDialog, CreateProjectDialog},
data() { data() {
return { return {
appVersion: 'v1.0.0',
currentPage: 1, currentPage: 1,
pageSize: PROJECT_PAGE_SIZE, pageSize: PROJECT_PAGE_SIZE,
searchWord: '', searchWord: '',
......
...@@ -6780,7 +6780,7 @@ promise-inflight@^1.0.1: ...@@ -6780,7 +6780,7 @@ promise-inflight@^1.0.1:
"props-compute@http://gitlab2.dui88.com/laoqifeng/props-compute.git": "props-compute@http://gitlab2.dui88.com/laoqifeng/props-compute.git":
version "1.0.0" version "1.0.0"
resolved "http://gitlab2.dui88.com/laoqifeng/props-compute.git#c676e9e12a06ccc3556101197171ee47e9ebdd3c" resolved "http://gitlab2.dui88.com/laoqifeng/props-compute.git#9c6abcccf41f8d38d3a327716060f5e7722c7c1a"
proxy-addr@~2.0.5: proxy-addr@~2.0.5:
version "2.0.5" version "2.0.5"
...@@ -8102,6 +8102,11 @@ svg-tags@^1.0.0: ...@@ -8102,6 +8102,11 @@ svg-tags@^1.0.0:
resolved "https://registry.npm.taobao.org/svg-tags/download/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" resolved "https://registry.npm.taobao.org/svg-tags/download/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764"
integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=
svgaplayerweb@^2.3.0:
version "2.3.0"
resolved "https://registry.npmjs.org/svgaplayerweb/-/svgaplayerweb-2.3.0.tgz#417e2620e68f9ba616037a0feeb93354cb63d545"
integrity sha512-o4hcgA3mW0rmt8n9/z8NXrPGhPnmLndKOLoGAVL+nd6S+aOIojDpnZ4nK3PAw9F4xrOA06FqI3VkEsVHVLNYVA==
svgo@^1.0.0: svgo@^1.0.0:
version "1.3.2" version "1.3.2"
resolved "https://registry.npm.taobao.org/svgo/download/svgo-1.3.2.tgz?cache=0&sync_timestamp=1572433263159&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsvgo%2Fdownload%2Fsvgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" resolved "https://registry.npm.taobao.org/svgo/download/svgo-1.3.2.tgz?cache=0&sync_timestamp=1572433263159&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsvgo%2Fdownload%2Fsvgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167"
......
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