Commit 71172877 authored by rockyl's avatar rockyl

素材合并功能

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