Commit 596fe898 authored by rockyl's avatar rockyl

菜单增加角标提示

素材项增加ext字段
素材展示层增加图片尺寸显示
素材项名字显示优化
暂时隐藏项目详情弹窗菜单
增加修改项目名功能
处理项目id不对的情况
所有路由返回home的地方由push改为replace
parent df3c7706
No preview for this file type
......@@ -42,7 +42,7 @@
this.timer = setInterval(() => {
if (this.cd <= 0) {
clearInterval(this.timer);
this.$router.push({name: 'home'});
this.$router.replace({name: 'home'});
return;
}
this.cd--;
......
<template>
<p>{{ $t('hello') }}</p>
</template>
<script>
export default {
name: 'HelloI18n'
}
</script>
<i18n>
{
"en": {
"hello": "Hello i18n in SFC!"
}
}
</i18n>
<template>
<div class="menu">
<el-link @click="clickItem(key)" v-for="(item, key) of data" :key="key" :icon="item.icon">
{{item.text}}
</el-link>
<el-badge class="menu-item" v-for="(item, key) of data" :key="key" is-dot :hidden="!menuBadge(key)">
<el-link @click="clickItem(key)" :icon="item.icon">
{{item.text}}
</el-link>
</el-badge>
</div>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
name: "SampleMenu",
props: ['data'],
data() {
return {}
},
computed: {
...mapGetters([
'menuBadge',
]),
},
methods: {
clickItem(key) {
this.$emit('click-menu', key);
......
......@@ -5,6 +5,7 @@
"Close": "Close",
"Save": "Save",
"Copy": "Copy",
"Exit": "Exit",
"Add": "Add",
"Delete": "Delete",
"Import": "Import",
......@@ -17,6 +18,7 @@
"No projects": "No projects",
"Create": "Create",
"Project details": "Project details",
"Project does not exist": "Project does not exist",
"Project name": "Project name",
"Data mapping": "Data mapping",
"Template": "Template",
......@@ -24,6 +26,9 @@
"Deleting": "Deleting…",
"Saving": "Saving…",
"Create project": "Create project",
"Rename project": "Rename project",
"Input project name": "Input project name",
"Invalid project name": "Invalid project name",
"Creating project": "Creating project…",
"Create project success": "Create project success",
"Duplicate project": "Duplicate project",
......@@ -47,11 +52,12 @@
"Are you sure to delete this asset": "Are you sure to delete this asset",
"Are you sure to delete this link": "Are you sure to delete this link",
"Rename asset": "Rename asset",
"Input asset name": "Input asset name",
"Invalid asset name": "Invalid asset name",
"Copied field to clipboard": "Copied {field} to clipboard",
"Unsaved Alert": "You are leaving, but the project is not saved. Do you want to save it?",
"menu": {
"save": "Save",
"details": "Details",
"preview": "Preview",
"publish": "Publish",
"data-mapping": "DataMapping",
......
......@@ -23,6 +23,7 @@ export default new Vuex.Store({
plugins: [
SaveToLocalPlugin({
mutationTypes: [
'modifyProject',
'addNode',
'deleteNode',
'addAsset',
......
......@@ -3,6 +3,7 @@
*/
import Vue from "vue";
import path from "path";
import {projectApi} from "../../api";
import generateUUID from "uuid/v4";
......@@ -15,9 +16,13 @@ export const projectStore = {
views: [],
assets: [],
dataMapping: [],
}
},
dirty: false,
},
mutations: {
setDirty(state, dirty = true) {
state.dirty = dirty;
},
updateProject(state, project) {
const {id, name, creator, data} = project;
state.id = id;
......@@ -37,6 +42,9 @@ export const projectStore = {
Vue.set(localData, 'dataMapping', dataMapping || []);
}
}
},
modifyProject(state,) {
},
addNode(state, {node, name, type}) {
const child = {
......@@ -58,8 +66,10 @@ export const projectStore = {
},
addAsset(state, {url, file}) {
const ext = path.extname(file.name);
state.data.assets.push({
name: file.name,
name: path.basename(file.name, ext),
ext,
url,
uuid: generateUUID(),
})
......@@ -79,9 +89,9 @@ export const projectStore = {
},
addDataMapping(state, link) {
if(link){
if (link) {
state.data.dataMapping.push(link);
}else{
} else {
state.data.dataMapping.push({
name: '',
path: '',
......@@ -104,13 +114,23 @@ export const projectStore = {
id, name, creator,
data: JSON.stringify(data),
};
},
menuBadge: (state) => (key) => {
let result = false;
switch (key) {
case 'save':
result = state.dirty;
break;
}
return result;
}
},
actions: {
saveToLocal({getters}) {
saveToLocal({getters, commit}) {
const {project} = getters;
localStorage.setItem('project-' + project.id, JSON.stringify(project));
commit('setDirty', true);
},
localVersionExist({commit}, projectID) {
let json = localStorage.getItem('project-' + projectID);
......@@ -121,15 +141,21 @@ export const projectStore = {
if (json) {
const project = JSON.parse(json);
commit('updateProject', project);
commit('setDirty', true);
}
},
deleteLocalVersion({state}, projectID) {
deleteLocalVersion({state, commit}, projectID) {
localStorage.removeItem('project-' + projectID);
commit('setDirty', false);
},
async loadFromRemote({commit, dispatch}, projectID) {
const project = await projectApi.fetchOne(projectID);
dispatch('deleteLocalVersion', projectID);
commit('updateProject', project);
if(project){
dispatch('deleteLocalVersion', projectID);
commit('updateProject', project);
}else{
throw new Error('Project does not exist')
}
},
async saveToRemote({state, dispatch, getters}) {
await projectApi.saveOne(getters.project);
......
......@@ -27,13 +27,17 @@
.file-item {
width: 60px;
padding: 5px 5px 0;
padding: 5px;
color: $--color-text-regular;
&:hover {
& > .icon > .operate-bar {
display: block;
}
& > .name > .full-name {
display: block;
}
}
.icon {
......@@ -72,14 +76,13 @@
position: relative;
margin-top: 2px;
&:hover {
& > .full-name {
display: block;
}
}
span {
word-break: break-all;
overflow:hidden;
text-overflow: ellipsis;
display:-webkit-box;
-webkit-line-clamp:2;
-webkit-box-orient:vertical;
}
.full-name {
......@@ -93,6 +96,7 @@
padding: 2px;
z-index: 2;
width: 95%;
line-height: 17px;
}
}
}
......@@ -122,6 +126,10 @@
width: 100%;
flex: 1;
}
.scrollbar-view{
padding-bottom: 5px;
}
}
}
......@@ -169,6 +177,11 @@
}
}
.image-info{
color: $__color-white;
font-size: 12px;
}
.operate-bar {
}
......
......@@ -19,10 +19,18 @@
.menu {
flex: 1;
a:not(:first-child) {
.menu-item + .menu-item {
margin-left: 10px;
}
}
.right-part{
color: $--color-text-regular;
.el-button{
padding: 2px;
}
}
}
.pane-container {
......@@ -76,3 +84,7 @@
}
}
.project-details-dialog {
}
\ No newline at end of file
......@@ -27,6 +27,7 @@
import ProjectDetailsDialog from "./Editor/dialogs/ProjectDetailsDialog";
import DataMappingDialog from "./Editor/dialogs/DataMappingDialog";
import {playWaiting} from "../utils";
import i18n from "../i18n";
export default {
name: 'Editor',
......@@ -62,13 +63,13 @@
}).then(() => {
this.loadLocalVersion(projectID);
}).catch((e) => {
if(e === 'cancel'){
if (e === 'cancel') {
this.loadRemoteVersion(projectID);
}else{
} else {
console.log(e);
}
});
}else{
} else {
this.loadRemoteVersion(projectID);
}
},
......@@ -79,6 +80,12 @@
loadRemoteVersion(projectID) {
if (projectID) {
playWaiting(this.loadFromRemote(projectID), this.$t('Preparing')).catch(e => {
this.$alert(this.$t('Project does not exist'), this.$t('Alert'), {
confirmButtonText: this.$t('Confirm'),
callback: action=>{
this.$router.replace({name: 'home'});
}
});
});
} else {
this.$router.push({name: 'home'})
......@@ -92,16 +99,20 @@
this.panesConfig[id] = configs[0].width / 100;
localStorage.panesConfig = JSON.stringify(this.panesConfig);
},
async saveProject() {
await playWaiting(this.saveToRemote(), this.$t('Saving'));
this.$message({
message: i18n.t('Save project successfully'), //因为message是异步出现,但是当路由回退的时候,this.i18n的实例已经置空,所以要用全局的i18n实例
type: 'success'
});
},
async clickMenu(menuItem) {
switch (menuItem) {
case 'save':
try {
await playWaiting(this.saveToRemote(), this.$t('Saving'));
this.$message({
message: this.$t('Save project successfully'),
type: 'success'
});
}catch (e) {}
this.saveProject();
} catch (e) {
}
break;
case 'details':
this.$refs.projectDialogsDialog.show();
......@@ -109,8 +120,31 @@
case 'data-mapping':
this.$refs.dataMappingDialog.show();
break;
case 'exit':
const {projectID} = this.$route.params;
if (await this.localVersionExist(projectID)) {
this.$confirm(this.$t('Unsaved Alert'), this.$t('Alert'), {
confirmButtonText: this.$t('Save'),
cancelButtonText: this.$t('Exit'),
type: 'warning'
}).then(() => {
try {
this.saveProject();
this.backToHome();
} catch (e) {
}
}).catch((e) => {
this.backToHome();
});
} else {
this.backToHome();
}
break;
}
},
backToHome() {
this.$router.replace({name: 'home'});
},
...mapActions([
'localVersionExist',
'loadFromLocal',
......
......@@ -4,7 +4,7 @@
<!--<div class="header-bar">
<el-link>{{$t('Upload')}}</el-link>
</div>-->
<el-scrollbar class="assets-scrollbar" wrap-class="wrap-x-hidden">
<el-scrollbar class="assets-scrollbar" wrap-class="wrap-x-hidden" view-class="scrollbar-view">
<div class="file-list">
<el-upload
class="file-uploader"
......@@ -17,7 +17,7 @@
>
<i class="el-icon-plus file-uploader-icon"></i>
</el-upload>
<file-item v-for="file in assets" :data="file" :key="file.url" @show-file-details="showFileDetails"/>
<file-item v-for="(file, index) in assets" :data="file" :key="index + '_' + file.url" @show-file-details="showFileDetails"/>
</div>
</el-scrollbar>
</div>
......@@ -55,7 +55,7 @@
},
uploadFileSuccess(response, file){
if(response.success){
console.log('upload success', response, file);
//console.log('upload success', response, file);
this.addAsset({
url: response.url,
file,
......
......@@ -21,7 +21,10 @@
<el-button slot="append" icon="el-icon-document-copy" @click="copyValue('url')"></el-button>
</el-input>
</div>
<el-image class="big-image" :src="imageUrl" fit="contain"/>
<el-image class="big-image" :src="imageUrl" fit="contain" @load="onImageLoaded"/>
<div class="image-info">
<span class="size">{{size}}</span>
</div>
<div class="operate-bar">
<el-button-group>
</el-button-group>
......@@ -41,10 +44,16 @@
return {
visible: false,
file: null,
size: '',
}
},
watch: {
file(){
this.size = '';
}
},
computed: {
imageUrl(){
imageUrl() {
return this.file.url;
},
},
......@@ -66,10 +75,10 @@
afterLeave() {
this.$emit('closed');
},
handleWrapperClick(){
handleWrapperClick() {
this.hide();
},
copyValue(field){
copyValue(field) {
copy(this.file[field]);
this.$message({
message: this.$t('Copied field to clipboard', {field}),
......@@ -77,6 +86,10 @@
duration: 700,
});
},
onImageLoaded(e) {
const {width, height} = e.target;
this.size = width + ' x ' + height;
}
}
}
</script>
......
......@@ -10,7 +10,7 @@
</div>
</div>
<div class="name">
<span>{{ellipsisName}}</span>
<span>{{data.name}}</span>
<span class="full-name">{{data.name}}</span>
</div>
</div>
......@@ -19,7 +19,6 @@
<script>
import {mapMutations} from "vuex";
import {fileTypeIcon} from "../../../config";
import path from "path";
import {strEllipsis} from "../../../utils";
export default {
......@@ -27,35 +26,27 @@
props: ['data'],
data() {
return {
ext: '',
}
},
watch: {
data() {
this.updateExt();
}
},
mounted() {
this.updateExt();
},
computed: {
fileIcon() {
return 'icon-' + fileTypeIcon[this.ext];
return 'icon-' + fileTypeIcon[this.data.ext];
},
showThumbnail() {
return fileTypeIcon[this.ext] === 't';
return fileTypeIcon[this.data.ext] === 't';
},
thumbnailUrl() {
return this.data.url;
},
ellipsisName(){
return strEllipsis(this.data.name, 14, 8);
return strEllipsis(this.data.name, 14, 5);
},
},
methods: {
updateExt() {
this.ext = path.extname(this.data.name);
},
onDbclick() {
this.$emit('show-file-details', this.data);
},
......@@ -73,7 +64,7 @@
});
},
onClickEdit() {
this.$prompt(this.$t('Input view name'), this.$t('Rename asset'), {
this.$prompt(this.$t('Input asset name'), this.$t('Rename asset'), {
inputValue: this.data.name,
confirmButtonText: this.$t('Confirm'),
cancelButtonText: this.$t('Cancel'),
......
<template>
<div class="tool-bar">
<sample-menu :data="menu" @click-menu="clickMenu"/>
<div>
[{{project.name}}]
<div class="right-part">
<span>
[{{project.name}}]
<el-button size="mini" circle icon="el-icon-edit" @click="editProjectName"/>
</span>
</div>
</div>
</template>
<script>
import {mapState, mapActions} from 'vuex'
import {mapState, mapActions, mapMutations} from 'vuex'
import SampleMenu from "../../components/SampleMenu";
export default {
......@@ -32,7 +35,24 @@
methods: {
clickMenu(menuItem) {
this.$emit('click-menu', menuItem);
}
},
editProjectName(){
this.$prompt(this.$t('Input project name'), this.$t('Rename project'), {
inputValue: this.project.name,
confirmButtonText: this.$t('Confirm'),
cancelButtonText: this.$t('Cancel'),
closeOnClickModal: false,
inputPattern: /^.{1,64}$/,
inputErrorMessage: this.$t('Invalid project name'),
}).then(({value}) => {
this.$set(this.project, 'name', value);
this.modifyProject();
}).catch(() => {
});
},
...mapMutations([
'modifyProject'
]),
}
}
</script>
......
<template>
<el-dialog :title="$t('Project details')" width="70%" :visible.sync="visible" @open="onOpen"
:close-on-click-modal="false"
:append-to-body="true">
<div class="project-details-dialog">
<el-form v-model="project">
<el-form-item prop="">
</el-form-item>
</el-form>
</div>
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="visible=false">{{$t('Cancel')}}</el-button>
<el-button size="mini" type="primary" @click="onConfirm">{{$t('Save')}}</el-button>
......@@ -10,6 +17,8 @@
</template>
<script>
import {mapState} from 'vuex';
export default {
name: "ProjectDetailsDialog",
data() {
......@@ -17,6 +26,11 @@
visible: false,
}
},
computed: {
...mapState([
'project',
]),
},
methods: {
show(){
this.visible = true;
......
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