Compare commits

...

8 Commits

Author SHA1 Message Date
guofei 741a498ca4 fix: change api suffix 2024-11-18 13:13:53 +08:00
guofei 9473427bd6 fix: add mobile fit 2024-11-18 11:56:35 +08:00
guofei d4959a2260 fix: chagne style 2024-11-15 18:27:26 +08:00
guofei 18f9e61435 change style 2024-11-07 11:46:45 +08:00
guofei bed619d6ad fix: change size 2024-11-05 17:56:26 +08:00
guofei a5f133f055 fix: change style 2024-11-05 15:08:21 +08:00
guofei 42c3e51d04 fix: change styles 2024-10-17 14:42:07 +08:00
guofei 86d150fb29 fix: repaire style 2024-10-17 14:27:53 +08:00
8 changed files with 327 additions and 167 deletions

View File

@ -15,6 +15,34 @@
}
}
@media only screen and (orientation: landscape) {
#abc {
width: 200px;
height: 200px;
background-color: red;
}
}
/* 竖屏 */
@media only screen and (orientation: portrait) {
#abc {
width: 200px;
height: 200px;
background-color: blue;
}
}
.pane_mobile {
position: fixed;
left: 0;
top: 0;
bottom: 0;
width: 200px;
height: 100vh;
background-color: #535353;
z-index: 1000;
}
.App-header {
background-color: #282c34;
min-height: 100vh;
@ -62,7 +90,7 @@
}
.pane-btn.checked {
border: 3px solid #00DE7A;
border: 3px solid #00de7a;
}
.pane-btn + .pane-btn {
@ -94,8 +122,8 @@
.language-select-container .language-select {
width: 156px;
height: 42px;
background-color: #36383A;
color: #EEEEEE;
background-color: #36383a;
color: #eeeeee;
font-size: 14px;
display: flex;
align-items: center;
@ -104,8 +132,8 @@
.language-select-warpper {
position: relative;
border-radius: 5px;
background: #36383A;
border: 1px solid #5B5B5B;
background: #36383a;
border: 1px solid #5b5b5b;
box-shadow: 0px 3px 0px 0px rgba(0, 0, 0, 0.3);
}

View File

@ -29,6 +29,8 @@ import { withTranslation } from "react-i18next";
import i18n from "i18next";
import languageImg from "./images/language.png";
import Arrow from './images/arrow.svg'
import logoPanePng from "./images/logo-pane.png";
import SvgIcon from '@mui/material/SvgIcon';
@ -40,11 +42,14 @@ function CustomIcon(props) {
);
}
const isMobile = () => {
return /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)
}
class App extends React.Component {
constructor(props) {
super();
this.state = {
mode: "normal",
projects: [],
selectedProject: {},
selectedProjectName: "",
@ -61,10 +66,16 @@ class App extends React.Component {
keepLogin: false,
},
language: localStorage.getItem("lang") ?? "zh",
isMobile: isMobile(),
};
this.t = props.t;
}
componentDidMount() {
window.addEventListener('resize', () => {
this.setState({ isMobile: isMobile() });
})
const loginInfo = getLoginInfo();
var tenant = utils.getTenant();
const hideLogo = queryString.parseUrl(window.location.href)?.query
@ -161,12 +172,6 @@ class App extends React.Component {
});
}
setMode(mode) {
this.setState({
mode: mode,
});
}
setLoginForm(form) {
this.setState({
loginForm: {
@ -208,18 +213,7 @@ class App extends React.Component {
}
render() {
var {
mode,
device,
projects,
selectedProject,
dataUrl,
loading,
loginOpen,
loginForm,
hideLogo,
language,
} = this.state;
const { device, projects, dataUrl, loading, loginOpen, loginForm, hideLogo, language, isMobile } = this.state;
const { t } = this.props;
return (
@ -277,44 +271,52 @@ class App extends React.Component {
<Button onClick={() => this.login()}>{t("submit")}</Button>
</DialogActions>
</Dialog>
<Pane
mode={mode}
onModeChange={(_mode) => this.setMode(_mode)}
projects={projects}
device={device}
loading={loading}
hideLogo={hideLogo}
onProjectSelect={(project) => {
this.setSelectedProject(project);
}}
onDeviceChange={(_device) => this.setDevice(_device)}
/>
<div className="language-select-container">
<div className="language-select-warpper">
<img className="language-icon" src={languageImg} style={{ width: "18px" }} alt="" />
<Select
className="language-select"
value={language}
label={t("language")}
IconComponent={CustomIcon}
onChange={(e) => {
let lang = e.target.value;
this.setState({
language: lang,
});
i18n.changeLanguage(lang);
localStorage.setItem("lang", lang);
}}
>
<MenuItem style={{ fontSize: "14px" }} value="en">
English
</MenuItem>
<MenuItem style={{ fontSize: "14px" }} value="zh">
简体中文
</MenuItem>
</Select>
{
<Pane
isMobile={isMobile}
projects={projects}
device={device}
loading={loading}
hideLogo={hideLogo}
onProjectSelect={(project) => {
this.setSelectedProject(project);
}}
onDeviceChange={(_device) => this.setDevice(_device)}
/>
}
{
!isMobile &&
<div className="language-select-container">
<div className="language-select-warpper">
<img className="language-icon" src={languageImg} style={{ width: "18px" }} alt="" />
<Select
className="language-select"
value={language}
label={t("language")}
IconComponent={CustomIcon}
onChange={(e) => {
let lang = e.target.value;
this.setState({
language: lang,
});
i18n.changeLanguage(lang);
localStorage.setItem("lang", lang);
}}
>
<MenuItem style={{ fontSize: "14px" }} value="en">
English
</MenuItem>
<MenuItem style={{ fontSize: "14px" }} value="zh">
简体中文
</MenuItem>
</Select>
</div>
</div>
</div>
}
<div
style={{
display: "flex",
@ -326,20 +328,13 @@ class App extends React.Component {
backgroundRepeat: "no-repeat",
}}
>
{mode === "normal" ? (
<DeviceFrame
htmlUrl={this.selectedProjectUrl}
device={device}
qrDataUrl={dataUrl}
refreshQrCode={() => this.refreshQrCode()}
/>
) : (
<SettingFrame
setting={selectedProject?.TextObjStr}
settingValue={this.projectSettingValue}
generate={(value) => this.UpdateSetting(value)}
/>
)}
<DeviceFrame
isMobile={isMobile}
htmlUrl={this.selectedProjectUrl}
device={device}
qrDataUrl={dataUrl}
refreshQrCode={() => this.refreshQrCode()}
/>
</div>
</div>
);

View File

@ -15,6 +15,7 @@
right: 24px;
bottom: 24px;
cursor: pointer;
z-index: 1000;
}
.qrCode {

View File

@ -21,12 +21,18 @@ var configMap = {
width: "666px",
height: "321px",
offsetv: "4px",
imgStyle: {
marginTop: '-5px',
},
},
"android-v": {
bkg: androidVPng,
width: "321px",
height: "666px",
offsetv: "5px",
imgStyle: {
marginLeft: '2px',
},
},
"iphone-h": {
bkg: iphoneVPng,
@ -39,35 +45,37 @@ var configMap = {
},
"iphone-v": {
bkg: iphoneVPng,
width: "322px",
height: "693px",
width: "325px",
height: "690px",
styles: {
borderRadius: '13px'
}
},
},
"ipad-h": {
bkg: ipadHPng,
rotate: true,
width: "458px",
height: "326px",
width: "646px",
height: "478px",
offsetv: "5px",
imgStyle: {
transform: 'rotate(-90deg) scale(1.4)',
marginTop: '-2px',
transform: 'translate(-50%, -50%) rotate(-90deg)',
},
styles: {
transform: "translate(-50%, -50%) scale(1.42)",
transform: "translate(-50%, -50%)",
}
},
"ipad-v": {
bkg: ipadHPng,
width: "326px",
height: "458px",
width: "478px",
height: "646px",
offsetv: "5px",
imgStyle: {
transform: 'scale(1.4)',
marginTop: '-2px',
transform: 'translate(-50%, -50%)',
},
styles: {
transform: "translate(-50%, -50%) scale(1.42)",
transform: "translate(-50%, -50%)",
}
},
};
@ -77,11 +85,44 @@ function DeviceFrame(props) {
var [cacheKey, setCacheKey] = useState(new Date().getTime());
var [openPopup, setOpenPopup] = useState(false);
var [absoluteUrl, setAbsoluteUrl] = useState("");
var [isMobile, setIsMobile] = useState(props.isMobile);
const { t } = useTranslation();
useEffect(() => {
setConfig(configMap[props.device]);
}, [props.device, config]);
// 将宽度和高度的值转换为数字并增加10%
const current = JSON.parse(JSON.stringify(configMap[props.device]))
const w = parseFloat(current.width)
const h = parseFloat(current.height)
current.width = (w * 1.1) + 'px';
current.height = (h * 1.1) + 'px';
let bgW = (w * 1.1) + 32;
let bgH = (h * 1.1) + 32;
// 竖屏
if (props.device === 'android-v') {
bgW -= 12;
} else if (props.device === 'android-h') {
// 横屏
bgH -= 12;
}
// 平板
if (props.device === 'ipad-v') {
bgW += 28;
bgH += 28;
} else if (props.device === 'ipad-h') {
// 横屏
bgW += 28;
bgH += 28;
}
if (current.rotate) {
current.imgStyle = Object.assign({ height: bgW, width: bgH }, current.imgStyle || {})
} else {
current.imgStyle = Object.assign({ width: bgW, height: bgH }, current.imgStyle || {})
}
setConfig(current);
// setConfig(configMap[props.device]);
}, [props.device]);
var refresh = () => setCacheKey(new Date().getTime());
@ -94,19 +135,22 @@ function DeviceFrame(props) {
return (
<div className="deviceFrameContainer">
<img src={refreshButtonPng} alt="refresh" onClick={() => refresh()} className="refreshButton" />
{props.qrDataUrl && (
{props.qrDataUrl && !isMobile && (
<div className="qrCode">
<img src={props.qrDataUrl} alt="qr code" />
<p style={{ margin: "0", }}>
{t("scan")}
<CopyToClipboard text={absoluteUrl} onCopy={() => setOpenPopup(true)}>
<img style={{ cursor: "pointer", width: "20px", height: "20px" }} src={copyPng} alt="复制链接" />
<img style={{ cursor: "pointer", width: "20px", height: "20px", marginLeft: '4px' }} src={copyPng} alt="复制链接" />
</CopyToClipboard>
</p>
</div>
)}
<Snackbar
open={openPopup}
onClose={() => setOpenPopup(false)}
@ -119,28 +163,57 @@ function DeviceFrame(props) {
{t("copySuccess")}
</Alert>
</Snackbar>
<div>
<img src={config.bkg} alt="background" style={{ position: "relative", zIndex: 100, transform: config.rotate ? "rotate(-90deg)" : "", pointerEvents: 'none', ...config.imgStyle }} />
{props.htmlUrl && (
<iframe
id="deviceFrame"
style={{
{
!isMobile ?
<div>
<img src={config.bkg} alt="background" style={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%) scale(1.007)",
paddingBottom: config.offsetv,
...config.styles
}}
allow="clipboard-read; clipboard-write *"
title="preview"
src={absoluteUrl + "&cacheKey=" + cacheKey}
width={config.width}
height={config.height}
frameBorder={"0"}
/>
)}
</div>
zIndex: 100,
transform: `translate(-50%, -50%) ${config.rotate ? "rotate(-90deg)" : ''}`,
pointerEvents: 'none',
...config.imgStyle
}} />
{props.htmlUrl && (
<iframe
id="deviceFrame"
style={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%) scale(1.007)",
paddingBottom: config.offsetv,
...config.styles
}}
allow="clipboard-read; clipboard-write *"
title="preview"
src={absoluteUrl + "&cacheKey=" + cacheKey}
width={config.width}
height={config.height}
frameBorder={"0"}
/>
)}
</div> : <div>
{
props.htmlUrl && <iframe
id="deviceFrame_mobile"
allow="clipboard-read; clipboard-write *"
title="preview"
src={absoluteUrl + "&cacheKey=" + cacheKey}
style={{
position: 'fixed',
inset: 0,
width: '100vw',
height: window.innerHeight,
}}
frameBorder={"0"}
/>
}
</div>
}
</div>
);
}

View File

@ -9,6 +9,56 @@
position: relative;
}
.selectPager {
left: 25px !important;
/* width: 319px !important; */
}
.Pane.mobile {
position: relative;
left: 0;
top: 0;
bottom: 0;
width: 60vw;
height: 100vh;
background-color: #535353;
z-index: 1000;
overflow: hidden;
transition: width 0.2s linear;
}
.flod-menu-btn-warpper {
position: fixed;
right: 12px;
top: 10px;
padding: 6px;
border-radius: 6px;
z-index: 1000;
display: flex;
background-color: #535353;
}
.flod-menu-btn-warpper .flod-menu-btn {
width: 28px;
height: 28px;
transition: all 0.2s linear;
}
.Pane.mobile.fold {
padding: 0;
width: 0;
}
.logo_mobile {
position: absolute;
width: 90%;
bottom: 20px;
left: 0;
right: 0;
margin: auto;
display: block;
}
.modeSelect {
width: 100%;
border: none;
@ -38,11 +88,6 @@
cursor: pointer;
}
.selectPager {
left: 25px !important;
width: 319px !important;
}
.bottomLogo {
position: absolute;
width: 322px;

View File

@ -15,6 +15,7 @@ import horizentalButton from "../../images/horizental-button.png";
import verticalChecked from "../../images/vertical-button-checked.png";
import verticalButton from "../../images/vertical-button.png";
import modeSelectPng from "../../images/mode-select.png";
import menuIcon from "../../images/menu.png";
import { useTranslation } from "react-i18next";
import SvgIcon from '@mui/material/SvgIcon';
@ -26,7 +27,7 @@ function CustomIcon(props) {
);
}
var deviceConfigs = [
const deviceConfigs = [
{
name: "iPhone",
icon: iphonePng,
@ -51,16 +52,12 @@ var deviceConfigs = [
];
function Pane(props) {
var [mode, setMode] = useState(props.mode);
var [isMobile] = useState(props.isMobile);
var [device, setDevice] = useState(props.device);
var [project, setProject] = useState(props.project);
const { t } = useTranslation();
var modeChange = (e) => {
var _mode = e.target.value;
setMode(_mode);
props.onModeChange(e.target.value);
};
const [foldPanel, setFoldPanel] = useState(props.isMobile ? true : false);
const { t } = useTranslation();
var deviceChange = (_device) => {
setDevice(_device);
@ -70,6 +67,7 @@ function Pane(props) {
var projectSelect = (e) => {
var projectName = e.target.value;
setProject(projectName);
setFoldPanel(true)
props.onProjectSelect(projectName);
};
@ -77,8 +75,26 @@ function Pane(props) {
props.projects.length && !project && setProject(props.projects[0]);
}, [props.projects]);
return (
<div className="Pane">
<div className={`Pane ${isMobile ? 'mobile' : ''} ${foldPanel ? 'fold' : ''}`} style={{ height: window.innerHeight }}>
{
isMobile &&
<div className="flod-menu-btn-warpper">
<img
onClick={() => {
setFoldPanel(!foldPanel)
}}
src={menuIcon}
alt="menu"
className="flod-menu-btn"
style={{
transform: !foldPanel ? 'rotate(-90deg)' : '',
}}
/>
</div>
}
<div>
{props.loading ? (
<CircularProgress color="inherit" />
@ -98,9 +114,6 @@ function Pane(props) {
borderRadius: '5px',
color: "white",
boxShadow: '0px 3px 0px 0px rgba(0, 0, 0, 0.3)',
// '&.MuiOutlinedInput-notchedOutline': {
// borderColor: '#757575', // 设置焦点时的边框颜色为红色
// },
'&.Mui-focused': {
borderColor: '#757575',
'&.MuiOutlinedInput-notchedOutline': {
@ -124,48 +137,52 @@ function Pane(props) {
)}
</div>
<List
sx={{
paddingTop: '20px'
}}
>
{deviceConfigs.map((_device) => (
<ListItem
key={_device.name}
sx={{
display: "flex",
textAlign: "center",
justifyContent: "space-between",
borderRadius: '5px',
background: '#535353',
border: '1px solid #757575',
boxShadow: '0px 3px 0px 0px rgba(0, 0, 0, 0.3)',
paddingLeft: '23px',
paddingRight: '20px',
marginBottom: '14px'
}}>
<div style={{ display: "flex", flexDirection: 'column', justifyContent: 'center', alignItems: "center", width: '98px' }}>
<img className="deviceIcon" style={{ height: _device.name === 'iPad' ? '54px' : '76px' }} src={_device.icon} alt={_device.name} />
<img className="deviceText" src={_device.text} alt={_device.name} />
</div>
<div className="deviceContent">
<div className="deviceButtons">
<button className={`pane-btn ${device === _device.horizental ? "checked" : ""}`} onClick={() => deviceChange(_device.horizental)}>
{t("horizontal")}
</button>
<button className={`pane-btn ${device === _device.vertical ? "checked" : ""}`} onClick={() => deviceChange(_device.vertical)}>
{t("vertical")}
</button>
{/* <img src={device === _device.horizental ? horizentalChecked : horizentalButton} alt="horizental" onClick={() => deviceChange(_device.horizental)} />
<img src={device === _device.vertical ? verticalChecked : verticalButton} alt="vertical" onClick={() => deviceChange(_device.vertical)} /> */}
{
!isMobile && <List
sx={{
paddingTop: '20px'
}}
>
{deviceConfigs.map((_device) => (
<ListItem
key={_device.name}
sx={{
display: "flex",
textAlign: "center",
justifyContent: "space-between",
borderRadius: '5px',
background: '#535353',
border: '1px solid #757575',
boxShadow: '0px 3px 0px 0px rgba(0, 0, 0, 0.3)',
paddingLeft: '23px',
paddingRight: '20px',
marginBottom: '14px'
}}>
<div style={{ display: "flex", flexDirection: 'column', justifyContent: 'center', alignItems: "center", width: '98px' }}>
<img className="deviceIcon" style={{ height: _device.name === 'iPad' ? '54px' : '76px' }} src={_device.icon} alt={_device.name} />
<img className="deviceText" src={_device.text} alt={_device.name} />
</div>
</div>
</ListItem>
))}
</List>
<div className="deviceContent">
<div className="deviceButtons">
<button className={`pane-btn ${device === _device.horizental ? "checked" : ""}`} onClick={() => deviceChange(_device.horizental)}>
{t("horizontal")}
</button>
<button className={`pane-btn ${device === _device.vertical ? "checked" : ""}`} onClick={() => deviceChange(_device.vertical)}>
{t("vertical")}
</button>
{/* <img src={device === _device.horizental ? horizentalChecked : horizentalButton} alt="horizental" onClick={() => deviceChange(_device.horizental)} />
<img src={device === _device.vertical ? verticalChecked : verticalButton} alt="vertical" onClick={() => deviceChange(_device.vertical)} /> */}
</div>
</div>
</ListItem>
))}
</List>
}
{!props.hideLogo && <div className="bottomLogo"><img src={logoPanePng} alt="logo" width={"100%"} /></div>}
{(!props.hideLogo && !isMobile) && <div className="bottomLogo"><img src={logoPanePng} alt="logo" width={"100%"} /></div>}
{(!props.hideLogo && isMobile) && <img src={logoPanePng} className="logo_mobile" alt="logo" width={"100%"} />}
</div>
);
}

View File

@ -1,5 +1,6 @@
// var BaseUrl = "https://api.soyootech.com/";
var BaseUrl = "api/";
var BaseUrl = "https://api.soyootech.com/";
// var BaseUrl = "api/";
export async function UserLogin(loginForm) {
try {
var response = await fetch(BaseUrl + "SoyooUser/previewlogin", {

BIN
src/images/menu.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB