!2275 功能:配置列表可排序,重命名,优化配置名显示

pull/2321/MERGE
黄诗津 1 year ago committed by ChenX
parent d78d6cf3e7
commit aee595622c

@ -1,5 +1,5 @@
import type { Identifier, XYCoord } from 'dnd-core';
import type { FC } from 'react';
import type { FC, ReactNode } from 'react';
import React, { useRef } from 'react';
import { useDrag, useDrop } from 'react-dnd';
@ -10,12 +10,11 @@ export const ItemTypes = {
export interface CardProps
{
id: any;
label: string;
orderName: string;
value: string;
index: number;
moveCard: (dragIndex: number, hoverIndex: number) => void;
onDoubleClick: (id: number) => void;
onDoubleClick?: (id: number) => void;
conteainer: ReactNode;
canDrag: boolean;
}
interface DragItem
@ -23,7 +22,7 @@ interface DragItem
index: number;
}
export const CustomNumCard: FC<CardProps> = ({ id, label, orderName, value, index, moveCard, onDoubleClick }) =>
export const CustomNumCard: FC<CardProps> = ({ id, index, moveCard, onDoubleClick, conteainer, canDrag }) =>
{
const ref = useRef<HTMLDivElement>(null);
const [{ handlerId }, drop] = useDrop<
@ -102,6 +101,10 @@ export const CustomNumCard: FC<CardProps> = ({ id, label, orderName, value, inde
collect: (monitor: any) => ({
isDragging: monitor.isDragging(),
}),
canDrag: () =>
{
return canDrag;
}
});
const opacity = isDragging ? 0 : 1;
@ -113,10 +116,7 @@ export const CustomNumCard: FC<CardProps> = ({ id, label, orderName, value, inde
style={{ opacity }}
data-handler-id={handlerId}
className="item"
onDoubleClick={() => onDoubleClick(id)}
>
<div>{label}:{value}</div>
<div>{orderName}:{index + 1}</div>
</div>
onDoubleClick={() => onDoubleClick && onDoubleClick(id)}
>{conteainer}</div>
);
};

@ -1,60 +1,69 @@
import update from 'immutability-helper';
import type { FC } from 'react';
import React, { useCallback, useState } from 'react';
import { CustomNumberStore } from './CustomNumberPanel';
import type { CSSProperties, FC } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import { CustomNumCard } from './CustomNumCard';
import { CustomNumberStore } from './CustomNumberPanel';
const style = {
width: 400,
};
export interface CustomNumberItem
{
id: number;
text: string;
}
interface ICustomNumContainer
{
state: CustomNumberStore;
canDrag: boolean;
renderConteainer: (state: CustomNumberStore, card: CustomNumberItem, index: number) => JSX.Element | string;
clsssName?: string;
style?: CSSProperties;
}
export const CustomNumContainer: FC<{ state: CustomNumberStore; }> = (prop) =>
export const CustomNumContainer: FC<ICustomNumContainer> = (prop) =>
{
const [cards, setCards] = useState(prop.state.option.items);
useEffect(() =>
{
const [cards, setCards] = useState(prop.state.option.items);
setCards(prop.state.option.items);
}, [prop.state.option.items]);
const moveCard = useCallback((dragIndex: number, hoverIndex: number) =>
const moveCard = useCallback((dragIndex: number, hoverIndex: number) =>
{
setCards((prevCards: CustomNumberItem[]) =>
{
setCards((prevCards: CustomNumberItem[]) =>
{
let cards = update(prevCards, {
$splice: [
[dragIndex, 1],
[hoverIndex, 0, prevCards[dragIndex] as CustomNumberItem],
],
});
if (prop.state.onChange)
prop.state.onChange(cards, dragIndex, hoverIndex);
return cards;
let cards = update(prevCards, {
$splice: [
[dragIndex, 1],
[hoverIndex, 0, prevCards[dragIndex] as CustomNumberItem],
],
});
}, []);
if (prop.state.onChange)
prop.state.onChange(cards, dragIndex, hoverIndex);
return cards;
});
}, []);
const renderCard = useCallback(
(card: { id: number; text: string; }, index: number) =>
{
return (
<CustomNumCard
id={card.id}
key={card.id}
label={prop.state.label}
orderName={prop.state.orderName}
index={index}
value={card.text}
moveCard={moveCard}
onDoubleClick={prop.state.onDoubleClick}
/>
);
}, [],
);
const renderCard = useCallback(
(card: { id: number; text: string; }, index: number) =>
{
return (
<CustomNumCard
id={card.id}
key={card.id}
index={index}
canDrag={prop.canDrag}
moveCard={moveCard}
onDoubleClick={prop.state.onDoubleClick}
conteainer={
prop.renderConteainer(prop.state, card, index)
}
/>
);
}, [prop.canDrag],
);
return (
<div style={style}>{cards.map((card, i) => renderCard(card, i))}</div>
);
}
return (
<div className={prop.clsssName} style={prop.style}>{cards.map((card, i) => renderCard(card, i))}</div>
);
};

@ -5,8 +5,8 @@ import { DndProvider } from "react-dnd";
import { HTML5Backend } from 'react-dnd-html5-backend';
import { app } from "../../ApplicationServices/Application";
import { ModalState } from "../../UI/Components/Modal/ModalInterface";
import { CustomNumContainer, CustomNumberItem } from "./CustomNumContainer";
import "./CustomNumberPanelCss.less";
import { CustomNumberItem, CustomNumContainer } from "./CustomNumContainer";
@observer
export class CustomNumberPanel extends React.Component<{ store: CustomNumberStore; }>
@ -35,6 +35,15 @@ export class CustomNumberPanel extends React.Component<{ store: CustomNumberStor
<DndProvider backend={HTML5Backend}>
<CustomNumContainer
state={this.props.store}
style={{ width: 400 }}
renderConteainer={(state, card, index) =>
{
return (
<>
<div>{state.label}:{card.text}</div>
<div>{state.orderName}:{index + 1}</div>
</>);
}}
/>
</DndProvider>
</div>

@ -9,6 +9,7 @@ import { IndexedDbStore, StoreName } from "../IndexedDb/IndexedDbStore";
import { BoardModalType } from "../UI/Components/Board/BoardModalType";
import { AppToaster } from "../UI/Components/Toaster";
import { IConfigStore } from "../UI/Store/BoardStore";
import { configListMapStore } from "../UI/Store/ConfigListMapStore";
import { DrillStore } from "../UI/Store/DrillStore";
import { userConfigStore } from "../UI/Store/UserConfigStore";
@ -122,6 +123,7 @@ export async function ImportConfig(type: string, store: IConfigStore, newName: s
importConfigs = await store.GetDeserializeConfig(fileData.config);
}
const newNames = [];
let firstKey: string;
for (let key in importConfigs)
{
@ -135,9 +137,10 @@ export async function ImportConfig(type: string, store: IConfigStore, newName: s
if (!firstKey)
firstKey = newKey;
configs[newKey] = importConfigs[key];
store.configsNames.push(newKey);
newNames.push(newKey);
}
}
await configListMapStore.AddConfig(type, newNames, store);
let data = await PostJson(ConfigUrls.Edit, { key: type, value: JSON.stringify(configs) });
if (data.err_code === RequestStatus.Ok)

@ -21,15 +21,12 @@ export enum BoardModalType
JG = "jg",
Lat = "lattice",
TempDes = "templatedesign",
ProcessGroupCategory = "processgroupcategory",
Ct = "drawer",
ActLr = "activelr",
CompMetals = "compmetals",
ToplineMetals = "toplinemetals",
UserConfig = "userConfig",
Curves2Rec = "curves2rec",
Rec2Br = "rec2br",
SmoothEdge = "smoothEdge",
UpdateBoardInfo = "updateboardinfo",
YX = "yixing",
R2WR = "R2WR",
@ -39,7 +36,6 @@ export enum BoardModalType
HS = "hideSelect",
ParseBrName = "ParseBrName",
AutoDimBrs = "AutoDimBrs",
SelectThinBehindBoard = "SelectThinBehindBoard",
ChangeColorByBoardMaterial = "ChangeColorByMaterial",
ShareBoardInfoUpdateConfiguration = "ShareBoardInfoSettings",
ModifyTexts = "ModifyTexts",
@ -47,22 +43,29 @@ export enum BoardModalType
Viewport2 = "Viewport2",
Viewport3 = "Viewport3",
Viewport4 = "Viewport4",
AutoHoleFaceSetting = "AutoHoleFaceSetting",
EditViewSetting = "EditViewSetting",
PointLight = "PointLight",
SpotLight = "SpotLight",
RectAreaLight = "RectAreaLight",
RightPlaneLight = "RightPlaneLight",
CommonPanelStore = "CommonPanelStore",
KJLImportConfig = "KJLMaterialMap", //酷家乐导入配置(原酷家乐材质映射,考虑用户可能已经存在配置,所以原配置名称不变)
BBSEditor = "BBSEditor", //编辑BBS
BatchCurtail = "curtail", //批量内缩
BatchModifyPanel = "BatchModifyPanel", //批量修改板件
Sealing = "Sealing", //封边
TemplateManage = "TemplateManage",//模板管理界面信息
DimStyleConfig = "DimStyleConfig",//标注配置
DatalistStore = "DatalistStore", //数据列表配置
BulkheadCeiling = "BulkheadCeiling",//吊顶轮廓
BulkheadCeilingContour = "BulkheadCeilingContour",//吊顶轮廓
HeadCeilingProfileMaterial = "HeadCeilingProfileMaterial",//吊顶截面材质
//独立配置,只存在一个的配置
AutoHoleFaceSetting = "AutoHoleFaceSetting",
SelectThinBehindBoard = "SelectThinBehindBoard",
SmoothEdge = "smoothEdge",
ProcessGroupCategory = "processgroupcategory",
UserConfig = "userConfig",
CommonPanelStore = "CommonPanelStore",
TemplateManage = "TemplateManage",//模板管理界面信息
DatalistStore = "DatalistStore", //数据列表配置
ConfigListMapStore = "ConfigListMapStore", //配置列表排序映射
}

@ -2,14 +2,20 @@ import { Button, InputGroup, Intent, Menu, MenuItem, Popover, Position, Tab, Tab
import { autorun, observable } from "mobx";
import { observer } from "mobx-react";
import React from "react";
import { DndProvider } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import { CustomNumContainer, CustomNumberItem } from "../../../Add-on/CustomNumber/CustomNumContainer";
import { CustomNumberStore } from "../../../Add-on/CustomNumber/CustomNumberPanel";
import { templateTagCommand } from "../../../Add-on/Template/TemplateTagCommand";
import { KeyBoard } from "../../../Common/KeyEnum";
import { commandReg } from "../../../Common/Utils";
import { IConfigStore } from "../../Store/BoardStore";
import { configListMapStore } from "../../Store/ConfigListMapStore";
import { userConfigStore } from "../../Store/UserConfigStore";
import { CommandList } from "../CommandPanel/CommandList";
import { AppToaster } from "../Toaster";
import { BoardModalType } from "./BoardModalType";
import { TabContainer } from "./ConfigListTabContainer";
import { ConfigTagCommand } from "./ConfigTagCommand";
import { Config_ModalType } from "./UserConfigComponent";
@ -36,6 +42,9 @@ export class ConfigList extends React.Component<IConfigListProps>
@observable private flag: TipType = TipType.OK;
@observable private isShow = false;
@observable private isCNInput: boolean = false;
isResetName = observable.box(false);
isShowCoustomNumList = observable.box(false);
private tagRef = React.createRef<HTMLInputElement>();
disposeAutorun: Function;
componentDidMount()
@ -53,6 +62,8 @@ export class ConfigList extends React.Component<IConfigListProps>
this.disposeAutorun();
this.disposeAutorun = undefined;
}
//快捷命令标签
ShortcutLabel = (errorMsg: string) =>
{
return (
@ -66,6 +77,7 @@ export class ConfigList extends React.Component<IConfigListProps>
>
<InputGroup
tabIndex={1}
disabled={this.isResetName.get()}
defaultValue={ConfigTagCommand.GetInstance().GetTagByConfig(this.props.store.configName, this.props.type)?.tagName ?? ""}
inputRef={this.tagRef}
className={this.flag === TipType.OK ? "" : "err-input"}
@ -86,62 +98,106 @@ export class ConfigList extends React.Component<IConfigListProps>
InputSelect = () =>
{
const { store, type } = this.props;
const state = new CustomNumberStore();
const items = store.configsNames.concat();
state.option.items = items.map((c, i) => ({ id: i + 1, text: c }));
state.onChange = (items: CustomNumberItem[]) =>
{
state.option.items = items;
};
state.onOk = async () =>
{
let newConfigNames = state.option.items.map(item => item.text);
if (JSON.stringify(items) === JSON.stringify(newConfigNames)) return;
await configListMapStore.ResetConfig(type, newConfigNames, store);
};
return (
<label className="input-select">
<span></span>
<InputGroup
tabIndex={1}
value={this.props.store.configName}
onKeyDown={(e) =>
{
if (e.keyCode === KeyBoard.Space)
<>
<label className="input-select">
<span></span>
<InputGroup
tabIndex={1}
disabled={this.isResetName.get()}
value={store.configName}
onKeyDown={(e) =>
{
if (e.keyCode === KeyBoard.Space)
{
e.stopPropagation();
}
}}
onKeyUp={() =>
{
e.stopPropagation();
//过滤空格
store.configName = store.configName.replace(/\s+/g, '');
}}
onChange={e =>
{
if (e.target.value.length <= 15)
store.configName = e.target.value;
}}
rightElement=
{
<Popover
autoFocus={true}
enforceFocus={false}
usePortal={false}
position={Position.TOP}
isOpen={this.isResetName.get() ? true : undefined}
onClosed={() => { state.onOk(); }}
modifiers={{
arrow: { enabled: false },
flip: { enabled: true },
keepTogether: { enabled: true },
preventOverflow: { enabled: true, boundariesElement: "scrollParent" }
}}
content={
<Menu style={{ overflow: "auto", maxHeight: 400 }}>
<DndProvider backend={HTML5Backend}>
<CustomNumContainer
state={state}
clsssName="config-custom-number"
canDrag={!this.isResetName.get()}
renderConteainer={(state, card, index) =>
{
return (
<MenuItem
className="config-menuitem"
key={card.id}
onClick={() => { this.props.updateBoardOption(card.text); }}
shouldDismissPopover={!this.isResetName.get()}
text={
<TabContainer
index={index}
keyName={card.text}
type={type}
store={store}
isResetName={this.isResetName}
/>
}
/>
);
}}
/>
</DndProvider>
</Menu>
}
target={
<Button
minimal={true}
rightIcon="caret-up"
/>
}
/>
}
}}
onKeyUp={() =>
{
//过滤空格
this.props.store.configName = this.props.store.configName.replace(/\s+/g, '');
}}
onChange={e =>
{
if (e.target.value.length <= 15)
this.props.store.configName = e.target.value;
}}
rightElement=
{
<Popover
autoFocus={true}
enforceFocus={false}
usePortal={false}
position={Position.TOP}
modifiers={{
arrow: { enabled: false },
flip: { enabled: true },
keepTogether: { enabled: true },
preventOverflow: { enabled: true, boundariesElement: "scrollParent" }
}}
content={
<Menu style={{ overflow: "auto", maxHeight: 400 }}>
{
this.props.store.configsNames
.map((k, i) =>
<MenuItem
key={i}
onClick={e => this.props.updateBoardOption(e.currentTarget.text)}
text={k}
/>)
}
</Menu>}
target={
<Button
minimal={true}
rightIcon="caret-up"
></Button>} />
}
/>
</label>
/>
</label>
</>
);
};
@ -152,12 +208,14 @@ export class ConfigList extends React.Component<IConfigListProps>
<Button
text="保存"
intent={Intent.SUCCESS}
disabled={this.isResetName.get()}
style={{ marginLeft: 3 }}
onClick={async () => { this.handleSaveTagConfig(); }}
/>
<Button
text="删除"
intent={Intent.DANGER}
disabled={this.isResetName.get()}
style={{ marginLeft: 3 }}
onClick={async () => { this.props.handleDeleteConfig(); }}
/>
@ -186,54 +244,135 @@ export class ConfigList extends React.Component<IConfigListProps>
ConfigListTag = (errorMsg: string) =>
{
const { store, type } = this.props;
return (
<div className='config-list'>
<h4 className="bp3-heading"></h4>
<div>
<Tabs
id="configTabs"
vertical={true}
onChange={(id) =>
{
this.props.updateBoardOption(id.toString());
if (this.props.type === BoardModalType.TempDes) return;
this.flag = TipType.OK;
this.props.store.configName = id.toString();
}}
animate={true}
selectedTabId={this.props.store.configName}
<div className="flex-between">
<h4 className="bp3-heading">{`${this.isShowCoustomNumList.get() ? "列表排序" : "配置列表"}`}</h4>
<Tooltip
content={"自定义排序"}
position={Position.TOP}
disabled={this.isShowCoustomNumList.get() || this.isResetName.get()}
>
{
this.props.store.configsNames.map((key, i) =>
<Tab
key={key}
id={key}
title={key}
/>
)
}
</Tabs>
</div>
<div className='config-input'>
<label>
<span></span>
<InputGroup
tabIndex={1}
value={this.props.store.configName}
onChange={e =>
{
if (e.target.value.length <= 15)
this.props.store.configName = e.target.value;
}}
<Button
icon={"sort"}
small
disabled={this.isShowCoustomNumList.get() && (!!store.configsNames.length) || this.isResetName.get()}
onClick={() => { this.isShowCoustomNumList.set(true); }}
/>
</label>
{
this.props.configType === Config_ModalType.ConfigListTagModal &&
this.ShortcutLabel(errorMsg)
}
{
this.SaveAndDelete()
}
</Tooltip>
</div>
{
this.isShowCoustomNumList.get() ?
this.renderCustomNumList() :
<>
<div className="config-tabs">
<Tabs
id="configTabs"
vertical={true}
onChange={(id) =>
{
this.props.updateBoardOption(id.toString());
if (type === BoardModalType.TempDes) return;
this.flag = TipType.OK;
store.configName = id.toString();
}}
animate={true}
selectedTabId={store.configName}
>
{
store.configsNames.map((key, i) =>
<Tab
key={key}
id={key}
className="config-tab"
title={
<TabContainer
index={i}
keyName={key}
type={type}
store={store}
isResetName={this.isResetName}
isTip={true}
/>
}
/>
)
}
</Tabs>
</div>
<div className='config-input'>
<label>
<span></span>
<InputGroup
tabIndex={1}
disabled={this.isResetName.get()}
value={store.configName}
onChange={e =>
{
if (e.target.value.length <= 15)
store.configName = e.target.value;
}}
/>
</label>
{
this.props.configType === Config_ModalType.ConfigListTagModal &&
this.ShortcutLabel(errorMsg)
}
{
this.SaveAndDelete()
}
</div>
</>
}
</div>
);
};
renderCustomNumList = () =>
{
const { store, type } = this.props;
const state = new CustomNumberStore();
const items = store.configsNames.concat();
state.option.items = items.map((c, i) => ({ id: i + 1, text: c }));
state.onChange = (items: CustomNumberItem[]) =>
{
state.option.items = items;
};
state.onOk = async () =>
{
let newConfigNames = state.option.items.map(item => item.text);
await configListMapStore.ResetConfig(type, newConfigNames, store);
};
return (
<div className="custom-number-list">
<DndProvider backend={HTML5Backend}>
<CustomNumContainer
state={state}
canDrag={true}
clsssName="config-custom-number"
renderConteainer={(state, card) => { return (<div>{card.text}</div>); }}
/>
</DndProvider>
<div className="flex-arround">
<Button
intent="success"
text="确定"
onClick={() =>
{
this.isShowCoustomNumList.set(false);
state.onOk();
}}
/>
<Button
intent="danger"
text="取消"
onClick={() => { this.isShowCoustomNumList.set(false); }}
/>
</div>
</div>
);

@ -0,0 +1,119 @@
import { Button, InputGroup, Position, Tooltip } from '@blueprintjs/core';
import { IObservableValue } from 'mobx';
import { observer } from 'mobx-react';
import type { FC } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { Intent } from '../../../Common/Toaster';
import { IConfigStore } from '../../Store/BoardStore';
import { userConfigStore } from '../../Store/UserConfigStore';
import { BoardModalType } from './BoardModalType';
export interface ITabContainer
{
index: number;
keyName: string;
type: BoardModalType;
store: IConfigStore;
isResetName: IObservableValue<Boolean>;
isTip?: boolean;
}
export const TabContainer: FC<ITabContainer> = observer(({ index, keyName, type, isResetName, store, isTip }) =>
{
const curIsResetName = useRef(false);
let [curInputName, setCurInputName] = useState("");
useEffect(() =>
{
if (curIsResetName.current)
{
handleClose();
}
}, [store.configName]);
const handleOpen = (keyName: string) =>
{
curIsResetName.current = true;
setCurInputName(keyName);
isResetName.set(true);
};
const handleClose = () =>
{
curIsResetName.current = false;
isResetName.set(false);
};
return (
<div>
{
isResetName.get() && curIsResetName.current ?
<div
className='flex'
style={{ paddingLeft: 2, backgroundColor: "color(display-p3 0.43 1 0.65 / 0.2)" }}
onClick={(e) => { e.stopPropagation(); }}
>
<div style={{ flex: 1 }}>
<InputGroup
value={curInputName}
style={{ width: "100%", height: 28, marginTop: 1 }}
onChange={e =>
{
if (e.target.value.length <= 15)
setCurInputName(e.target.value);
}}
onKeyDown={(e) => { e.stopPropagation(); }}
/>
</div>
<div style={{ width: 60 }}>
<Button
icon="small-tick"
minimal
intent={Intent.SUCCESS}
onClick={async () =>
{
if (curInputName.length && curInputName != keyName)
{
await userConfigStore.ResetNameConfig(type, store, keyName, curInputName, index);
}
handleClose();
}}
/>
<Button
icon="small-cross"
minimal
intent={Intent.DANGER}
onClick={() => { handleClose(); }}
/>
</div>
</div>
:
<div className="flex" style={{ padding: "0 10px" }} >
<div style={{ overflow: "hidden" }}>
<Tooltip content={keyName} disabled={!isTip || keyName.length <= 10} position={Position.TOP} >
<div>{keyName}</div>
</Tooltip>
</div>
{
!isResetName.get() &&
<div className="rename">
<Button
small
icon="edit"
style={{
backgroundImage: "none",
boxShadow: "none",
backgroundColor: "rgba(19, 124, 189, 0.2)"
}}
onClick={(e: React.MouseEvent) =>
{
e.stopPropagation();
handleOpen(keyName);
}}
/>
</div>
}
</div>
}
</div>
);
});

@ -101,6 +101,18 @@ export class ConfigTagCommand
this.UploadTagList();
}
UpdataTagMap(oldCofigName: string, newConfigName: string, type: BoardModalType)
{
const tag = this.GetTagByConfig(oldCofigName, type);
if (tag)
{
this.DeleteCustomTagCommand(oldCofigName);
tag.configName = newConfigName;
this.RegistCustomTagCommand(tag);
this.UploadTagList();
}
}
RemoveTag(configName: string, type: BoardModalType)
{
let tagName = this.GetTagByConfig(configName, type)?.tagName;

@ -147,7 +147,7 @@ export class DrillTypeCom extends React.Component<{ store: DrillStore; }, { type
for (let i = 0; i < drillList.length; i++)
store.option.items.push({ id: i + 1, text: drillList[i] });
store.onChange = (items: CustomNumberItem[], dragIndex: number, hoverIndex: number) =>
store.onChange = (items: CustomNumberItem[]) =>
{
store.option.items = items;
};

@ -6,6 +6,7 @@ import { arrayLast } from '../../../Common/ArrayExt';
import { FS } from '../../../Common/FileSystem';
import { userConfig } from '../../../Editor/UserConfig';
import { IConfigStore } from '../../Store/BoardStore';
import { configListMapStore } from '../../Store/ConfigListMapStore';
import { IDoorInfo, IDrawerInfo } from '../../Store/DoorInterface';
import { DrillConfigSortType } from '../../Store/DrillStore';
import { BoardProcessOption } from "../../Store/OptionInterface/BoardProcessOption";
@ -116,6 +117,7 @@ export class UserConfigComponent extends React.Component<IConfigProps, {}>{
//某些情况下 需要提前手动加载配置(例如双击实体属性时 改封边 改造型时)(如果需要 也可以手动初始化配置(提前))
LoadAndInitConfig()
{
if (this.props.isImpExp) return; //导入导出就不需要更新了
let isNotUpdateStore = this.props.isNotUpdateStore;//备份变量,异步过程中这个变量被修改
action(async () =>
{
@ -173,7 +175,7 @@ export class UserConfigComponent extends React.Component<IConfigProps, {}>{
let store = this.props.store;
return (
<>
<label style={this.props.style} className={this.props.className}>
<span style={this.props.style} className={this.props.className}>
{
this.props.hasconfig &&
<ConfigList
@ -186,7 +188,7 @@ export class UserConfigComponent extends React.Component<IConfigProps, {}>{
handleDeleteConfig={this.handleDeleteConfig}
/>
}
</label>
</span>
{
this.props.isImpExp &&
<div style={{ display: "flex", width: 105, justifyContent: 'space-between' }}>
@ -272,9 +274,7 @@ export class DialogUserConfig
if (userConfigStore.readConfigs.has(this._UIType)) return false;//已经载入过
userConfigStore.readConfigs.add(this._UIType);//避免重入
let configs = (await userConfigStore.GetAllConfigs(this._UIType)) || {};
let confNames = Array.from(Object.keys(configs));
let confNames = await configListMapStore.GetConfig(this._UIType);
observable(this._Store.configsNames).replace(confNames);
return true;//载入成功
}
@ -293,7 +293,9 @@ export class DialogUserConfig
if (configs)
{
observable(this._Store.configsNames).replace(Object.keys(configs));
let confNames = Object.keys(configs);
await configListMapStore.AddConfig(this._UIType, confNames, this._Store);
await userConfigStore.InitConfigs(configs, this._UIType);//多个配置上传到云端
}
else

@ -1,116 +1,167 @@
.config-list {
width : 180px;
height : 100%;
display : flex;
flex-direction: column;
h4 {
font-size : 16px;
margin-left : 3px;
margin-bottom: 5px;
}
&>:nth-child(2) {
padding : 3px;
flex-grow : 1;
flex-basis : 60px;
border : 1px solid #ccc;
border-radius: 3px;
overflow-y : auto;
}
.bp3-tab-list {
width: 100%;
}
.config-input {
display: flex;
flex-direction: column;
align-items : center;
&>:nth-child(n) {
margin-top: 5px;
}
&>label {
&>:nth-child(1) {
font-size : 14px;
font-weight : 600;
padding-right: 10px;
}
.bp3-input-group {
display: inline-block;
}
.bp3-input {
width : 7rem;
height: 2rem;
}
}
.err-input{
.err-input();
}
}
}
.err-input{
border: 1px solid red;
border-radius: 5px;
.bp3-input:focus{
box-shadow: 0 0 0 0 red;
}
}
#commonModal .config-list .config-input .bp3-input {
width : 7rem;
height: 2rem;
}
#commonModal .userconfig .bp3-input {
width: 120px;
}
.userconfig {
display: flex;
.input-select {
&>span:first-of-type {
margin-right: 3px;
}
display: flex;
align-items: center;
}
}
.userconfig-tag {
display: flex;
flex-direction: column;
align-items: center;
.err-input{
.err-input();
}
.input-select {
display: flex;
align-items: center;
}
&>:nth-child(n) {
margin-top: 5px;
}
label {
&>:nth-child(1) {
margin-right: 5px;
}
.bp3-input{
width: 120px;
}
}
}
width: 180px;
height: 100%;
display: flex;
flex-direction: column;
h4 {
font-size: 16px;
margin-left: 3px;
margin-bottom: 5px;
}
.config-tabs {
padding: 3px;
flex-grow: 1;
flex-basis: 60px;
border: 1px solid #ccc;
border-radius: 3px;
overflow-y: auto;
}
.custom-number-list {
flex-grow: 1;
flex-basis: 60px;
display: flex;
flex-direction: column;
overflow-y: auto;
.config-custom-number {
flex: 1;
border: 1px solid #ccc;
margin: 3px;
padding: 3px;
border-radius: 3px;
overflow-y: auto;
.item {
cursor: move;
padding: 0.5rem 1rem;
margin-bottom: 2px;
background-color: #cccccc54;
}
.item:hover {
background-color: rgba(19, 124, 189, 0.2);
}
}
}
.bp3-tabs.bp3-vertical>.bp3-tab-list {
width: 100%;
.bp3-tab {
padding: 0;
}
}
.config-input {
display: flex;
flex-direction: column;
align-items: center;
&>:nth-child(n) {
margin-top: 5px;
}
&>label {
&>:nth-child(1) {
font-size: 14px;
font-weight: 600;
padding-right: 10px;
}
.bp3-input-group {
display: inline-block;
}
.bp3-input {
width: 7rem;
height: 2rem;
}
}
.err-input {
.err-input();
}
}
}
.err-input {
border: 1px solid red;
border-radius: 5px;
.bp3-input:focus {
box-shadow: 0 0 0 0 red;
}
}
#commonModal .config-list .config-input .bp3-input {
width: 7rem;
height: 2rem;
}
#commonModal .userconfig .bp3-input {
width: 120px;
}
.userconfig {
display: flex;
.input-select {
&>span:first-of-type {
margin-right: 3px;
}
display: flex;
align-items: center;
}
}
.userconfig-tag {
display: flex;
flex-direction: column;
align-items: center;
.err-input {
.err-input();
}
.input-select {
display: flex;
align-items: center;
}
&>:nth-child(n) {
margin-top: 5px;
}
label {
&>:nth-child(1) {
margin-right: 5px;
}
.bp3-input {
width: 120px;
}
}
}
.config-tab,
.config-menuitem {
.rename {
position: absolute;
right: 0px;
top: -1px;
opacity: 0;
}
.rename:hover {
opacity: 1;
}
}
.config-menuitem {
position: relative;
padding: 3px 0;
}

@ -144,7 +144,7 @@ export class ConfigStore extends Singleton
app.Viewer.UpdateRender();
await userConfigStore.SaveConfig(BoardModalType.UserConfig, userConfig);
await userConfigStore.SaveConfig(BoardModalType.UserConfig, userConfig, { isUploadUserConfigNames: false });
};
}

@ -0,0 +1,125 @@
import { arrayRemoveIf } from "../../Common/ArrayExt";
import { ConfigUrls } from "../../Common/HostUrl";
import { PostJson, RequestStatus } from "../../Common/Request";
import { Singleton } from "../../Common/Singleton";
import { GetIndexDBID } from "../../Common/Utils";
import { IndexedDbStore, StoreName } from "../../IndexedDb/IndexedDbStore";
import { BoardModalType } from "../Components/Board/BoardModalType";
import { IConfigOption } from "../Components/Board/UserConfigComponent";
import { IConfigStore } from "./BoardStore";
import { ConfigListMapOption } from "./OptionInterface/IOptionInterface";
import { userConfigStore } from "./UserConfigStore";
export class ConfigListMapStore extends Singleton
{
configListMap = new Map<string, string[]>();
m_Option: ConfigListMapOption = {
version: 1,
configList: Object.fromEntries(this.configListMap.entries())
};
InitOption()
{
this.m_Option = {
version: 1,
configList: Object.fromEntries(this.configListMap.entries())
};
}
async GetConfig(key: string)
{
const configs = (await userConfigStore.GetAllConfigs(key)) || {};
const confNames = Array.from(Object.keys(configs));
const names = [];
if (!this.configListMap.get(key))
{
names.push(...confNames);
}
else
{
const configListNames = this.configListMap.get(key);
if (JSON.stringify(confNames.concat().sort()) != JSON.stringify(configListNames.concat().sort()))
{
//这里提供一个数据验证,提示数据出错
console.error(`配置名称对不上,type:${key}`);
names.push(...confNames);
}
else
names.push(...configListNames);
}
return names.concat();
}
/**
* store.configsNames
*/
async AddConfig(key: string, addNames: string[], store: IConfigStore)
{
const names = await this.GetConfig(key);
const isInit = addNames.length > 1; //初始配置时可能存在多个
const isExist = addNames.length === 1 && names.includes(addNames[0]); //判断是否存在
if (isInit || !isExist)
names.push(...addNames);
store.configsNames = names;
this.configListMap.set(key, names);
await this.SaveConfig();
}
/**
* store.configsNames
*/
async ResetConfig(key: string, resetName: string[], store: IConfigStore)
{
store.configsNames = resetName;
this.configListMap.set(key, resetName.concat());
await this.SaveConfig();
45;
}
/**
* store.configsNames
*/
async DeleteConfig(key: string, name: string, store: IConfigStore)
{
const names = await this.GetConfig(key);
arrayRemoveIf(names, (n) => n === name);
store.configsNames = names;
if (names.length)
this.configListMap.set(key, names);
else
this.configListMap.delete(key);
await this.SaveConfig();
}
async SaveConfig()
{
let newConfig: IConfigOption = {};
this.m_Option.configList = Object.fromEntries(this.configListMap.entries());
newConfig.option = this.m_Option;
let dbStore = await IndexedDbStore.CADStore();
let data = await PostJson(ConfigUrls.Edit, { key: BoardModalType.ConfigListMapStore, value: JSON.stringify(newConfig) });
if (data.err_code === RequestStatus.Ok)
{
dbStore.Put(StoreName.ConfigData, GetIndexDBID(BoardModalType.ConfigListMapStore), newConfig);
dbStore.Put(StoreName.ConfigVersion, GetIndexDBID(BoardModalType.ConfigListMapStore), data.version);
}
};
UpdateOption(cof: IConfigOption<ConfigListMapOption>)
{
this.configListMap = new Map(Object.entries(cof.option.configList));
Object.assign(this.m_Option, cof.option);
}
}
export const configListMapStore = ConfigListMapStore.GetInstance();

@ -339,3 +339,8 @@ export interface ProcessingGroupOption
processGroupCategory: string[];
addAlone: boolean;
}
export interface ConfigListMapOption extends IBaseOption
{
configList: { [k: string]: string[]; };
}

@ -1,5 +1,4 @@
import { Intent } from "@blueprintjs/core";
import { observable } from "mobx";
import React from "react";
import { TemplateTagCommand, templateTagCommand } from "../../Add-on/Template/TemplateTagCommand";
import { app } from "../../ApplicationServices/Application";
@ -32,11 +31,12 @@ import RoomBaseParamsStore from "../Components/ToolBar/ModifyModel/RoomBaseParam
import ResourceStore from "../Components/ToolBar/ResourceLibrary/RsourceStore";
import { bbsEditorStore } from "./BBSEditorStore";
import { IConfigStore } from "./BoardStore";
import { configListMapStore } from "./ConfigListMapStore";
import { DoorStore } from "./DoorDrawerStore/DoorStore";
import { DrawerStore } from "./DoorDrawerStore/DrawerStore";
import { DownPanelStore } from "./DownPanelStore";
import { DrillConfigSortType, DrillStore } from "./DrillStore";
import { AnyObject, CommonPanelConfigOption, DatalistConfigOption } from "./OptionInterface/IOptionInterface";
import { AnyObject, CommonPanelConfigOption, ConfigListMapOption, DatalistConfigOption } from "./OptionInterface/IOptionInterface";
import { RightPanelStore } from "./RightPanelStore/RightPanelStore";
import { TopPanelStore } from "./TopPanelStore";
import { updateBoardInfoStore } from "./UpdateBoardInfoStore";
@ -164,7 +164,7 @@ export class UserConfigStore extends Singleton
}
else
{
await this.SaveConfig(BoardModalType.UserConfig, userConfig, { isInit: true });
await this.SaveConfig(BoardModalType.UserConfig, userConfig, { isInit: true, isUploadUserConfigNames: false });
}
}
@ -186,7 +186,7 @@ export class UserConfigStore extends Singleton
}
else
{
await this.SaveConfig(BoardModalType.CommonPanelStore, commonPanelStore, { toaster: false, isInit: true });
await this.SaveConfig(BoardModalType.CommonPanelStore, commonPanelStore, { toaster: false, isInit: true, isUploadUserConfigNames: false });
let config = await this.GetConfig(BoardModalType.CommonPanelStore) as IConfigOption<CommonPanelConfigOption>;
if (config)
{
@ -225,6 +225,20 @@ export class UserConfigStore extends Singleton
doorPanelStore.InitOption();
}
private async InitConfigListMap()
{
let configs = await this.GetAllConfigs(BoardModalType.ConfigListMapStore) as IConfigOption<ConfigListMapOption>;
if (configs)
{
configListMapStore.UpdateOption(configs);
}
else
{
configListMapStore.InitOption();
await configListMapStore.SaveConfig();
}
}
/**处理用户登陆后的信息 */
async InitUserData()
{
@ -235,6 +249,7 @@ export class UserConfigStore extends Singleton
FileServer.GetInstance().Clear();
this.readConfigs.clear();
await this.CacheAllConfigs();
await this.InitConfigListMap();
await this.GetUserConfigNames();
await this.InitDrillConfig();
await this.InitUpdateBoardInfoConfigs();
@ -359,14 +374,11 @@ export class UserConfigStore extends Singleton
await ConfigTagCommand.GetInstance().AddTag(type, tagName, store.configName);
// 配置添加到数据库
configs[configName] = newConfig;
observable(store.configsNames).replace(Object.keys(configs));
if (type === BoardModalType.Dr)
this.ChangeDrillRuleMap(configs);
}
let dbStore = await IndexedDbStore.CADStore();
if (!configs)
{
AppToaster.show({
@ -376,11 +388,17 @@ export class UserConfigStore extends Singleton
});
return;
}
if (isUploadUserConfigNames)
{
//同理多个配置就保存
await configListMapStore.AddConfig(type, [configName], store);
}
let data = await PostJson(ConfigUrls.Edit, { key: type, value: JSON.stringify(configs) });
if (data.err_code === RequestStatus.Ok)
{
let dbStore = await IndexedDbStore.CADStore();
dbStore.Put(StoreName.ConfigData, GetIndexDBID(type), configs);
dbStore.Put(StoreName.ConfigVersion, GetIndexDBID(type), data.version);
appCache.set(type, configs);
@ -421,7 +439,7 @@ export class UserConfigStore extends Singleton
let configTagCommand = ConfigTagCommand.GetInstance();
configTagCommand.RemoveTag(store.configName, type);
observable(store.configsNames).remove(currentName);
configListMapStore.DeleteConfig(type, currentName, store);
let configs = await this.GetAllConfigs(type);
if (!configs)
@ -477,6 +495,63 @@ export class UserConfigStore extends Singleton
}
}
}
/**
* ,
*/
async ResetNameConfig(type: BoardModalType, store: IConfigStore, oldName: string, newName: string, index: number)
{
const configList = await configListMapStore.GetConfig(type);
if (configList.includes(newName))
{
AppToaster.show({
message: "重命名失败,配置名重复",
intent: Intent.DANGER,
timeout: 3000,
});
return;
}
let confirm = await AppConfirm.show({ message: "确认重命名配置?" });
if (!confirm)
return;
const configs = await this.GetAllConfigs(type);
if (type === BoardModalType.Dr)
this.ChangeDrillRuleMap(configs);
configs[newName] = configs[oldName];
delete configs[oldName];
let configTagCommand = ConfigTagCommand.GetInstance();
configTagCommand.UpdataTagMap(oldName, newName, type);
let data = await PostJson(ConfigUrls.Edit, { key: type, value: JSON.stringify(configs) });
if (data.err_code === RequestStatus.Ok)
{
let dbStore = await IndexedDbStore.CADStore();
dbStore.Put(StoreName.ConfigData, GetIndexDBID(type), configs);
dbStore.Put(StoreName.ConfigVersion, GetIndexDBID(type), data.version);
appCache.set(type, configs);
AppToaster.show({
message: "配置重命名成功!",
timeout: 5000,
intent: Intent.SUCCESS,
});
if (store.configName === oldName)
{
store.configName = newName;
await this.UpdateBoardOption(newName, type, store);
userConfig.userConfigName[type] = newName;
await this.UploadUserConfigNames(dbStore);
}
configList[index] = newName;
await configListMapStore.ResetConfig(type, configList, store);
}
}
//更新配置
UpdateBoardOption = async (k: string, type: BoardModalType, store: IConfigStore) =>
{

Loading…
Cancel
Save