Commit fa933d54 authored by rockyl's avatar rockyl

增加打包管理

parent f42544b9
<template>
<div class="menu">
<el-badge class="menu-item" v-for="(item, key) of data" :key="key" is-dot :hidden="!menuBadge(key)">
<div class="menu-item" v-for="(item, key) of data">
<el-link @click="clickItem(key)" :icon="item.icon" :disabled="item.disabled">
{{item.label || ''}}
<el-badge is-dot :hidden="!menuBadge(key)">
{{item.label || ''}}
</el-badge>
</el-link>
</el-badge>
<el-dropdown v-if="item.sub" trigger="click" placement="top" size="mini" @command="onSubCommand">
<i class="el-icon-arrow-down el-icon--right"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="(subItem, key) in item.sub" :command="key" :key="key">{{subItem}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
......@@ -25,7 +33,10 @@
methods: {
clickItem(key) {
this.$emit('click-menu', key);
}
},
onSubCommand(command){
this.$emit('click-menu', command);
},
}
}
</script>
......
......@@ -6,10 +6,13 @@
"Refresh": "刷新",
"Still Close": "直接关闭",
"Save": "保存",
"Pack": "打包",
"Save And Preview": "保存并预览",
"Save And Close": "保存并关闭",
"Reset": "重置",
"Copy": "复制",
"Time": "时间",
"Remark": "备注",
"Assets": "素材",
"Version": "版本",
"Paste same level":"粘贴(同级)",
......@@ -178,6 +181,10 @@
"All versions": "全部版本",
"Dependencies missing": "依赖缺失",
"missingDependenciesNotice": "<i class=\"el-icon-warning\"></i>依赖缺失,请到【<span style=\"font-weight: bold,\">详情>包管理</span>】进行安装",
"Pack manager": "打包管理",
"Publish config": "发布配置",
"Publish to projectx": "发布到星速台",
"Are sure to delete this item?": "确定要删除这条记录吗?",
"eventGroup": {
"in": "接收",
"out": "派发"
......@@ -192,8 +199,11 @@
"preview-fast": {
"label": "预览"
},
"publish": {
"label": "发布"
"pack": {
"label": "打包",
"sub": {
"pack-manager": "打包管理"
}
},
"mock": {
"label": "Mock"
......
......@@ -3,10 +3,10 @@
*/
import Vue from "vue"
import JSZip from "jszip"
import {projectApi, editorApi} from "../../api"
import {editorApi, projectApi} from "../../api"
import path from "path"
import generateUUID from "uuid/v4"
import {getCmpProps, flattenViews, getCmpByUUID} from '../../utils/common'
import {flattenViews, getCmpByUUID, getCmpProps} from '../../utils/common'
import {clonePureObj, getMockServeEnabled, saveAs} from "../../utils"
import {template} from "../../template"
import events from "@/global-events"
......@@ -15,11 +15,12 @@ import {addBehavior, deleteProcessMeta, findProcess} from "./behavior"
import db from "../../utils/db-storage"
import {preprocess} from "../../views/Preview/preview-preprocess"
import {fillLastVersion, packageStore} from "./package"
import {packageStore} from "./package"
import {fetchApi} from "../../api/common"
import {toZeroing} from "psd-parse-web"
const storeName = 'project'
const storeName = 'project';
const psStoreName = 'pack-history';
const defaultOptions = {
pageTitle: 'no title',
......@@ -743,14 +744,31 @@ export const projectStore = {
commit('replaceAsset', {uuid, url: result[0].url,});
return failedList;
},
async packProject({state}, debug) {
async packProject({state, dispatch}, params) {
let debug = false;
let packedAssets;
if (!debug) {
packedAssets = await packAssets(state.data.assets);
}
const result = await projectApi.pack(state.id, debug, packedAssets);
console.log(result);
return result;
const packResult = await projectApi.pack(state.id, debug, packedAssets);
console.log(packResult);
const {tpl, tplUrl} = packResult;
await db.set(psStoreName, {
pid: state.id,
time: Date.now(),
packResult: {tpl, tplUrl},
remark: params.remark,
});
return packResult;
},
async getPackHistory({state}) {
return (await db.getAll(psStoreName, state.id, 'pid')).reverse();
},
async deletePackItem({state}, id) {
await db.remove(psStoreName, id);
},
savePreview({state, rootState, getters}) {
const {project} = getters;
......
......@@ -20,6 +20,7 @@
.menu {
flex: 1;
display: flex;
.menu-item + .menu-item {
margin-left: 10px;
......@@ -115,7 +116,7 @@
border-bottom: 1px solid $--border-color-base;
padding: 2px;
.use-checkbox{
.use-checkbox {
margin-right: 5px;
}
......@@ -297,3 +298,33 @@
}
}
}
.pack-manager-dialog {
.scrollbar {
height: 50vh;
.popover-publish{
//margin-right: 10px;
}
.pack-list > :not(*:first-child){
margin-left: 10px;
}
}
.popover-px-config{
margin-left: 10px;
}
}
.project-x-config{
.input{
flex:1;
}
.bottom-bar{
display: flex;
justify-content: space-between;
margin-top: 10px;
}
}
......@@ -57,18 +57,6 @@
display: flex;
flex-direction: column;
.popover-remark {
width: 100%;
display: block;
.short-remark {
width: 100%;
display: block;
white-space: nowrap;
overflow: hidden;
}
}
.pagination {
align-self: flex-end;
margin-top: 5px;
......
......@@ -24,6 +24,18 @@
}
}
.popover-remark {
width: 100%;
display: block;
.short-remark {
width: 100%;
display: block;
white-space: nowrap;
overflow: hidden;
}
}
.el-tree {
background: transparent;
}
......
......@@ -8,6 +8,11 @@ const storeConfigs = [
{name: 'mock', key: 'path'},
{name: 'preview', key: 'id'},
{name: 'packages', key: 'id'},
{
name: 'pack-history', key: 'id', autoIncrement: true, indices: [
{name: 'pid', unique: false}
]
},
];
export default {
......@@ -29,9 +34,14 @@ export default {
},
createStore(stores) {
for (let {name, key} of stores) {
for (let {name, key, autoIncrement, indices} of stores) {
if (!this.db.objectStoreNames.contains(name)) {
this.db.createObjectStore(name, {keyPath: key || 'id'});
let store = this.db.createObjectStore(name, {keyPath: key || 'id', autoIncrement: !!autoIncrement});
if (indices) {
for (let {name, unique} of indices) {
store.createIndex(name, name, {unique})
}
}
}
}
},
......@@ -52,11 +62,16 @@ export default {
})
},
getAll(storeName) {
getAll(storeName, id, index) {
return new Promise((resolve, reject) => {
let request = this.db.transaction([storeName])
.objectStore(storeName)
.getAll();
let store = this.db.transaction([storeName]).objectStore(storeName);
let request;
if (index) {
let indexStore = store.index(index);
request = indexStore.getAll(id);
} else {
request = store.getAll();
}
request.onerror = function (event) {
reject(event.target.error);
......@@ -124,7 +139,7 @@ export default {
});
},
clear(storeName){
clear(storeName) {
return new Promise((resolve, reject) => {
let request = this.db.transaction([storeName], 'readwrite')
.objectStore(storeName)
......
......@@ -13,7 +13,7 @@
</split-panes>
<bottom-bar/>
<details-dialog ref="dialogsDialog"/>
<pack-result-dialog ref="packResultDialog"/>
<pack-manager-dialog ref="packManagerDialog" @pack="pack"/>
<mock-editor-dialog ref="mockEditorDialog"/>
<code-sync-serve-dialog ref="codeSyncServeDialog"/>
<missing-packages-dialog ref="missingPackagesDialog"/>
......@@ -31,7 +31,6 @@
import DetailsDialog from "./Editor/dialogs/DetailsDialog";
import {openPreview, playWaiting} from "../utils";
import i18n from "../i18n";
import PackResultDialog from "./Editor/dialogs/PackResultDialog";
import events from "@/global-events.js"
import db from "../utils/db-storage";
import MockEditorDialog from "./Editor/dialogs/MockEditorDialog";
......@@ -39,15 +38,16 @@
import BottomBar from "./Editor/BottomBar";
import CodeSyncServeDialog from "./Editor/dialogs/CodeSyncServeDialog";
import MissingPackagesDialog from "./Editor/dialogs/MissingPackagesDialog";
import PackManagerDialog from "./Editor/dialogs/PackManagerDialog";
export default {
name: 'Editor',
components: {
PackManagerDialog,
MissingPackagesDialog,
CodeSyncServeDialog,
BottomBar,
MockEditorDialog,
PackResultDialog,
DetailsDialog,
Assets,
Playground,
......@@ -187,7 +187,7 @@
inputPattern: /^.{0,256}$/,
}).then(
({value}) => {
remark = value;
remark = this.lastSaveRemark = value;
}
).catch((action) => {
cancel = true;
......@@ -220,8 +220,11 @@
case 'preview-fast':
this.preview();
break;
case 'publish':
await this.publish();
case 'pack':
await this.pack();
break;
case 'pack-manager':
this.$refs.packManagerDialog.show();
break;
case 'mock':
this.$refs.mockEditorDialog.show();
......@@ -254,14 +257,9 @@
break;
}
},
async publish() {
this.pack();
},
async pack(debug = false) {
async pack() {
let cancel;
if (!debug) {
cancel = await this.saveProject(false);
}
cancel = await this.saveProject(false);
if (cancel) {
return;
}
......@@ -270,28 +268,16 @@
text: this.$t('Packing'),
});
try {
const packResult = await this.packProject(debug);
await this.packProject({
remark: this.lastSaveRemark,
});
this.$message({
message: this.$t('Pack project successfully'),
type: 'success',
duration: 500,
});
if (debug) {
openPreview(packResult);
} else {
this.$refs.packResultDialog.show(packResult);
}
/*this.$confirm(this.$t('Pack project successfully'), this.$t('Alert'), {
confirmButtonText: this.$t('Open in new tab'),
cancelButtonText: this.$t('Close'),
type: 'warning'
}).then(() => {
setTimeout(()=>{
window.open(tplUrl, 'blank');
}, 500);
}).catch(() => {
});*/
this.$refs.packManagerDialog.show();
} catch (e) {
console.log(e);
this.$message({
......
......@@ -29,8 +29,8 @@
const menuConfig = this.$t('menu');
let menu = {};
for (let key of Object.keys(menuConfig)) {
let item = menuConfig[key];
menu[key] = {label: item.label, icon: item.icon, disabled: false}
let {label, icon, sub} = menuConfig[key];
menu[key] = {label, icon, sub, disabled: false}
}
if (menu['undo']) {
menu['undo']['disabled'] = !this.project.operateStack.length || this.project.operateStack.length === this.project.stackIndex + 1
......
<template>
<el-dialog
:title="$t('Pack manager')"
width="70%"
:visible.sync="visible"
:append-to-body="true"
custom-class="pack-manager-dialog"
>
<div>
<el-scrollbar class="scrollbar" wrap-class="wrap-x-hidden" view-class="view">
<el-table :data="historyItems">
<el-table-column :label="$t('Time')" width="180px">
<template slot-scope="scope">
{{$timeFormat(scope.row.time)}}
</template>
</el-table-column>
<el-table-column :label="$t('Remark')">
<template slot-scope="scope">
<el-popover
class="popover-remark"
placement="top"
width="200"
title="版本备注"
:open-delay="500"
trigger="hover"
:content="scope.row.remark">
<span slot="reference" class="short-remark">{{scope.row.remark}}</span>
</el-popover>
</template>
</el-table-column>
<el-table-column width="180px">
<div class="pack-list" slot-scope="scope">
<el-popover
class="popover-publish"
placement="bottom"
width="400"
:title="$t('Publish to projectx')"
@show="onPopoverPublishShow"
>
<publish-view ref="popoverPublish"></publish-view>
<el-button
slot="reference"
icon="el-icon-s-promotion"
size="mini" plain
type="primary"
/>
</el-popover>
<el-button
icon="el-icon-document-copy"
size="mini" plain
type="success"
@click="copyTpl(scope.row.packResult.tpl)"
/>
<el-popconfirm :title="$t('Are sure to delete this item?')"
@onConfirm="deleteItem(scope.row.id)"
placement="top">
<el-button
slot="reference"
icon="el-icon-delete"
size="mini" plain
type="danger"
/>
</el-popconfirm>
</div>
</el-table-column>
</el-table>
</el-scrollbar>
</div>
<div slot="footer" class="dialog-footer">
<div>
<el-button type="primary" size="mini" @click="onPack">{{ $t("Pack") }}</el-button>
<el-popover
class="popover-px-config"
placement="top"
:title="$t('Projectx config')"
v-model="popoverPxConfigVisible"
@show="onPopoverPxConfigShow"
>
<projectx-config ref="pxConfig" @save="onSavePxConfig" :show-bottom-bar="true"/>
<el-button
slot="reference"
size="mini" plain>
{{$t('Publish config')}}
</el-button>
</el-popover>
</div>
<div>
<el-button size="mini" @click="onClose">{{ $t("Close") }}</el-button>
</div>
</div>
</el-dialog>
</template>
<script>
import {mapActions} from 'vuex'
import copy from 'copy-to-clipboard'
import PublishView from "./PublishView";
import {openPreview} from "../../../utils";
import ProjectxConfig from "./editors/ProjectxConfig";
export default {
name: "PackManagerDialog",
components: {ProjectxConfig, PublishView},
data() {
return {
visible: false,
popoverPxConfigVisible: false,
isSaveProjecx: false,
activeName: 'project',
historyItems: [],
}
},
methods: {
async show() {
this.visible = true;
this.historyItems = await this.getPackHistory();
},
onPopoverPublishShow(){
this.$refs.popoverPublish.active();
},
onPack() {
this.$emit('pack');
},
onClose() {
this.visible = false;
},
onSavePxConfig() {
this.popoverPxConfigVisible = false;
},
onPopoverPxConfigShow() {
this.$refs.pxConfig.edit();
},
copyTpl(tpl) {
copy(tpl);
},
async deleteItem(id) {
await this.deletePackItem(id);
this.show();
},
...mapActions([
'getPackHistory',
'deletePackItem',
]),
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<el-dialog
:title="$t('Project details')"
width="70%"
:visible.sync="visible"
@open="onOpen"
:close-on-click-modal="false"
:append-to-body="true"
:show-close="false"
custom-class="details-dialog"
>
<div>
<p>{{ $t("Pack project successfully") }}</p>
<el-collapse>
<el-collapse-item :title="$t('Check template code')" name="1">
<el-input
v-if="packResult"
type="textarea"
readonly
v-model="packResult.tpl"
:rows="10"
/>
</el-collapse-item>
</el-collapse>
<el-checkbox v-model="isSaveProjecx" style="margin: 20px 0">{{$t('Save template to projectx')}}</el-checkbox>
<projectx-options
v-if="isSaveProjecx"
:tpl="packResult.tpl"
></projectx-options>
</div>
<div slot="footer" class="dialog-footer">
<div></div>
<div>
<el-button size="mini" @click="onClose">{{ $t("Close") }}</el-button>
<el-button size="mini" @click="copy">
{{ $t("Copy template to clipboard") }}
</el-button>
<el-button size="mini" type="primary" @click="openInNewTab">
{{ $t("Open in new tab") }}
</el-button>
</div>
</div>
</el-dialog>
</template>
<script>
import copy from 'copy-to-clipboard'
import ProjectxOptions from "./ProjectxOptions";
import {openPreview} from "../../../utils";
export default {
name: "PackResultDialog",
components: {"projectx-options": ProjectxOptions},
data() {
return {
visible: false,
isSaveProjecx: false,
activeName: 'project',
packResult: null,
}
},
methods: {
show(packResult) {
this.packResult = packResult;
this.visible = true;
},
onClose() {
this.visible = false;
},
openInNewTab() {
this.visible = false;
openPreview(this.packResult);
},
copy() {
this.visible = false;
copy(this.packResult.tpl);
},
onOpen() {
},
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<div class="config">
<el-select size="small" v-model="env" placeholder="请选择环境" @change="changeenv">
<el-option v-for="(item, key) in pxEnvs" :key="key" :label="item" :value="key"></el-option>
</el-select>
<el-select @change="$parent.getTpl('')" size="small" v-model="operate" placeholder="是否新增">
<el-option v-for="(item, key) in tplOperates" :key="key" :label="item" :value="key"></el-option>
</el-select>
<el-select
@change="getTpl"
v-if="operate !== 0"
size="small"
v-model="skinId"
placeholder="选择skinID"
clearable
>
<el-option
v-for="item in skinList"
:key="item.id"
:label="`${item.type !== 0 ? item.name : '首页'}(${item.id})`"
:value="item.id"
></el-option>
</el-select>
<div v-if="operate === 0">
<el-select size="small" v-model="tplType" placeholder>
<el-option v-for="(item, key) in tplTypes" :key="key" :label="item" :value="key"></el-option>
</el-select>
<el-input v-model="name" size="small" class="name" placeholder="请输入皮肤名称"></el-input>
</div>&nbsp;
<el-button type="primary" size="small" @click="saveSkins">保存</el-button>
<el-button v-if="skinId" type="primary" size="small" @click="getUrl">获取链接</el-button>
</div>
</template>
<script>
import { mapState } from "vuex";
import copy from "copy-to-clipboard";
import {
getProjectSkins,
saveSkins,
getTestEnvTicket,
getProdTicket,
sendDingTalk
} from "../../../../src/api/polaris";
export default {
name: "ProjectxOptions",
props: {
tpl: String
},
data() {
return {
pxEnvs: this.$t("pxEnvs"),
tplOperates: this.$t("tplOperates"),
tplTypes: this.$t("tplTypes"),
env: "dev",
operate: 1,
tplType: 0,
skinId: "",
skinList: [],
projectId: "",
name: ""
};
},
computed: {
...mapState(["project"])
},
methods: {
getProjectId(env) {
const { pxEnv } = this.project.data.options;
this.projectId = pxEnv[env];
return this.projectId;
},
async changeenv(e) {
this.$parent.getTpl("");
if (e === "test") {
await this.getTicket(getTestEnvTicket);
} else if (e === "prod") {
await this.getTicket(getProdTicket, "prod_ticket");
}
const projectId = this.getProjectId(e);
this.skinId = "";
this.getSkinsList(projectId);
},
async getSkinsList(projectId) {
const { env } = this;
if (!projectId) {
this.$message({
message: `请先配置${env}环境下的projectId`,
type: "error"
});
return;
}
try {
const data = await getProjectSkins(projectId, env);
if (data.success !== false) {
this.skinList = data;
} 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: "线上tickct失效,请联系呼呼修改",
type: "info"
});
this.skinList = [];
return;
} else {
this.$message({
message: data.message,
type: "error"
});
this.skinList = [];
return;
}
}
} catch (e) {
this.skinList = [];
throw new Error(e.message);
}
},
hasIndex() {
const { skinList } = this;
return skinList.some(v => v.type === "1");
},
async saveSkins() {
const {
env,
skinId,
tplType,
operate,
projectId,
tpl,
name,
skinList
} = this;
if (operate === 1 && !skinId) {
this.$message({ message: "请选择修改的皮肤", type: "warning" });
return;
}
if (operate === 0) {
if (this.hasIndex() && tplType === 0) {
this.$message({ message: "已存在首页", type: "warning" });
return;
} else if (!name) {
this.$message({ message: "请输入要添加的皮肤名称", type: "warning" });
return;
}
}
const data = {
projectId,
type: (operate + 1).toString(),
currentHtmlType: (tplType + 1).toString(),
skinId,
tpl,
name,
env: env
};
const { ret } = await saveSkins(data);
if (ret.success !== false) {
this.$message({
message: `操作成功`,
type: "success"
});
if (this.$parent.getTpl) this.getSkinsList(projectId);
} else {
this.$message({ message: ret.message, type: "error" });
}
// 新增皮肤则重新获取皮肤列表
if (operate !== 1) {
// 2为修改,修改不需重新获取列表
this.getSkinsList(projectId);
} else if (operate !== 2) {
this.name = "";
}
},
/** 获取访问链接 */
getUrl() {
const { tplType, env, skinId, projectId, skinList } = this;
let type = 1;
skinList.forEach(skin => {
if (skin.id === skinId) {
type = skin.type;
}
});
const mapping = {
dev: "activity.m.duibadev.com.cn",
test: "activity.m.duibatest.com.cn",
prod: "https://activity.m.duiba.com.cn"
};
const url = `${mapping[env]}/projectx/${projectId}/${
type === "1" ? "index" : skinId
}.html`;
copy(url);
this.$message({
message: "链接复制成功",
type: "success"
});
},
async getTicket(fn, name = "ticket") {
let ticket = localStorage.getItem(name);
if (!ticket) {
ticket = await fn();
localStorage.setItem(name, ticket);
}
},
getTpl(id) {
const { skinList } = this;
let tpl = "";
skinList.forEach(skin => {
if (skin.id === id) {
tpl = skin.html;
}
});
this.$parent.getTpl(tpl);
}
},
async mounted() {
const { projectxConfig } = this.project.data.options;
const { env } = this;
if (projectxConfig) {
const projectId = projectxConfig[env];
this.projectId = projectId;
this.getSkinsList(projectId);
}
},
async created() {}
};
</script>
<style lang="scss">
.config {
display: flex;
.name {
display: inline-block;
width: 200px;
}
}
</style>
<template>
<div class="config">
<el-select size="small" v-model="env" placeholder="请选择环境" @change="changeEnv">
<el-option v-for="(item, key) in pxEnvs" :key="key" :label="item" :value="key"></el-option>
</el-select>
<el-select size="small" v-model="operate" placeholder="是否新增">
<el-option v-for="(item, key) in tplOperates" :key="key" :label="item" :value="key"></el-option>
</el-select>
<el-select
v-if="operate !== 0"
size="small"
v-model="skinId"
placeholder="选择skinID"
clearable
>
<el-option
v-for="item in skinList"
:key="item.id"
:label="`${item.type !== 0 ? item.name : '首页'}(${item.id})`"
:value="item.id"
></el-option>
</el-select>
<div v-if="operate === 0">
<el-select size="small" v-model="tplType" placeholder>
<el-option v-for="(item, key) in tplTypes" :key="key" :label="item" :value="key"></el-option>
</el-select>
<el-input v-model="name" size="small" class="name" placeholder="请输入皮肤名称"></el-input>
</div>&nbsp;
<el-button type="primary" size="small" @click="saveSkins">保存</el-button>
<el-button v-if="skinId" type="primary" size="small" @click="getUrl">获取链接</el-button>
</div>
</template>
<script>
import {mapState} from "vuex";
import copy from "copy-to-clipboard";
import {
getProjectSkins,
saveSkins,
getTestEnvTicket,
getProdTicket,
sendDingTalk
} from "../../../../src/api/polaris";
const mapping = {
dev: "activity.m.duibadev.com.cn",
test: "activity.m.duibatest.com.cn",
prod: "https://activity.m.duiba.com.cn"
};
export default {
name: "PublishView",
props: {
//tpl: String
},
data() {
return {
tpl: '',
pxEnvs: this.$t("pxEnvs"),
tplOperates: this.$t("tplOperates"),
tplTypes: this.$t("tplTypes"),
env: "dev",
operate: 1,
tplType: 0,
skinId: "",
skinList: [],
pxPid: "",
name: ""
};
},
computed: {
...mapState(["project"])
},
methods: {
async active(tpl) {
this.tpl = tpl;
this.$nextTick(this.getSkinsList);
},
async changeEnv(e) {
this.skinId = "";
this.getSkinsList();
},
async getSkinsList() {
const {env} = this;
if (env === "test") {
await this.getTicket(getTestEnvTicket);
} else if (env === "prod") {
await this.getTicket(getProdTicket, "prod_ticket");
}
const {pxEnv} = this.project.data.options;
const pxPid = this.pxPid = pxEnv[env];
if (!pxPid) {
this.$message({
message: `请先配置${env}环境下的projectId`,
type: "error"
});
return;
}
try {
const data = await getProjectSkins(pxPid, env);
if (data.success !== false) {
this.skinList = data;
} 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: "线上tickct失效,请联系管理员修改",
type: "info"
});
this.skinList = [];
} else {
this.$message({
message: data.message,
type: "error"
});
this.skinList = [];
}
}
} catch (e) {
this.skinList = [];
throw new Error(e.message);
}
},
hasIndex() {
const {skinList} = this;
return skinList.some(v => v.type === "1");
},
async saveSkins() {
const {
env,
skinId,
tplType,
operate,
pxPid,
tpl,
name,
skinList
} = this;
if (operate === 1 && !skinId) {
this.$message({message: "请选择修改的皮肤", type: "warning"});
return;
}
if (operate === 0) {
if (this.hasIndex() && tplType === 0) {
this.$message({message: "已存在首页", type: "warning"});
return;
} else if (!name) {
this.$message({message: "请输入要添加的皮肤名称", type: "warning"});
return;
}
}
const data = {
projectId: pxPid,
type: (operate + 1).toString(),
currentHtmlType: (tplType + 1).toString(),
skinId,
tpl,
name,
env: env
};
const {ret} = await saveSkins(data);
if (ret.success !== false) {
this.$message({
message: `操作成功`,
type: "success"
});
//if (this.$parent.getTpl) this.getSkinsList(projectId);
} else {
this.$message({message: ret.message, type: "error"});
}
// 新增皮肤则重新获取皮肤列表
if (operate !== 1) {
// 2为修改,修改不需重新获取列表
this.getSkinsList();
} else if (operate !== 2) {
this.name = "";
}
},
/** 获取访问链接 */
getUrl() {
const {tplType, env, skinId, projectId, skinList} = this;
let type = 1;
skinList.forEach(skin => {
if (skin.id === skinId) {
type = skin.type;
}
});
const url = `${mapping[env]}/projectx/${projectId}/${
type === "1" ? "index" : skinId
}.html`;
copy(url);
this.$message({
message: "链接复制成功",
type: "success"
});
},
async getTicket(fn, name = "ticket") {
let ticket = localStorage.getItem(name);
if (!ticket) {
ticket = await fn();
localStorage.setItem(name, ticket);
}
},
/*getTpl(id) {
const {skinList} = this;
let tpl = "";
skinList.forEach(skin => {
if (skin.id === id) {
tpl = skin.html;
}
});
this.$parent.getTpl(tpl);
}*/
},
};
</script>
<style lang="scss">
.config {
display: flex;
.name {
display: inline-block;
width: 200px;
}
}
</style>
<template>
<div>
<div v-for="(item, key) in pxEnvs" :key="key">
<div class="list">
<span>{{ item }}</span>
<el-icon class="el-icon-connection" />
<el-input
size="small"
v-model="editData[key]"
:placeholder="$t('Input projectx id', {envName: item})"
></el-input>
</div>
</div>
<el-checkbox
v-model="isSaveProjecx"
style="margin: 20px 0; display: block"
>{{$t('Save template to projectx')}}</el-checkbox>
<div v-if="isSaveProjecx">
<el-input class="tpl" type="textarea" rows="6" v-model="tpl" placeholder></el-input>
<projectx-options :tpl="tpl" :getTpl="getTpl"></projectx-options>
</div>
</div>
<div class="project-x-config mapping-list">
<div class="list" v-for="(item, key) in pxEnvs" :key="key">
<div class="item">
<span>{{ item }}</span>
<el-icon class="el-icon-connection"/>
<el-input
class="input"
size="mini"
v-model="editData[key]"
:placeholder="$t('Input projectx id', {envName: item})"
></el-input>
</div>
</div>
<div class="bottom-bar" v-if="showBottomBar">
<div></div>
<el-button @click="save" size="mini" type="primary">{{$t('Save')}}</el-button>
</div>
<!--<el-checkbox
v-model="isSaveProjecx"
style="margin: 20px 0; display: block"
>{{$t('Save template to projectx')}}</el-checkbox>
<div v-if="isSaveProjecx">
<el-input class="tpl" type="textarea" rows="6" v-model="tpl" placeholder></el-input>
<projectx-options :tpl="tpl" :getTpl="getTpl"></projectx-options>
</div>-->
</div>
</template>
<script>
import { mapState, mapGetters, mapMutations } from "vuex";
import ProjectxOptions from "../ProjectxOptions";
import { clonePureObj } from "../../../../utils";
export default {
name: "ProjectxConfig",
components: {
"projectx-options": ProjectxOptions
},
data() {
return {
pxEnvs: this.$t("pxEnvs"),
isSaveProjecx: false,
tpl: "",
editData: {
dev: "",
test: "",
prod: ""
}
};
},
computed: {
...mapState({
pxEnv: state => state.project.data.options.pxEnv
})
},
methods: {
...mapMutations(["modifyProjectx"]),
edit() {
this.editData = clonePureObj(this.pxEnv);
},
save() {
this.modifyProjectx(this.editData);
},
getTpl(tpl) {
this.tpl = tpl;
}
}
};
import {mapState, mapGetters, mapMutations} from "vuex";
//import ProjectxOptions from "../ProjectxOptions";
import {clonePureObj} from "../../../../utils";
export default {
name: "ProjectxConfig",
components: {
//"projectx-options": ProjectxOptions
},
props: ['showBottomBar'],
data() {
return {
pxEnvs: this.$t("pxEnvs"),
isSaveProjecx: false,
tpl: "",
editData: {
dev: "",
test: "",
prod: ""
}
};
},
computed: {
...mapState({
pxEnv: state => state.project.data.options.pxEnv
})
},
methods: {
...mapMutations(["modifyProjectx", 'makeDirty']),
edit() {
this.editData = clonePureObj(this.pxEnv);
},
save() {
this.modifyProjectx(this.editData);
this.$emit('save');
if (this.showBottomBar) {
this.makeDirty();
}
},
getTpl(tpl) {
this.tpl = tpl;
}
}
};
</script>
<style lang="scss" scoped>
.tpl {
margin-bottom: 20px;
width: 60%;
}
.list {
display: flex;
align-items: center;
margin-bottom: 20px;
span {
width: 100px;
text-align: center;
}
i {
width: 50px;
}
> div {
width: 200px;
}
}
.tpl {
margin-bottom: 20px;
width: 60%;
}
</style>
......@@ -2226,11 +2226,6 @@ code-point-at@^1.0.0:
resolved "https://registry.npm.taobao.org/code-point-at/download/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
codemirror@^5.50.0:
version "5.50.2"
resolved "https://registry.npm.taobao.org/codemirror/download/codemirror-5.50.2.tgz#32ddfe2b50193fcf573d8141c4a31d267c92b4a3"
integrity sha1-Mt3+K1AZP89XPYFBxKMdJnyStKM=
collection-visit@^1.0.0:
version "1.0.0"
resolved "https://registry.npm.taobao.org/collection-visit/download/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
......
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