Commit 71172877 authored by rockyl's avatar rockyl

素材合并功能

parent 2ad0aa92
......@@ -16,6 +16,7 @@
</style>
<script>
import events from "@/global-events.js"
import {assetScheme} from "../../../utils";
export default {
props: {
......@@ -35,7 +36,7 @@
drop(e) {
if (this.$store.state.project.dragUUID) {
console.log('native drop', this.$store.state);
this.swvalue = `asset://${this.$store.state.project.dragUUID}`
this.swvalue = assetScheme + this.$store.state.project.dragUUID
}
},
dragOver(e) {
......@@ -54,7 +55,7 @@
computed: {
url: function () {
if (this.swvalue) {
if (this.swvalue.indexOf('asset://') > -1) {
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 : '';
......
......@@ -7,7 +7,7 @@ if (process.env.NODE_ENV === 'development') {
//API_HOST = '//10.10.95.74:7777';
//API_HOST = '//192.168.1.16:7777';
//API_HOST = '//10.10.92.100:7777';
//API_HOST = '//192.168.0.106:7777';
//API_HOST = '//192.168.0.105:7777';
//API_HOST = '//localhost:3002';
API_HOST = window.__data.apiHost;
//API_HOST = '';
......
......@@ -157,7 +157,8 @@
"Confirm to publish": "确定发布吗?",
"Are you sure to delete this process?": "确定删除这对应的过程吗",
"Are you sure to delete it's process": "确定删除这对应的过程吗",
"Are you sure to delete this asset": "确定删除这个素材吗",
"Are you sure to delete this asset?": "确定删除这个素材吗",
"Are you sure to combine those assets?": "确定合并这些素材吗",
"Are you sure to delete all assets": "确定删除全部素材吗",
"Are you sure to delete this item": "确定删除这一项吗",
"Rename asset": "重命名素材",
......@@ -341,5 +342,10 @@
"process": "过程库",
"script": "脚本库",
"custom": "模块库"
},
"assetItemMenu": {
"rename": "重命名",
"replace": "替换",
"combine": "合并"
}
}
\ No newline at end of file
......@@ -37,6 +37,7 @@ export default new Vuex.Store({
'addAsset',
'deleteAsset',
'deleteAllAssets',
'combineAssets',
'modifyAsset',
'importView',
'importAssets',
......
......@@ -7,7 +7,7 @@ import {editorApi, projectApi} from "../../api"
import path from "path"
import generateUUID from "uuid/v4"
import {flattenViews, getCmpByUUID, getCmpProps} from '../../utils/common'
import {clonePureObj, findProcess, getMockServeEnabled, saveAs, traverseViewNode} from "../../utils"
import {assetScheme, clonePureObj, findProcess, getMockServeEnabled, saveAs, traverseViewNode} from "../../utils"
import {template} from "../../template"
import events from "@/global-events"
import {packImages} from "../../utils/sheet-pack"
......@@ -419,6 +419,26 @@ export const projectStore = {
importAssets(state, assets) {
state.data.assets.push(...assets);
},
combineAssets(state, {targetAsset, selectedAssets}) {
//todo 需要遍历所有节点查找使用并替换
const assets = state.data.assets;
let targetAssetUrl = assetScheme + targetAsset.uuid;
let replaceAssetUrls = [];
for (let asset of selectedAssets) {
if (asset !== targetAsset) {
replaceAssetUrls.push(assetScheme + asset.uuid);
assets.splice(assets.indexOf(asset), 1);
}
}
traverseViewNode(state.data.views, function (node) {
let properties = node.properties;
for (let key in properties) {
if (properties[key] && replaceAssetUrls.includes(properties[key])) {
properties[key] = targetAssetUrl;
}
}
});
},
addAsset(state, {url, file}) {
const ext = path.extname(file.name);
state.data.assets.push({
......@@ -680,7 +700,7 @@ export const projectStore = {
// 设置image类型节点的原图高宽度
if (!_props.imageWidth || !_props.imageHeight) {
let _url = _props.source; //_source.value;
if (_url.indexOf('asset://') === 0) {
if (_url.indexOf(assetScheme) === 0) {
let uuid = _url.split('//')[1];
let asset = state.data.assets.find(a => a.uuid === uuid);
_url = asset ? asset.url : _url;
......
......@@ -112,13 +112,9 @@
bottom: 1px;
display: flex;
.el-button + .el-button{
.delete-button{
margin-left: 2px;
}
.el-button {
padding: 2px;
}
}
}
......
import _ from 'lodash';
import properties from './properties';
import {assetScheme} from "./index";
// 属性的计算方法
const propsComputeRules = {
......@@ -199,7 +200,7 @@ export const styles = {
let resultObj = {};
_.forIn(obj, (value, key) => {
if (key === 'source' && value.indexOf('asset://') === 0) {
if (key === 'source' && value.indexOf(assetScheme) === 0) {
let uuid = value.split('//')[1];
let asset = project.data.assets.find(a => a.uuid === uuid);
value = asset ? asset.url : '';
......
......@@ -37,6 +37,7 @@ export const pxHostMapping = {
* @type {string}
*/
export const nodeScheme = 'node://';
export const assetScheme = 'asset://';
/**
* 弹出错误消息
......
......@@ -3,14 +3,16 @@
<slot name="first"></slot>
<file-item v-for="(asset, index) in assets" :class="{select: isSelected(index)}" :editable="editable" :data="asset"
:key="index" @show-file-details="showFileDetails(asset)"
@click="onClickItem(asset)"
:combinable="combinable"
@click="onClickItem(asset, $event)"
@delete="onDeleteItem(asset)"
@combine="onCombineAssets"
/>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
import {mapGetters, mapMutations} from 'vuex';
import FileItem from "./FileItem";
export default {
......@@ -28,6 +30,16 @@
}
},
computed: {
selectedAssets() {
let assets = [];
for(let index of this.selectedIndices){
assets.push(this.assets[index]);
}
return assets;
},
combinable(){
return this.selectedIndices.length > 1
},
...mapGetters([
'assets',
])
......@@ -36,25 +48,68 @@
showFileDetails(asset) {
this.$emit('show-file-details', asset);
},
onClickItem(asset) {
onClickItem(asset, event) {
this.$emit('click-item', asset);
if (event.metaKey) {
if (this.isSelected(asset)) {
this.unselectItem(asset);
} else {
this.selectItem(asset, false);
}
} else {
this.selectItem(asset);
}
},
onDeleteItem(asset) {
if (this.isSelected(this.assets.indexOf(asset))) {
if (this.isSelected(asset)) {
this.selectItem();
this.$emit('click-item', null);
}
},
selectItem(asset) {
onCombineAssets(targetAsset) {
if (this.selectedIndices.length <= 1) {
return;
}
this.$confirm(this.$t('Are you sure to combine those assets?'), this.$t('Alert'), {
showClose: false,
closeOnClickModal: false,
closeOnPressEscape: false,
confirmButtonText: this.$t('Confirm'),
cancelButtonText: this.$t('Cancel'),
type: 'warning'
}).then(() => {
this.combineAssets({
targetAsset,
selectedAssets: this.selectedAssets
});
this.selectItem(targetAsset);
}).catch((e) => {
});
},
selectItem(asset, unselectAll = true) {
if (unselectAll) {
this.selectedIndices.splice(0);
}
if (asset) {
this.selectedIndices.push(this.assets.indexOf(asset));
}
},
isSelected(index) {
return this.selectedIndices.includes(index);
unselectItem(asset) {
let sIndex = this.assets.indexOf(asset);
this.selectedIndices.splice(this.selectedIndices.indexOf(sIndex), 1);
},
isSelected(item) {
let index;
if (typeof item === 'object') {
index = this.assets.indexOf(item);
} else {
index = item;
}
return this.selectedIndices.includes(index);
},
...mapMutations(['combineAssets']),
}
}
</script>
......
......@@ -7,11 +7,32 @@
class="thumbnail alpha-image-background" :src="thumbnailUrl"
alt="thumb" @dblclick="onDbclick()">
<div v-if="editable" class="operate-bar">
<el-button circle size="mini" type="success" icon="icon-upload" @dblclick.native.stop
@click="onClickReplace"/>
<el-button circle size="mini" type="success" icon="el-icon-edit" @dblclick.native.stop @click="onClickEdit"/>
<el-button circle size="mini" type="danger" icon="el-icon-delete" @dblclick.native.stop
@click="onClickDelete"/>
<!--<el-button class="micro" circle plain size="mini" type="success" icon="icon-upload" @dblclick.native.stop
@click="onClickReplace"/>-->
<!--<el-button class="micro" circle plain size="mini" type="success" icon="el-icon-edit" @dblclick.native.stop @click="onClickEdit"/>-->
<el-dropdown size="mini" trigger="click" placement="top" @command="onMoreMenu">
<el-button circle size="mini" class="micro" type="success" icon="el-icon-more" @click.stop/>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="(item, key) in assetItemMenu"
:command="key"
:key="key"
:disabled="key === 'combine' && !combinable"
>{{item}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-popconfirm class="delete-button" :title="$t('Are you sure to delete this asset?')"
@onConfirm="onClickDelete"
placement="top">
<el-button
slot="reference"
class="micro" circle size="mini"
type="danger"
icon="el-icon-delete"
@click.stop
/>
</el-popconfirm>
</div>
</div>
<div class="name">
......@@ -31,9 +52,12 @@
props: {
data: {type: Object},
editable: {type: Boolean, default: false},
combinable: {type: Boolean, default: false}
},
data() {
return {}
return {
assetItemMenu: this.$t('assetItemMenu'),
}
},
watch: {},
computed: {
......@@ -56,7 +80,7 @@
this.$emit('show-file-details', this.data);
},
onClickDelete() {
this.$confirm(this.$t('Are you sure to delete this asset'), this.$t('Alert'), {
/*this.$confirm(this.$t('Are you sure to delete this asset'), this.$t('Alert'), {
showClose: false,
closeOnClickModal: false,
closeOnPressEscape: false,
......@@ -67,9 +91,24 @@
this.$emit('delete', this.data);
this.deleteAsset(this.data.uuid);
}).catch((e) => {
});
});*/
this.$emit('delete', this.data);
this.deleteAsset(this.data.uuid);
},
onMoreMenu(command) {
switch (command) {
case 'rename':
this.editName();
break;
case 'replace':
this.replace();
break;
case 'combine':
this.$emit('combine', this.data);
break;
}
},
onClickEdit() {
editName() {
this.$prompt(this.$t('Input asset name'), this.$t('Rename asset'), {
inputValue: this.data.name,
confirmButtonText: this.$t('Confirm'),
......@@ -83,7 +122,7 @@
}).catch(() => {
});
},
onClickReplace() {
replace() {
selectFile((files) => {
let file = files[0];
this.replaceAsset({
......
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