mirror of https://gitee.com/cf-fz/WebCAD.git
!2204 新增:分享图纸导出配置
parent
6717dbcc71
commit
9c243e918c
@ -0,0 +1,76 @@
|
||||
import { CommandNames } from "../../Common/CommandNames";
|
||||
import { RenderType } from "../../GraphicsSystem/RenderType";
|
||||
import { ViewDirection } from "../../UI/Store/BoardInterface";
|
||||
|
||||
//仅在分享图纸shareView使用
|
||||
export const ViewAngleTypes = [
|
||||
{
|
||||
command: CommandNames.FS,
|
||||
name: "俯视",
|
||||
viewDirection: ViewDirection.Up
|
||||
},
|
||||
{
|
||||
command: CommandNames.YS,
|
||||
name: "右视",
|
||||
viewDirection: ViewDirection.Right
|
||||
},
|
||||
{
|
||||
command: CommandNames.ZS,
|
||||
name: "左视",
|
||||
viewDirection: ViewDirection.Left
|
||||
},
|
||||
{
|
||||
command: CommandNames.QS,
|
||||
name: "前视",
|
||||
viewDirection: ViewDirection.Front
|
||||
},
|
||||
{
|
||||
command: CommandNames.BottomView,
|
||||
name: "仰视",
|
||||
viewDirection: ViewDirection.Bottom
|
||||
},
|
||||
{
|
||||
command: CommandNames.BackView,
|
||||
name: "后视",
|
||||
viewDirection: ViewDirection.Back
|
||||
},
|
||||
{
|
||||
command: CommandNames.Swiso,
|
||||
name: "西南等轴测",
|
||||
viewDirection: ViewDirection.Southwest
|
||||
},
|
||||
];
|
||||
|
||||
//仅在分享图纸shareView使用
|
||||
export const ViewStyleTypes = [
|
||||
{
|
||||
title: "二维线框",
|
||||
cmd: CommandNames.Wireframe,
|
||||
renderType: RenderType.Wireframe,
|
||||
},
|
||||
{
|
||||
title: "概念",
|
||||
cmd: CommandNames.Conceptual,
|
||||
renderType: RenderType.Conceptual,
|
||||
},
|
||||
{
|
||||
title: "真实",
|
||||
cmd: CommandNames.Physical,
|
||||
renderType: RenderType.Physical,
|
||||
},
|
||||
{
|
||||
title: "真实带线框",
|
||||
cmd: CommandNames.Physical2,
|
||||
renderType: RenderType.Physical2,
|
||||
},
|
||||
{
|
||||
title: "排版面",
|
||||
cmd: CommandNames.CheckPlaceFace,
|
||||
renderType: RenderType.PlaceFace,
|
||||
},
|
||||
{
|
||||
title: "概念(透明)",
|
||||
cmd: CommandNames.ConceptualTransparent,
|
||||
renderType: RenderType.ConceptualTransparent,
|
||||
},
|
||||
];
|
@ -0,0 +1,62 @@
|
||||
import { observable, toJS } from "mobx";
|
||||
|
||||
import { Singleton } from "../../Common/Singleton";
|
||||
import { Board } from "../../DatabaseServices/Entity/Board";
|
||||
import { DefaultShareBoardInfConfigurationOption } from "../../Editor/DefaultConfig";
|
||||
import { IConfigOption } from "../../UI/Components/Board/UserConfigComponent";
|
||||
import { ShareBoardInfConfigurationOption } from "../../UI/Store/BoardInterface";
|
||||
import { IConfigStore } from '../../UI/Store/BoardStore';
|
||||
|
||||
interface IProps
|
||||
{
|
||||
/* 是否展示物料明细 */
|
||||
showBom?: boolean | null;
|
||||
}
|
||||
|
||||
export class ShareViewStore extends Singleton implements IConfigStore
|
||||
{
|
||||
@observable
|
||||
Index: number[] = [];
|
||||
@observable
|
||||
RoomName: string;
|
||||
|
||||
@observable
|
||||
SelectedBoard: Board = null;
|
||||
|
||||
@observable
|
||||
ViewIDErrorMsg: string = '';
|
||||
|
||||
// 主题 画布颜色
|
||||
@observable
|
||||
Theme: 'light' | 'dark' | string = 'light';
|
||||
|
||||
// 纪录上一次
|
||||
@observable
|
||||
ThemeLog: 'light' | 'dark' | string = '';
|
||||
|
||||
// 后台配置数据
|
||||
@observable
|
||||
Props: IProps = {};
|
||||
@observable m_Option: ShareBoardInfConfigurationOption = DefaultShareBoardInfConfigurationOption;
|
||||
|
||||
@observable viewUploadProps: ShareBoardInfConfigurationOption = DefaultShareBoardInfConfigurationOption;
|
||||
|
||||
@observable configName = "默认";
|
||||
SaveConfig()
|
||||
{
|
||||
//新的配置
|
||||
let newConfig: IConfigOption = {};
|
||||
newConfig.option = toJS(this.m_Option);
|
||||
return newConfig;
|
||||
};
|
||||
//板数据
|
||||
@observable configsNames: string[] = [];
|
||||
InitOption()
|
||||
{
|
||||
Object.assign(this.m_Option, DefaultShareBoardInfConfigurationOption);
|
||||
}
|
||||
UpdateOption(cof: IConfigOption<ShareBoardInfConfigurationOption>)
|
||||
{
|
||||
Object.assign(this.m_Option, cof.option);
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
import { observable } from "mobx";
|
||||
|
||||
import { Singleton } from "../../Common/Singleton";
|
||||
import { Board } from "../../DatabaseServices/Entity/Board";
|
||||
|
||||
interface IProps
|
||||
{
|
||||
/* 是否展示物料明细 */
|
||||
IsMaterialDetails?: boolean | null;
|
||||
}
|
||||
|
||||
export class BoxStore extends Singleton
|
||||
{
|
||||
@observable
|
||||
Index: number[] = [];
|
||||
@observable
|
||||
RoomName: string;
|
||||
|
||||
@observable
|
||||
SelectedBoard: Board = null;
|
||||
|
||||
@observable
|
||||
ViewIDErrorMsg: string = '';
|
||||
|
||||
// 主题 画布颜色
|
||||
@observable
|
||||
Theme: 'light' | 'dark' | string = 'light';
|
||||
|
||||
// 纪录上一次
|
||||
@observable
|
||||
ThemeLog: 'light' | 'dark' | string = '';
|
||||
|
||||
// 后台配置数据
|
||||
@observable
|
||||
Props: IProps = {}
|
||||
}
|
@ -0,0 +1,125 @@
|
||||
.container {
|
||||
position: relative;
|
||||
min-height: 1.5em;
|
||||
border: .05em solid #777;
|
||||
display: flex;
|
||||
width: 16em;
|
||||
align-items: center;
|
||||
gap: .5em;
|
||||
padding: .5em;
|
||||
margin-left: .5em;
|
||||
border-radius: .25em;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.container:focus {
|
||||
border-color: hsl(200, 100%, 50%);
|
||||
}
|
||||
|
||||
.value {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
gap: .5em;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.clear-btn {
|
||||
background: none;
|
||||
color: #777;
|
||||
border: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
.clear-btn:focus,
|
||||
.clear-btn:hover {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.divider {
|
||||
background-color: #777;
|
||||
align-self: stretch;
|
||||
width: .05em;
|
||||
}
|
||||
|
||||
.caret {
|
||||
translate: 0 25%;
|
||||
border: .25em solid transparent;
|
||||
border-top-color: #777;
|
||||
}
|
||||
|
||||
.options {
|
||||
position: absolute;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
display: none;
|
||||
max-height: 15em;
|
||||
overflow-y: auto;
|
||||
border: .05em solid #777;
|
||||
border-radius: .25em;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: calc(100% + .25em);
|
||||
background-color: white;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.options.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5em;
|
||||
padding: .25em .5em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.option.selected {
|
||||
background-color: hsl(200, 100%, 70%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.option.highlighted {
|
||||
background-color: hsl(200, 100%, 50%);
|
||||
color: white
|
||||
}
|
||||
|
||||
.option-badge {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: .05em solid #777;
|
||||
border-radius: .25em;
|
||||
padding: .15em .25em;
|
||||
gap: .25em;
|
||||
cursor: pointer;
|
||||
background: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.option-badge:hover,
|
||||
.option-badge:focus {
|
||||
background-color: hsl(0, 100%, 90%);
|
||||
border-color: hsl(0, 100%, 50%);
|
||||
}
|
||||
|
||||
.option-badge:hover>.remove-btn,
|
||||
.option-badge:focus>.remove-btn {
|
||||
color: hsl(0, 100%, 50%);
|
||||
}
|
||||
|
||||
.option-badge>.remove-btn {
|
||||
font-size: 1.25em;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.container .colorBox {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
display: inline-block;
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import "./ColorSelect.css";
|
||||
|
||||
export type SelectOption = {
|
||||
label: string | number;
|
||||
value: string | number | any;
|
||||
};
|
||||
|
||||
type SelectProps = {
|
||||
onChange: (value: number) => void;
|
||||
options: SelectOption[];
|
||||
value: number;
|
||||
};
|
||||
|
||||
export function ColorSelect({ value, onChange, options }: SelectProps)
|
||||
{
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [highlightedIndex, setHighlightedIndex] = useState(0);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
function selectOption(val: number)
|
||||
{
|
||||
if (val !== value) onChange(val);
|
||||
}
|
||||
|
||||
function isOptionSelected(option: number)
|
||||
{
|
||||
return option === value;
|
||||
}
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if (isOpen) setHighlightedIndex(0);
|
||||
}, [isOpen]);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
const handler = (e: KeyboardEvent) =>
|
||||
{
|
||||
if (e.target != containerRef.current) return;
|
||||
switch (e.code)
|
||||
{
|
||||
case "Enter":
|
||||
case "Space":
|
||||
setIsOpen(prev => !prev);
|
||||
if (isOpen) selectOption(highlightedIndex);
|
||||
break;
|
||||
case "ArrowUp":
|
||||
case "ArrowDown": {
|
||||
if (!isOpen)
|
||||
{
|
||||
setIsOpen(true);
|
||||
break;
|
||||
}
|
||||
|
||||
const newValue = highlightedIndex + (e.code === "ArrowDown" ? 1 : -1);
|
||||
if (newValue >= 0 && newValue < options.length)
|
||||
{
|
||||
setHighlightedIndex(newValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "Escape":
|
||||
setIsOpen(false);
|
||||
break;
|
||||
}
|
||||
};
|
||||
containerRef.current?.addEventListener("keydown", handler);
|
||||
|
||||
return () =>
|
||||
{
|
||||
containerRef.current?.removeEventListener("keydown", handler);
|
||||
};
|
||||
}, [isOpen, highlightedIndex, options]);
|
||||
|
||||
const IsLightShadow = (rgb: number[]) =>
|
||||
{
|
||||
const shadow = (rgb[0] * 0.299 + rgb[1] * 0.587 + rgb[2] * 0.114) * rgb[3];
|
||||
if (shadow > 192) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
onBlur={() => setIsOpen(false)}
|
||||
onClick={() => setIsOpen(prev => !prev)}
|
||||
tabIndex={0}
|
||||
className="container"
|
||||
>
|
||||
<div className="value" >
|
||||
<span >
|
||||
{value}.
|
||||
</span>
|
||||
<span style={{ background: `rgba(${value === 0 ? "0,0,0,255" : options[value].value.join(",")})`, border: IsLightShadow(options[value].value) ? "1px solid #666" : null }} className="colorBox" />
|
||||
</div>
|
||||
<div className={"divider"}></div>
|
||||
<div className={"caret"}></div>
|
||||
<ul className={`options ${isOpen ? "show" : ""}`}>
|
||||
{options.map((option, index) =>
|
||||
{
|
||||
if (index === options.length - 1) return;
|
||||
return (
|
||||
<li
|
||||
onClick={e =>
|
||||
{
|
||||
e.stopPropagation();
|
||||
selectOption(index);
|
||||
setIsOpen(false);
|
||||
}}
|
||||
onMouseEnter={() => setHighlightedIndex(index)}
|
||||
key={option.value}
|
||||
className={`option ${isOptionSelected(index) ? "selected" : ""} ${index === highlightedIndex ? "highlighted" : ""}`}
|
||||
>
|
||||
<span> {option.label}. </span>
|
||||
<span style={{ background: `rgba(${index === 0 ? "0,0,0,255" : option.value.join(",")})`, border: IsLightShadow(option.value) ? "1px solid #666" : null }} className="colorBox" />
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,149 @@
|
||||
import { Button, Checkbox, Classes, HTMLSelect, Icon, Intent } from "@blueprintjs/core";
|
||||
import { observer } from "mobx-react";
|
||||
import React from "react";
|
||||
import { begin } from "xaop";
|
||||
import { app } from "../../../ApplicationServices/Application";
|
||||
import { ColorPalette } from "../../../Common/ColorPalette";
|
||||
import { KeyBoard } from "../../../Common/KeyEnum";
|
||||
import { BoardModalType } from "../../../UI/Components/Board/BoardModalType";
|
||||
import { Config_ModalType, UserConfigComponent } from "../../../UI/Components/Board/UserConfigComponent";
|
||||
import { AppToaster } from "../../../UI/Components/Toaster";
|
||||
import { ViewAngleTypes, ViewStyleTypes } from "../ShareViewRules";
|
||||
import { ShareViewStore } from "../ShareViewStore";
|
||||
import { ColorSelect } from "./ColorSelect";
|
||||
import "./ShareBoradModal.less";
|
||||
|
||||
@observer
|
||||
export class ShareBoardInfoConfiguration extends React.Component<{ store: ShareViewStore; }, {}>
|
||||
{
|
||||
_RemoveFun: Function;
|
||||
|
||||
componentDidMount()
|
||||
{
|
||||
this._RemoveFun = begin(app.Editor.ModalManage, app.Editor.ModalManage.OnKeyDown, (e: KeyboardEvent) =>
|
||||
{
|
||||
if (e.keyCode === KeyBoard.Enter || e.keyCode === KeyBoard.Space)
|
||||
app.Editor.ModalManage.Destory();
|
||||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount()
|
||||
{
|
||||
if (this._RemoveFun) this._RemoveFun();
|
||||
}
|
||||
|
||||
BoardAndHadrwareToaster()
|
||||
{
|
||||
AppToaster.show({
|
||||
message: "板件与五金必选其中一项!",
|
||||
timeout: 5000,
|
||||
intent: Intent.DANGER,
|
||||
}, "shareview");
|
||||
}
|
||||
|
||||
render()
|
||||
{
|
||||
const option = this.props.store.m_Option;
|
||||
return (
|
||||
<div id="ShareBoardInfoPanel" className={Classes.DIALOG_CONTAINER}>
|
||||
<div className={Classes.DIALOG} >
|
||||
<div className={Classes.DIALOG_HEADER} data-id="dragArea">
|
||||
<Icon icon="cog" iconSize={18} />
|
||||
<h4 className={Classes.HEADING}>分享图设置</h4>
|
||||
<Button
|
||||
icon="cross"
|
||||
aria-label="Close"
|
||||
minimal={true}
|
||||
onClick={() => { app.Editor.ModalManage.Destory(); }}
|
||||
/>
|
||||
</div>
|
||||
<div className={Classes.DIALOG_BODY}>
|
||||
<span >选择分享实体</span>
|
||||
<div className="label" style={{ marginTop: "6px", marginBottom: "0px" }}>
|
||||
<Checkbox
|
||||
checked={option.IsExportBoard}
|
||||
label="板件"
|
||||
onChange={() =>
|
||||
{
|
||||
if (!option.IsExportHardware && option.IsExportBoard)
|
||||
{
|
||||
this.BoardAndHadrwareToaster();
|
||||
return;
|
||||
}
|
||||
option.IsExportBoard = !option.IsExportBoard;
|
||||
}}
|
||||
/>
|
||||
<Checkbox
|
||||
checked={option.IsExportHardware}
|
||||
label="五金"
|
||||
onChange={() =>
|
||||
{
|
||||
if (!option.IsExportBoard && option.IsExportHardware)
|
||||
{
|
||||
this.BoardAndHadrwareToaster();
|
||||
return;
|
||||
}
|
||||
option.IsExportHardware = !option.IsExportHardware;
|
||||
}}
|
||||
/>
|
||||
<Checkbox
|
||||
checked={true}
|
||||
disabled
|
||||
label="其他"
|
||||
/>
|
||||
</div>
|
||||
<div className="label" style={{ marginTop: "6px", marginBottom: "0px" }}>
|
||||
<Checkbox
|
||||
checked={option.showBom}
|
||||
label="展示物料明细"
|
||||
onChange={() => { option.showBom = !option.showBom; }}
|
||||
/>
|
||||
</div>
|
||||
<div className="label">
|
||||
<span>真实带线框颜色:</span>
|
||||
<ColorSelect
|
||||
options={JSON.parse(JSON.stringify(ColorPalette)).map((rgb, index) => ({ value: rgb, label: index }))}
|
||||
value={option.Physical2EdgeColor}
|
||||
onChange={(value) =>
|
||||
{
|
||||
option.Physical2EdgeColor = value;
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="label">
|
||||
<span>视觉角度:</span>
|
||||
<HTMLSelect
|
||||
style={{ height: "28px" }}
|
||||
value={option.Viewport}
|
||||
options={ViewAngleTypes.map((v) => ({ value: v.viewDirection, label: v.name }))}
|
||||
onChange={(e) => { option.Viewport = parseInt(e.target.value); }}
|
||||
/>
|
||||
</div>
|
||||
<div className="label">
|
||||
<span>视觉样式:</span>
|
||||
<HTMLSelect
|
||||
style={{ height: "28px" }}
|
||||
value={option.VisualStyle}
|
||||
options={ViewStyleTypes.map((v) => ({ value: v.renderType, label: v.title }))}
|
||||
onChange={(e) => { option.VisualStyle = parseInt(e.target.value); }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={Classes.DIALOG_FOOTER} >
|
||||
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
||||
<UserConfigComponent store={this.props.store} type={BoardModalType.ShareBoardInfoUpdateConfiguration} configType={Config_ModalType.UserConfigModal} />
|
||||
<div className="foot_right">
|
||||
<Button
|
||||
intent={Intent.SUCCESS}
|
||||
text="确定"
|
||||
onClick={() => { app.Editor.ModalManage.DestoryAndExec(); }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
#ShareBoardInfoPanel{
|
||||
.bp3-dialog-body{
|
||||
padding: 10px 20px 0 20px;
|
||||
background-color: white;
|
||||
|
||||
label{
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
|
||||
.bp3-dialog-footer{
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.label{
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
Loading…
Reference in new issue