提交 acf8042f 编写于 作者: NoSubject's avatar NoSubject

新版系统配置组件

上级 f17c379a
......@@ -100,9 +100,9 @@ o2.xDesktop.Default = new Class({
this.path = o2.session.path+"/xDesktop/$Default/";
this.node = $(node);
this.node.empty();
this.options.style = layout.config.defaultSkin || "blue";
this.initData();
this.zoom();
//this.load();
this.zoom(layout.config.scaleConfig===false ? 1 : 0);
},
initData: function(){
this.apps = {};
......@@ -135,7 +135,7 @@ o2.xDesktop.Default = new Class({
this.status.apps[appNames].isIndex = true;
this.status.forceCurrentApp = appNames;
}
if (this.status && this.status.flatStyle) this.options.style = this.status.flatStyle;
if (layout.config.skinConfig!==false && this.status && this.status.flatStyle) this.options.style = this.status.flatStyle;
},
load: function(cb){
......@@ -278,24 +278,14 @@ o2.xDesktop.Default = new Class({
oReq.withCredentials = true;
oReq.send();
// var res = new Request({
// "url": this.session.user.iconUrl,
// method: "get",
// withCredentials: true,
// onSuccess: function(response,a,s,d){
//
// }.bind(this)
// });
// res.setHeader("authorization", layout.session.user.token);
// res.send();
debugger;
if (layout.config.scaleConfig===false && this.zoomValueNode){
this.zoomValueNode.hide()
}
this.sliderNode.getLast().set("title", o2.LP.desktop.returnZoom);
this.node.loadCss(skinCss);
if (callback) callback();
// this.node.load(html, {
// "bind": {"user": this.session.user}
// }, function(){});
}.bind(this));
},
......
......@@ -6,7 +6,6 @@
font-weight: bold;
}
@font-face {
font-family: 'o2SystemConfig';
src:
......
......@@ -116,6 +116,7 @@ o2.xApplication.systemconfig.LP = {
"_uiConfig": {
"baseConfig": "基本配置",
"menuConfig": "主菜单配置",
"lnkConfig": "侧边栏配置",
"userConfig": "用户界面配置",
"openStatus": "进入系统",
......@@ -129,6 +130,32 @@ o2.xApplication.systemconfig.LP = {
"skinConfigInfo": "是否允许用户个性化修改修改系统皮肤",
"skinDefault": "系统默认皮肤",
"skinDefaultInfo": "设置系统默认皮肤色系",
"scaleConfig": "是否允许缩放",
"scaleConfigInfo": "是否允许用户个性化设置系统显示的缩放比例",
"defaultMenuInfo": "保存为默认菜单设置后,未进行个性化菜单设置的用户,会按此设置展现菜单。",
"forceMenuInfo": "保存为强制菜单设置后,所有的用户都会按此设置展现菜单,个性化设置将会失效。",
"userMenuInfo": "所有用户的个性化菜单设置将被清除,以默认方式展现菜单。",
"defaultMenu": "默认菜单配置",
"forceMenu": "强制菜单配置",
"userMenu": "用户个性化菜单配置",
"saveMenu": "保存配置",
"clearMenu": "清除配置",
"loadMenu": "载入配置",
"clearUserMenu": "清除配置",
"menu": {
"application": "应用",
"process": "流程",
"cms": "信息",
"query": "数据",
"defaultMenu": "恢复默认菜单状态"
}
}
}
......@@ -55,7 +55,6 @@ const contentComponent = computed(() => {
border-radius: 4px;
overflow: auto;
display: flex;
flex-direction: column;
text-align: left;
}
</style>
......@@ -63,7 +62,7 @@ const contentComponent = computed(() => {
.systemconfig_title{
height: 40px;
padding: 20px 30px 0;
font-size: 24px;
font-size: 20px;
color: rgb(51, 51, 51);
font-weight: bold;
line-height: 40px;
......@@ -72,9 +71,8 @@ const contentComponent = computed(() => {
height: 30px;
line-height: 30px;
padding: 20px 0 0 30px;
font-size: 18px;
font-size: 16px;
font-weight: bold;
clear: both;
color: rgb(102, 102, 102);
}
.systemconfig_item_info{
......@@ -83,13 +81,46 @@ const contentComponent = computed(() => {
font-size: 14px;
line-height: 24px;
color: rgb(153, 153, 153);
clear: both;
}
.systemconfig_tab_area{
padding: 20px 30px;
width: 80%;
min-width: 900px;
/*max-width: 2000px;*/
min-width: 960px;
max-width: 2000px;
margin-right: 100px;
}
.systemconfig_area{
display: flex;
flex-direction: column;
width: 100%;
}
button{
border-radius: 100px;
border: 0;
padding: 6px 20px;
cursor: pointer;
margin-left: 10px;
}
*::-webkit-scrollbar {
width:8px;
height: 8px;
border-radius: 8px;
background-color: #dddddd;
}
*::-webkit-scrollbar-thumb{
width: 8px;
border-radius: 8px;
background-color: #bbbbbb;
cursor: pointer;
}
*::-webkit-scrollbar-thumb:hover{
width: 8px;
border-radius: 8px;
background-color: #666666;
cursor: pointer;
}
* {
scrollbar-color: #bbbbbb #dddddd;
scrollbar-width: thin;
}
</style>
<template>
<div class="systemconfig_title">{{lp.componentDeploy}}</div>
<div class="componentsArea">
<div class="componentItem" v-for="(componentItem, index) in components" :key="componentItem.id">
<div class="componentItemTitle">{{componentItem.title}}</div>
<div class="componentItemName">{{componentItem.name.substring(componentItem.name.indexOf(".")+1, componentItem.name.length)}}</div>
<div class="componentItemIcon">
<BaseIcon :value="componentItem"/>
</div>
<div>
<button class="grayColor_bg" v-if="componentItem.visible" @click="openApplication(componentItem)">{{lp._component.open}}</button>
<button class="grayColor_bg" @click="()=>{editComponent(componentItem, index)}">{{lp._component.edit}}</button>
<button class="grayColor_bg" v-if="componentItem.type!=='system'" @click="(e)=>{uninstallApplication(e, componentItem)}">{{lp._component.uninstall}}</button>
</div>
</div>
<div class="componentItem" style="background-color: #fcfcfc" @mouseenter="(e)=>{e.target.addClass('deployOver')}" @mouseleave="(e)=>{e.target.removeClass('deployOver')}" @click="createComponent">
<div class="componentItemTitle">{{lp._component.deploy}}</div>
<div class="componentItemName"></div>
<div class="componentItemDeploy" style="cursor: pointer">
<div class="componentItemIconDeploy" style=""></div>
</div>
</div>
<div class="componentEditorArea" ref="componentEditorNode">
<BaseInput :label="lp._component.name" v-model:value="currentComponent.name"/>
<BaseInput :label="lp._component.title" v-model:value="currentComponent.title"/>
<BaseInput :label="lp._component.path" v-model:value="currentComponent.path" @change="changePath"/>
<div class="editorPathInfo">{{lp._component.urlPathInfo}}</div>
<BaseBoolean :label="lp._component.visible" v-model:value="currentComponent.visible"/>
<BasePerson :label="lp._component.allowList" v-model:value="currentComponent.allowList"/>
<BasePerson :label="lp._component.denyList" v-model:value="currentComponent.denyList"/>
<BaseIcon :label="lp._component.icon" v-model:value="currentComponent"
:icon-style="{marginLeft:'10px'}"
:can-change="!!(currentComponent.path && currentComponent.path.startsWith('@url'))"
:upload-text="lp._component.selectIcon"
:clear-text="lp._component.clearIcon"/>
<BaseUpload v-if="currentComponent.type!=='system' && (!currentComponent.path || !currentComponent.path.startsWith('@url'))"
:label="lp._component.upload"
:warn="lp._component.uploadWarn"
:upload-files="currentComponent.componentFile"
accept=".zip"
@upload="uploadComponentFile"
@remove="removeComponentFile"/>
</div>
</div>
</template>
<script setup>
import {component, lp, o2} from '@o2oa/component';
import {loadComponents, removeComponent, saveComponent, dispatchComponentFile} from '@/util/acrions';
import {ref} from "vue";
import BaseInput from '../item/BaseInput.vue';
import BaseBoolean from '../item/BaseBoolean.vue';
import BasePerson from '../item/BasePerson.vue';
import BaseIcon from '../item/BaseIcon.vue';
import BaseUpload from '../item/BaseUpload.vue';
const components = ref([]);
const currentComponent = ref({});
const componentEditorNode = ref();
loadComponents().then((data)=>{
components.value = data;
});
function openApplication(cmpt){
if (cmpt.visible) o2.api.page.openApplication(cmpt.path);
}
function uninstallApplication(e, cmpt){
var text = lp._component.removeComponent.replace(/{name}/, cmpt.title);
component.confirm("warn", e, lp._component.removeComponentTitle, text, 500, 170, function(){
uninstallComponent(cmpt);
this.close();
}, function(){
this.close();
}, null, component.content);
}
async function uninstallComponent(cmpt) {
await removeComponent(cmpt.id)
component.notice(lp._component.removeComponentOk, "success");
components.value.erase(cmpt);
}
async function editComponent(cmpt, index) {
currentComponent.value = Object.clone(cmpt);
const container = component.content;
const content = componentEditorNode.value;
content.show();
const size = component.content.getSize();
const width = Math.min(size.x * 0.9, 800);
const height = Math.min(size.y * 0.9, 720);
o2.DL.open({
title: '编辑组件',
container,
maskNode: container,
width,
height,
content,
onQueryClose: () => {
content.hide();
content.inject(container);
},
buttonList: [{
text: lp.operation.ok,
type: 'ok',
action: async (dlg) => {
if (currentComponent.value.componentFile && currentComponent.value.componentFile.length){
await dispatchComponentFile(currentComponent.value.componentFile[0]);
currentComponent.value.componentFile = null;
}
await saveComponent(currentComponent.value);
component.notice( lp._component.deploySuccess, "success");
if (index){
components.value[index] = currentComponent.value;
}else{
components.value.push(currentComponent.value);
}
dlg.close();
}
}, {
text: lp.operation.cancel,
type: 'cancel',
action: dlg => dlg.close()
}]
})
}
function createComponent(){
const cmpt = {
allowList: [],
denyList: [],
iconPath: "appicon.png",
name: "",
path: "",
title: "",
type: "",
visible: true
}
editComponent(cmpt);
}
function uploadComponentFile(file){
currentComponent.value.componentFile = [file];
}
function removeComponentFile(){
currentComponent.value.componentFile = [];
}
function changePath(e){
if (e.startsWith('@url')){
removeComponentFile();
}
}
</script>
<style scoped>
.componentsArea{
padding: 20px;
text-align: center;
}
.componentItem{
width: 140px;
height: 180px;
padding: 10px;
background-color: #f6f6f6;
border-radius: 8px;
margin: 5px;
float: left;
border: 1px solid #dddddd;
}
.componentItemTitle{
height: 30px;
line-height: 30px;
font-weight: bold;
font-size: 18px;
}
.componentItemName{
height: 20px;
line-height: 20px;
color: #999999;
font-size: 14px;
}
.componentItemIcon{
height: 70px;
padding: 15px 0;
}
button{
margin: auto 2px;
width: 28px;
height: 20px;
border-radius: 20px;
border: 1px solid #cccccc;
font-size: 12px;
cursor: pointer;
}
.componentItemDeploy{
height: 90px;
padding: 5px 0;
}
.componentItemIconDeploy{
width: 90px;
height: 90px;
background-size: 60px 60px;
background-position: center;
background-repeat: no-repeat;
border-radius: 10%;
background-color: #f3f3f3;
border: 2px solid #cccccc;
margin: auto;
background-image: url('../../assets/add.png');
}
.deployOver{
color: #347ddb;
}
.deployOver .componentItemIconDeploy{
background-image: url('../../assets/add_over.png');
border: 2px solid #347ddb;
}
.componentEditorArea{
display: none;
padding: 20px;
}
.editorPathInfo{
padding: 5px 20px;
text-align: left;
margin-left: 90px;
}
</style>
<template xmlns="">
<div>
<div class="systemconfig_area">
<div class="systemconfig_title">{{lp.resourceDeploy}}</div>
<div class="systemconfig_tab_area">
......
<template>
<div>
<div class="systemconfig_area">
<div class="systemconfig_title">{{lp.systemInfo}}</div>
<div class="systemconfig_tab_area">
......
<template>
<div>
<div class="systemconfig_area">
<div class="systemconfig_title">{{lp.uiConfig}}</div>
<div class="systemconfig_tab_area">
<el-tabs tab-position="right">
<el-tab-pane :label="lp._uiConfig.baseConfig" lazy>
<BaseConfig></BaseConfig>
<BaseConfig/>
</el-tab-pane>
<el-tab-pane :label="lp._uiConfig.menuConfig" lazy>
<!-- <ServiceDeploy></ServiceDeploy>-->
<MenuConfig/>
</el-tab-pane>
<el-tab-pane :label="lp._uiConfig.userConfig" lazy>
<!-- <ServiceDeploy></ServiceDeploy>-->
......@@ -23,8 +23,8 @@
<script setup>
import {lp} from '@o2oa/component';
import BaseConfig from './uiConfig/BaseConfig.vue';
import MenuConfig from './uiConfig/MenuConfig.vue';
</script>
<style scoped>
</style>
......@@ -196,6 +196,7 @@ button{
border: 1px solid #cccccc;
font-size: 12px;
cursor: pointer;
padding: 2px 5px;
}
.componentItemDeploy{
height: 90px;
......
......@@ -17,16 +17,25 @@
<div class="systemconfig_item_title">{{lp._uiConfig.skinDefault}}</div>
<div class="systemconfig_item_info">{{lp._uiConfig.skinDefaultInfo}}</div>
<div v-for="style in styles" key="style.style">
<div :style="{backgroundColor: style.color}"></div>
<div></div>
<div class="item_skin_area">
<div class="item_skin" v-for="skin in skins" key="skin.style">
<div class="item_skin_color" :style="{backgroundColor: skin.color}" @click="selectSkin(skin)">
<div v-if="config.defaultSkin===skin.style" class="item_skin_current"></div>
</div>
<div>{{skin.title}}</div>
</div>
</div>
<div class="systemconfig_item_title">{{lp._uiConfig.scaleConfig}}</div>
<div class="systemconfig_item_info">{{lp._uiConfig.scaleConfigInfo}}</div>
<BaseBoolean :value="config.scaleConfig" @change="(value)=>{saveConfig('web', 'scaleConfig', value)}" />
</div>
</template>
<script setup>
import {lp} from '@o2oa/component';
import {o2, lp} from '@o2oa/component';
import BaseRadio from '@/components/item/BaseRadio.vue';
import {getConfig, saveConfig} from "@/util/acrions";
import {ref} from 'vue';
......@@ -34,20 +43,55 @@ import BaseBoolean from "@/components/item/BaseBoolean";
const config = ref({
openStatus: 'default',
skinConfig: true
skinConfig: true,
defaultSkin: 'blue',
scaleConfig: true
});
const skins = ref([]);
getConfig('web').then((data)=>{
config.value.openStatus = data.openStatus || 'default';
config.value.skinConfig = data.skinConfig!==false;
config.value.defaultSkin = data.defaultSkin || 'blue';
config.value.scaleConfig = data.scaleConfig!==false;
});
o2.JSON.get("../o2_core/o2/xDesktop/$Default/styles.json", (json)=>{
debugger;
skins.value = json;
})
function selectSkin(skin){
const path = o2.session.path+'/xDesktop/$Default/';
o2.removeCss(path+config.value.defaultSkin+ '/style-skin.css');
config.value.defaultSkin = skin.style;
layout.desktop.node.loadCss(path+config.value.defaultSkin+ '/style-skin.css');
saveConfig('web', 'defaultSkin', skin.style);
}
</script>
<style scoped>
.item_skin_area{
display: flex;
padding: 10px 30px;
text-align: center;
}
.item_skin{
margin-right: 10px;
overflow: hidden;
cursor: pointer;
}
.item_skin_current{
}
.item_skin_color{
width: 40px;
height: 40px;
border-radius: 40%;
line-height: 40px;
color: #ffffff;
font-weight: bold;
font-size: 18px;
}
</style>
<template>
<div class="item_menu_config" ref="menuConfigNode" :style="computeHeight">
<div class="item_lnk_area deepColor_bg"></div>
<div class="item_menu_area">
<ul class="item_menu_title">
<li :class="(currentList==='app') ? 'mainColor_bg' : ''"
@click="loadMenuList('app')">{{lp._uiConfig.menu.application}}</li>
<li :class="(currentList==='process') ? 'mainColor_bg' : ''"
@click="loadMenuList('process')">{{lp._uiConfig.menu.process}}</li>
<li :class="(currentList==='infor') ? 'mainColor_bg' : ''"
@click="loadMenuList('infor')">{{lp._uiConfig.menu.cms}}</li>
<li :class="(currentList==='query') ? 'mainColor_bg' : ''"
@click="loadMenuList('query')">{{lp._uiConfig.menu.query}}</li>
<li class="item_menu_refresh_icon" :title="lp._uiConfig.menu.defaultMenu" @click="test"></li>
</ul>
<div class="item_menu_content" v-if="currentList==='app'" @dragover="dragover" @drop="drop">
<div class="item_menu_content_loading" v-if="!menuList_app.length"></div>
<ul class="item_menu_ul" v-else>
<MenuItem v-for="item in menuList_app" :data="item" @dragItem="dragItem" @loaded="recordAppItems"></MenuItem>
</ul>
</div>
<div class="item_menu_content" v-if="currentList==='process'">
<div class="item_menu_content_loading" v-if="!menuList_process.length"></div>
<ul class="item_menu_ul" v-else>
<MenuItem v-for="item in menuList_process" key="item.id" :data="item"></MenuItem>
</ul>
</div>
<div class="item_menu_content" v-if="currentList==='infor'">
<div class="item_menu_content_loading" v-if="!menuList_infor.length"></div>
<ul class="item_menu_ul" v-else>
<MenuItem v-for="item in menuList_infor" key="item.id" :data="item"></MenuItem>
</ul>
</div>
<div class="item_menu_content" v-if="currentList==='query'">
<div class="item_menu_content_loading" v-if="!menuList_query.length"></div>
<ul class="item_menu_ul" v-else>
<MenuItem v-for="item in menuList_query" key="item.id" :data="item"></MenuItem>
</ul>
</div>
</div>
<div class="item_action_area">
<div class="systemconfig_item_title">{{lp._uiConfig.defaultMenu}}</div>
<div class="systemconfig_item_info">{{lp._uiConfig.defaultMenuInfo}}</div>
<div class="item_button_area">
<button class="mainColor_bg">{{lp._uiConfig.saveMenu}}</button>
<button>{{lp._uiConfig.clearMenu}}</button>
<button>{{lp._uiConfig.loadMenu}}</button>
</div>
<div class="systemconfig_item_title">{{lp._uiConfig.forceMenu}}</div>
<div class="systemconfig_item_info">{{lp._uiConfig.forceMenuInfo}}</div>
<div class="item_button_area">
<button class="mainColor_bg">{{lp._uiConfig.saveMenu}}</button>
<button>{{lp._uiConfig.clearMenu}}</button>
<button>{{lp._uiConfig.loadMenu}}</button>
</div>
<div class="systemconfig_item_title">{{lp._uiConfig.userMenu}}</div>
<div class="systemconfig_item_info">{{lp._uiConfig.userMenuInfo}}</div>
<div class="item_button_area">
<button>{{lp._uiConfig.clearUserMenu}}</button>
</div>
</div>
</div>
</template>
<script setup>
import {ref, computed, unref} from 'vue';
import {lp, layout} from '@o2oa/component';
import {getForceMenuData,
getDefaultMenuData,
loadComponents,
loadProcessApplication,
loadPortalApplication,
loadInforApplication,
loadQueryApplication} from '@/util/acrions';
import MenuItem from './MenuItem.vue'
import {isOverlap} from '@/util/common';
const menuConfigNode = ref();
const defaultMenuData = ref();
const forceMenuData = ref();
const menuData = ref( layout.userLayout.menuData || {
"appList": [],
"processList": [],
"inforList": [],
"queryList": []
});
let menuList_app = ref([]);
const menuList_process = ref([]);
const menuList_infor = ref([]);
const menuList_query = ref([]);
// const menuList_app = markRaw({value: []});
// const menuList_process = {value: []};
// const menuList_infor = {value: []};
// const menuList_query = {value: []};
const currentList = ref('app');
const computeHeight = computed(() => {
if (menuConfigNode.value){
var pNode = menuConfigNode.value.getParent('.systemconfig_area');
if (pNode){
const titleNode = pNode.querySelector('.systemconfig_title');
const size = pNode.getSize();
const titleSize = (titleNode) ? titleNode.getSize() : {y:0};
const height = size.y - titleSize.y-40;
return {height: height+'px'}
}
}
});
function test(){
let list = [];
list.push(menuList_app.value[0]);
list.push(menuList_app.value[2]);
list.push(menuList_app.value[1]);
list = list.concat(menuList_app.value.slice(3));
console.log(list);
menuList_app.value = list;
}
async function loadMenuList(listType, menuType) {
currentList.value = listType;
const getMenuData = (menuType === 'force') ? [getForceMenuData()] : [getDefaultMenuData()];
const dataPromise = {
appList: [loadComponents, loadPortalApplication],
processList: [loadProcessApplication],
inforList: [loadInforApplication],
queryList: [loadQueryApplication],
}[listType+'List'].reduce((p, v)=>{
p.push(v());
return p;
}, getMenuData);
const dataArr = await Promise.all(dataPromise);
const mData = dataArr.shift();
if (mData) menuData.value = mData;
const olist = dataArr.flat();
const orderMenu = menuData.value[listType+'List'];
const list = [];
orderMenu.forEach((item)=>{
if (item.type==='group'){
list.push(item);
item.itemDataList.forEach(m=>{
const i = olist.findIndex(e => e.id===m.id);
if (i!==-1){
olist.splice(i,1);
}
});
}else{
const i = olist.findIndex(e => e.id===item.id);
if (i!==-1){
list.push(olist[i]);
olist.splice(i,1);
}
}
});
switch (listType){
case 'app':
menuList_app.value = list.concat(olist);
break;
case 'process':
menuList_process.value = list.concat(olist);
break;
case 'infor':
menuList_infor.value = list.concat(olist);
break;
case 'query':
menuList_query.value = list.concat(olist);
break;
}
console.log(menuList_app)
// menuList_app = unref(menuList_app);
}
loadMenuList('app');
const menuItems = [];
const recordAppItems = (node)=>{
const iconNode = node.querySelector('.item_menu_icon');
const rect = iconNode.getBoundingClientRect();
const maskNode = node.querySelector('.item_icon_mask');
menuItems.push({node, rect, maskNode, iconNode});
};
let dragging;
function checkDargOverItem(rect){
var overItem = null;
menuItems.forEach(function(item){
if (!item.node.isDragging){
if (isOverlap(rect, item.rect)){
item.maskNode.style.display='block';
overItem = item;
}else{
item.maskNode.style.display='none';
}
}
});
return overItem;
}
function checkDargPosition(rect){
const p = {
x: rect.x+rect.width/2,
y: rect.y+rect.height/2
}
for (let i = 0; i<menuItems.length; i++){
const item = menuItems[i];
if (!item.node.isDragging){
if (p.y>=item.rect.y && p.y<=item.rect.y+item.rect.height){
if (p.x<item.rect.x && p.x>item.rect.x-20){
dragging.node.inject(item.node, "before");
}else if(p.x>item.rect.x+item.rect.width && p.x<item.rect.x+item.rect.width+20){
dragging.node.inject(item.node, "after");
}
}
}
item.rect = item.iconNode.getBoundingClientRect();
}
}
function dragover(e){
e.preventDefault();
const rect = {
x: e.clientX+dragging.offset.x+18,
y: e.clientY+dragging.offset.y+18,
width: dragging.size.x-36,
height: dragging.size.y-36,
}
const overItem = checkDargOverItem(rect);
if (!overItem){
checkDargPosition(rect)
}
}
function drop(e){
const nodeList = e.currentTarget.querySelectorAll('li');
const list = [];
nodeList.forEach((node)=>{
list.push(node.retrieve('data'));
});
console.log(list);
menuList_app.value = list;
}
function dragItem(e){
dragging = e;
}
</script>
<style scoped>
.item_lnk_area{
width: 80px;
height: 100%;
float: left;
}
.item_menu_area {
width: 390px;
height: 100%;
background: #ffffff;
box-shadow: 4px 0 6px 0 rgb(0 0 0 / 25%);
opacity: 1;
user-select: none;
-webkit-user-select: none;
float: left;
border: 1px solid #cccccc;
box-sizing: border-box !important;
display: flex;
flex-direction: column;
}
.item_action_area{
height: 100%;
margin-left: 470px;
}
.item_button_area{
padding: 10px 10px 30px 20px;
}
.item_menu_title{
font-size: 14px;
font-weight: bold;
color: #333333;
text-align: left;
padding: 20px;
height: 30px;
line-height: 30px;
margin: 0;
}
.item_menu_title li{
width: 60px;
height: 28px;
line-height: 28px;
border-radius: 14px;
text-align: center;
float: left;
margin-right: 6px;
margin-left: 6px;
cursor: pointer;
list-style: none;
padding: 0;
}
.item_menu_content{
overflow: auto;
height: 100%;
padding: 10px 0;
}
li.item_menu_refresh_icon{
height: 28px;
width: 28px;
float: right;
background-position: center;
background-repeat: no-repeat;
cursor: pointer;
background-image: url("../../../assets/refresh_menu.png");
}
.item_menu_content_loading{
background-position: center;
background-repeat: no-repeat;
background-image: url("../../../assets/loading.gif");
height: 300px;
}
.item_menu_ul{
padding: 0;
margin: 0;
list-style: none;
}
.item_menu_ul li{
padding: 0;
margin: 0;
width: 72px;
height: 90px;
margin-left: 18px;
margin-bottom: 10px;
float: left;
text-align: center;
cursor: pointer;
}
.item_menu_div{
}
.item_menu_div_text {
padding: 5px 0;
height: 32px;
font-size: 12px;
color: #333333;
}
</style>
<template>
<li ref="itemNode" draggable="true" @dragstart="dragstart" @dragenter="dragenter" @dragover="dragover" @dragend="dragend">
<div class="item_menu_icon">
<BaseIcon :value="data" :item-style="{padding: '0'}" icon-width="40px" icon-height="40px" :icon-style="{width:'40px', height: '40px', backgroundSize: '22px 22px'}"></BaseIcon>
<div ref="iconMask" class="item_icon_mask"></div>
</div>
<div class="item_menu_text" >{{displayName}}</div>
</li>
</template>
<script setup>
import {defineProps, onMounted, ref, defineEmits, nextTick, toRaw, onUpdated} from 'vue';
import {o2} from "@o2oa/component";
import BaseIcon from '@/components/item/BaseIcon.vue';
const emit = defineEmits(['dragItem', 'loaded']);
const props = defineProps({
data: {
type: Object,
default: {}
}
});
const itemType = ref('component');
const displayName = ref('');
const itemNode = ref();
const iconMask = ref();
function getAppNameCommon(){
return props.data.name;
}
function getAppNameInfor(){
return props.data.appName;
}
function getAppNameComponent(){
if (props.data.path && props.data.path.indexOf("@url") !== 0 ){
const appNames = props.data.path.split(".");
let o = o2.xApplication;
appNames.forEach((name)=>{
if (!o[name]) o[name] = {};
o = o[name];
});
return new Promise((resolve)=>{
o2.xDesktop.requireApp(props.data.path, 'lp.' + o2.language, {
onSuccess: function(){
resolve(o.LP.title || props.data.title);
},
onFailure: function () {
resolve(props.data.title);
}
});
});
}else{
return props.data.title;
}
}
function getItemNameType(){
if (props.data.type==='group') return 'group';
if (props.data.hasOwnProperty('portalCategory')) return 'portal';
if (props.data.type==='system' || props.data.type==='custom') return 'component';
if (props.data.hasOwnProperty('documentType')) return 'infor';
if (props.data.hasOwnProperty('queryCategory')) return 'query';
if (props.data.hasOwnProperty('applicationCategory')) return 'process';
}
function getItemNameMethod(){
switch (itemType.value){
case 'component':
return getAppNameComponent;
case 'infor':
return getAppNameInfor;
default:
return getAppNameCommon;
}
}
function getAppName(){
const name = getItemNameMethod()();
Promise.resolve(name).then((n)=>{
displayName.value = n;
})
}
function dragstart(e){
const node = e.currentTarget;
node.addClass('drag');
node.isDragging = true;
e.dataTransfer.effectAllowed = 'move';
const iconNode = node.querySelector('.item_menu_icon');
const p = iconNode.getPosition();
const size = iconNode.getSize();
const offset = {
x: p.x-e.clientX,
y: p.y-e.clientY
};
emit('dragItem', {node, offset, size});
}
function dragend(e){
const node = e.target;
node.isDragging = false;
node.removeClass('drag');
}
onMounted((e)=>{
itemType.value = getItemNameType();
getAppName();
nextTick((e)=>{
itemNode.value.store('data', toRaw(props.data));
emit('loaded', itemNode.value);
})
});
onUpdated(()=>{
console.log(props.data);
})
// function dragenter(e){
// // e.target.style.backgroundColor = '#999999'
// }
// function dragover(e){
// //e.dataTransfer.dropEffect = 'move'
// e.preventDefault();
// // Set the dropEffect to move
// // e.dataTransfer.dropEffect = "move";
// }
</script>
<style scoped>
li{
padding: 0;
margin: 0;
width: 72px;
height: 90px;
margin-left: 18px;
margin-bottom: 10px;
float: left;
text-align: center;
cursor: pointer;
}
li.drag{
opacity: 0.3
}
.item_menu_text {
padding: 5px 0;
height: 32px;
font-size: 12px;
color: #333333;
}
.item_menu_icon {
width: 40px;
height: 40px;
border-radius: 40%;
background-size: 22px 22px;
margin: auto;
position: relative;
}
.item_icon_mask{
width: 60px;
height: 60px;
display: none;
position: absolute;
opacity: 0.3;
background-color: #999999;
border-radius: 40%;
top: -10px;
left: -10px;
}
</style>
<template>
<div class="item" :style="getItemStyle()">
<label class="item_label" v-if="label" :style="Object.assign(labelStyle, {lineHeight: iconHeight, height: iconHeight})">{{label}}</label>
<div class="item_input" v-if="value.path">
<div :class="getClass(value)" :style="Object.assign(getIcon(value), iconStyle)"></div>
</div>
<BaseIconComponent v-if="itemType==='component'" :value="value" :icon-style="iconStyle" :icon-height="iconHeight" :icon-width="iconWidth"></BaseIconComponent>
<BaseIconGroup v-if="itemType==='group'" :value="value" :icon-style="iconStyle" :icon-height="iconHeight" :icon-width="iconWidth"></BaseIconGroup>
<BaseIconPortal v-if="itemType==='portal'" :value="value" :icon-style="iconStyle" :icon-height="iconHeight" :icon-width="iconWidth"></BaseIconPortal>
<BaseIconProcess v-if="itemType==='process'" :value="value" :icon-style="iconStyle" :icon-height="iconHeight" :icon-width="iconWidth"></BaseIconProcess>
<BaseIconInfor v-if="itemType==='infor'" :value="value" :icon-style="iconStyle" :icon-height="iconHeight" :icon-width="iconWidth"></BaseIconInfor>
<BaseIconQuery v-if="itemType==='query'" :value="value" :icon-style="iconStyle" :icon-height="iconHeight" :icon-width="iconWidth"></BaseIconQuery>
<button class="mainColor_bg" @click="changeIcon" v-if="canChange">{{uploadText}}</button>
<button class="" @click="clearIcon" v-if="canChange">{{clearText}}</button>
<input type="file" accept=".png,.jpg,.bmp,.gif,.jpeg,.jpe" ref="uploadNode" @change="uploadIcon" style="display: none" v-if="canChange">
......@@ -11,8 +16,15 @@
</template>
<script setup>
import {layout, o2} from '@o2oa/component';
import {o2} from '@o2oa/component';
import {defineProps, defineEmits, ref} from 'vue';
import BaseIconComponent from './BaseIconComponent.vue';
import BaseIconGroup from './BaseIconGroup.vue';
import BaseIconPortal from './BaseIconPortal.vue';
import BaseIconProcess from './BaseIconProcess.vue';
import BaseIconInfor from './BaseIconInfor.vue';
import BaseIconQuery from './BaseIconQuery.vue';
const uploadNode = ref();
......@@ -21,52 +33,35 @@ const emit = defineEmits(['update:value']);
const props = defineProps({
label: String,
value: Object,
// itemType: { type: String, default: 'component' },
canChange: { type: Boolean, default: false },
iconWidth: { type: String, default: '50px' },
iconHeight: { type: String, default: '50px' },
itemStyle: { type: Object, default: {} },
labelStyle: { type: Object, default: {} },
iconStyle: { type: Object, default: {} },
uploadText: { type: String, default: 'upload' },
clearText: { type: String, default: 'clear' }
});
if (!layout.iconJson){
layout.iconJson = fetch('../o2_core/o2/xDesktop/$Default/icons.json').then((res)=>{
return res.json();
});
function getItemNameType(){
if (props.value.type==='group') return 'group';
if (props.value.hasOwnProperty('portalCategory')) return 'portal';
if (props.value.type==='system' || props.value.type==='custom') return 'component';
if (props.value.hasOwnProperty('documentType')) return 'infor';
if (props.value.hasOwnProperty('queryCategory')) return 'query';
if (props.value.hasOwnProperty('applicationCategory')) return 'process';
}
const iconJson = ref({});
layout.iconJson.then((data)=>{
iconJson.value = data;
});
const itemType = ref(getItemNameType());
function getItemStyle(){
return (props.label) ? {
const style = (props.label) ? {
display: 'flex',
alignItems: 'center'
} : {}
}
} : {};
function getClass(cmpt){
const startWidthUrl = cmpt.path.startsWith('@url')
const path = (startWidthUrl) ? (cmpt.iconPath || 'Url') : cmpt.path;
return (iconJson.value[path]) ? 'componentItemIconSystem' : 'componentItemIconCustom';
}
function getIcon(cmpt){
const isUrl = cmpt.path.startsWith('@url');
const iconObj = iconJson.value[cmpt.path] || ((isUrl && cmpt.iconPath==='appicon.png') ? iconJson.value['Url'] : null);
return (iconObj) ? {
backgroundColor: iconObj.color,
backgroundImage: `url('../o2_core/o2/xDesktop/$Default/appicons/${iconObj.icon}')`,
height: props.iconHeight,
width: props.iconWidth
} : {
backgroundImage: (isUrl) ? `url('${cmpt.iconPath}')` : `url('../x_component_${cmpt.path.replace(/\./g, '_')}/$Main/${cmpt.iconPath}')`,
height: props.iconHeight,
width: props.iconWidth
};
return Object.assign(style, props.itemStyle);
}
function changeIcon(){
......@@ -117,22 +112,6 @@ function clearIcon(){
height: 32px;
line-height: 32px;
}
.item_input{
}
.componentItemIconSystem{
background-size: 26px 26px;
background-position: center;
background-repeat: no-repeat;
border-radius: 40%;
margin: auto;
}
.componentItemIconCustom{
background-size: 50px 50px;
background-position: center;
background-repeat: no-repeat;
margin: auto;
}
button {
border-radius: 100px;
border: 0;
......
<template>
<div class="item_input" v-if="value.path && iconJson">
<div :class="getClass" :style="getIcon">{{value.name}}</div>
</div>
</template>
<script setup>
import {layout} from '@o2oa/component';
import {defineProps, ref, onUpdated, computed} from 'vue';
const props = defineProps({
value: Object,
iconStyle: { type: Object, default: {} },
iconWidth: { type: String, default: '50px' },
iconHeight: { type: String, default: '50px' }
});
// onUpdated(()=>{
// console.log('BaseIconComponent');
// console.log(props.value);
// })
if (!layout.iconJson){
layout.iconJson = fetch('../o2_core/o2/xDesktop/$Default/icons.json').then((res)=>{
return res.json();
});
}
const iconJson = ref();
layout.iconJson.then((data)=>{
iconJson.value = data;
});
const getClass = computed(()=>{
const startWidthUrl = props.value.path.startsWith('@url')
const path = (startWidthUrl && (!props.value.iconPath || props.value.iconPath==='appicon.png')) ? 'Url' : props.value.path;
return (iconJson.value[path]) ? 'componentItemIconSystem' : 'componentItemIconCustom';
});
const getIcon = computed(()=>{
const cmpt = props.value;
const isUrl = cmpt.path.startsWith('@url');
const iconObj = iconJson.value[cmpt.path] || ((isUrl && cmpt.iconPath==='appicon.png') ? iconJson.value['Url'] : null);
const style = (iconObj) ? Object.assign({
backgroundColor: iconObj.color,
backgroundImage: `url('../o2_core/o2/xDesktop/$Default/appicons/${iconObj.icon}')`,
height: props.iconHeight,
width: props.iconWidth
}, props.iconStyle) : {
backgroundImage: (isUrl) ? `url('${cmpt.iconPath}')` : `url('../x_component_${cmpt.path.replace(/\./g, '_')}/$Main/${cmpt.iconPath}')`,
height: props.iconHeight,
width: props.iconWidth,
backgroundSize: `${props.iconWidth} ${props.iconHeight}`
};
console.log('BaseIconComponent-getIcon');
console.log(style);
return style;
});
</script>
<style scoped>
.item_input{
}
.componentItemIconSystem{
background-size: 26px 26px;
background-position: center;
background-repeat: no-repeat;
border-radius: 40%;
margin: auto;
}
.componentItemIconCustom{
background-size: 50px 50px;
background-position: center;
background-repeat: no-repeat;
margin: auto;
}
</style>
<template>
<div class="item_input">
<div class="componentGroupIcon" :style="Object.assign(getIcon(value), iconStyle)">
<div style="padding: 6px 0 0 6px; overflow: hidden;">
<BaseIcon v-for="item in value.itemDataList.slice(0,4)" key="item.id"
:value="item"
:item-style="{padding: '0', float:'left',clear: 'none'}" icon-width="12px" icon-height="12px"
:icon-style="{width:'12px', height: '12px', backgroundSize: '8px 8px', float: 'left', margin: '0 4px 4px 0'}"></BaseIcon>
</div>
</div>
</div>
</template>
<script setup>
import {layout} from '@o2oa/component';
import {defineProps, ref} from 'vue';
import BaseIcon from './BaseIcon.vue'
const props = defineProps({
value: Object,
iconStyle: { type: Object, default: {} },
iconWidth: { type: String, default: '50px' },
iconHeight: { type: String, default: '50px' }
});
function getIcon(){
return {
height: props.iconHeight,
width: props.iconWidth
};
}
</script>
<style scoped>
.item_input{
}
.componentGroupIcon{
width: 50px;
height: 50px;
border-radius: 40%;
margin: auto;
background-color: #e6e6e6;
}
</style>
<template>
<div class="item_input">
<div :class="getClass()" :style="getIcon()"></div>
</div>
</template>
<script setup>
import {defineProps} from 'vue';
const props = defineProps({
value: Object,
iconStyle: { type: Object, default: {} },
iconWidth: { type: String, default: '50px' },
iconHeight: { type: String, default: '50px' }
});
function getClass(){
return (props.value.appIcon) ? 'componentItemIcon' : 'componentItemIconDefault';
}
function getIcon(){
return (props.value.appIcon) ? {
backgroundImage: `url('data:image/png;base64,${props.value.appIcon}')`,
height: props.iconHeight,
width: props.iconWidth,
backgroundSize: `${props.iconWidth} ${props.iconHeight}`
} : Object.assign({
height: props.iconHeight,
width: props.iconWidth
}, props.iconStyle);
}
</script>
<style scoped>
.item_input{
}
.componentItemIconDefault{
background-color: #bbbbbb;
background-image: url(../../assets/cmsDefault.png);
background-position: center;
background-repeat: no-repeat;
width: 40px;
height: 40px;
border-radius: 40%;
background-size: 22px 22px;
}
.componentItemIcon{
background-position: center;
background-repeat: no-repeat;
margin: auto;
}
</style>
<template>
<div class="item_input">
<div :class="getClass()" :style="getIcon()"></div>
</div>
</template>
<script setup>
import {defineProps} from 'vue';
const props = defineProps({
value: Object,
iconStyle: { type: Object, default: {} },
iconWidth: { type: String, default: '50px' },
iconHeight: { type: String, default: '50px' }
});
function getClass(){
return (props.value.icon) ? 'componentItemIcon' : 'componentItemIconDefault';
}
function getIcon(){
return (props.value.icon) ? {
backgroundImage: `url('data:image/png;base64,${props.value.icon}')`,
height: props.iconHeight,
width: props.iconWidth,
backgroundSize: `${props.iconWidth} ${props.iconHeight}`
} : Object.assign({
height: props.iconHeight,
width: props.iconWidth
}, props.iconStyle);
}
</script>
<style scoped>
.item_input{
}
.componentItemIconDefault{
background-color: #bbbbbb;
background-image: url(../../assets/portalDefault.png);
background-position: center;
background-repeat: no-repeat;
width: 40px;
height: 40px;
border-radius: 40%;
background-size: 22px 22px;
}
.componentItemIcon{
background-position: center;
background-repeat: no-repeat;
margin: auto;
}
</style>
<template>
<div class="item_input">
<div :class="getClass()" :style="getIcon()"></div>
</div>
</template>
<script setup>
import {defineProps} from 'vue';
const props = defineProps({
value: Object,
iconStyle: { type: Object, default: {} },
iconWidth: { type: String, default: '50px' },
iconHeight: { type: String, default: '50px' }
});
function getClass(){
return (props.value.icon) ? 'componentItemIcon' : 'componentItemIconDefault';
}
function getIcon(){
return (props.value.icon) ? {
backgroundImage: `url('data:image/png;base64,${props.value.icon}')`,
height: props.iconHeight,
width: props.iconWidth,
backgroundSize: `${props.iconWidth} ${props.iconHeight}`
} : Object.assign({
height: props.iconHeight,
width: props.iconWidth
}, props.iconStyle);
}
</script>
<style scoped>
.item_input{
}
.componentItemIconDefault{
background-color: #bbbbbb;
background-image: url(../../assets/processDefault.png);
background-position: center;
background-repeat: no-repeat;
width: 40px;
height: 40px;
border-radius: 40%;
background-size: 22px 22px;
}
.componentItemIcon{
background-position: center;
background-repeat: no-repeat;
margin: auto;
}
</style>
<template>
<div class="item_input">
<div :class="getClass()" :style="getIcon()"></div>
</div>
</template>
<script setup>
import {defineProps} from 'vue';
const props = defineProps({
value: Object,
iconStyle: { type: Object, default: {} },
iconWidth: { type: String, default: '50px' },
iconHeight: { type: String, default: '50px' }
});
function getClass(){
return (props.value.icon) ? 'componentItemIcon' : 'componentItemIconDefault';
}
function getIcon(){
return (props.value.icon) ? {
backgroundImage: `url('data:image/png;base64,${props.value.icon}')`,
height: props.iconHeight,
width: props.iconWidth,
backgroundSize: `${props.iconWidth} ${props.iconHeight}`
} : Object.assign({
height: props.iconHeight,
width: props.iconWidth
}, props.iconStyle);
}
</script>
<style scoped>
.item_input{
}
.componentItemIconDefault{
background-color: #bbbbbb;
background-image: url(../../assets/queryDefault.png);
background-position: center;
background-repeat: no-repeat;
width: 40px;
height: 40px;
border-radius: 40%;
background-size: 22px 22px;
}
.componentItemIcon{
background-position: center;
background-repeat: no-repeat;
margin: auto;
}
</style>
......@@ -44,7 +44,7 @@ function toggleEditor(){
height: 30px;
line-height: 30px;
padding: 20px 0 0 30px;
font-size: 18px;
font-size: 16px;
font-weight: bold;
clear: both;
color: rgb(102, 102, 102);
......
......@@ -78,7 +78,34 @@ async function deployWebResource(data) {
const result = await action.dispatchResource(data.overwrite, formData, file);
return result.data;
}
function getDefaultMenuData(){
return new Promise((resolve, reject)=>{
o2.UD.getPublicData("defaultMainMenuData", dData=>resolve(dData));
});
}
function getForceMenuData(){
return new Promise((resolve, reject)=>{
o2.UD.getPublicData("forceMainMenuData", dData=>resolve(dData));
});
}
async function loadProcessApplication() {
const json = await o2.Actions.load("x_processplatform_assemble_surface").ApplicationAction.listWithPerson();
return json.data;
}
async function loadPortalApplication() {
const json = await o2.Actions.load("x_portal_assemble_surface").PortalAction.list();
return json.data;
}
async function loadInforApplication() {
const json = await o2.Actions.load("x_cms_assemble_control").AppInfoAction.listWhatICanView_AllType();
return json.data;
}
async function loadQueryApplication() {
const json = await o2.Actions.load("x_query_assemble_surface").QueryAction.listWithPerson();
return json.data;
}
//function to load application
export {
......@@ -89,5 +116,11 @@ export {
getComponent,
saveComponent,
dispatchComponentFile,
deployWebResource
deployWebResource,
getDefaultMenuData,
getForceMenuData,
loadProcessApplication,
loadPortalApplication,
loadInforApplication,
loadQueryApplication
};
if (window.NodeList && !NodeList.prototype.forEach) {
NodeList.prototype.forEach = Array.prototype.forEach;
}
function _getRectPoint(rect){
return {
leftTop: {x: rect.x, y: rect.y},
rightTop: {x: rect.x+rect.width, y: rect.y},
leftBottom: {x: rect.x, y: rect.y+rect.height},
rightBottom: {x: rect.x+rect.width, y: rect.y+rect.height},
}
}
function _pointInRect(p, ps){
return (p.x>=ps.leftTop.x && p.x<=ps.rightTop.x && p.y>=ps.leftTop.y && p.y<=ps.leftBottom.y)
}
function isOverlap(recta, rectb){
const pa = _getRectPoint(recta);
const pb = _getRectPoint(rectb);
for (const k of ['leftTop', 'rightTop', 'leftBottom', 'rightBottom']){
if (_pointInRect(pa[k], pb)) return true;
}
for (const k of ['leftTop', 'rightTop', 'leftBottom', 'rightBottom']){
if (_pointInRect(pb[k], pa)) return true;
}
return false;
}
export {isOverlap};
......@@ -40,6 +40,28 @@ body {
.o2_vue *{
box-sizing: border-box!important;
}
*::-webkit-scrollbar {
width:8px;
height: 8px;
border-radius: 8px;
background-color: #dddddd;
}
*::-webkit-scrollbar-thumb{
width: 8px;
border-radius: 8px;
background-color: #bbbbbb;
cursor: pointer;
}
*::-webkit-scrollbar-thumb:hover{
width: 8px;
border-radius: 8px;
background-color: #666666;
cursor: pointer;
}
* {
scrollbar-color: #bbbbbb #dddddd;
scrollbar-width: thin;
}
/*
.table-tr-selected {
background-color: #FFFFDD;
......
......@@ -27,6 +27,28 @@ body {
box-sizing: border-box!important;
}
*::-webkit-scrollbar {
width:8px;
height: 8px;
border-radius: 8px;
background-color: #dddddd;
}
*::-webkit-scrollbar-thumb{
width: 8px;
border-radius: 8px;
background-color: #bbbbbb;
cursor: pointer;
}
*::-webkit-scrollbar-thumb:hover{
width: 8px;
border-radius: 8px;
background-color: #666666;
cursor: pointer;
}
* {
scrollbar-color: #bbbbbb #dddddd;
scrollbar-width: thin;
}
input,button,select,textarea{outline:none}
select.script::-ms-expand { display: none; }
......
......@@ -3377,9 +3377,14 @@ Object.defineProperties(bind.assignData, {"data": {
return ((data instanceof javaClass.array) || typeOf(data) === "array") && createProxyArray(data);
}
function createProxyArray(data) {
return data.map(function (d) {
return createProxyData(d);
var arr = [];
data.forEach(function (d) {
arr.push(createProxyData(d));
});
return arr;
// return data.map(function (d) {
// return createProxyData(d);
// });
}
function createProxyData(data) {
var proxyData;
......@@ -3429,16 +3434,56 @@ Object.defineProperties(bind.assignData, {"data": {
function isProxyData(data){
return ProxyData.prototype.isPrototypeOf(data);
}
function commitArray(arrList, proxy){
proxy.forEach(function(d, i){
if (Array.isArray(d)){
if (arrList.length<=i) arrList.add(new java.util.ArrayList());
commitArray(arrList[i], d)
}else if (isProxyData(d)){
d.commit();
}else if (d instanceof Object) {
if (arrList.length<=i) arrList.add(new java.util.LinkedHashMap());
commitObject(arrList[i], d)
}else{
if (arrList.length<=i){
arrList.add(d);
}else if (arrList[i]!==d){
arrList[i]=d;
}
}
});
}
function commitObject(map, proxy){
Object.keys(proxy).forEach(function(key){
var d = proxy[key];
if (Array.isArray(d)){
if (!map.containsKey(key)) map.put(key, new java.util.ArrayList());
commitArray(map[key], d)
}else if (isProxyData(d)){
d.commit();
}else if (d instanceof Object) {
if (!map.containsKey(key)) map.put(key, new java.util.LinkedHashMap());
commitObject(map[key], d)
}else{
if (!map.containsKey(key) || map[key] !== d) map.put(key, d);
}
});
}
function commitData(data, proxy) {
Object.keys(proxy).forEach(function (key) {
var d = proxy[key];
if (isProxyData(d)){
d.commit();
}else{
if (Array.isArray(d) || !data.containsKey(key)) data[key] = d;
}else if (Array.isArray(d)) {
if (!data.containsKey(key)) data[key] = new java.util.ArrayList();
commitArray(data[key], d)
}else if (!data.containsKey(key)){
data[key] = d;
}
})
}
function ProxyData(tData) {
Object.defineProperty(this, "proxyData", {
value: {}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册