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 { .App-header {
background-color: #282c34; background-color: #282c34;
min-height: 100vh; min-height: 100vh;
@ -62,7 +90,7 @@
} }
.pane-btn.checked { .pane-btn.checked {
border: 3px solid #00DE7A; border: 3px solid #00de7a;
} }
.pane-btn + .pane-btn { .pane-btn + .pane-btn {
@ -94,8 +122,8 @@
.language-select-container .language-select { .language-select-container .language-select {
width: 156px; width: 156px;
height: 42px; height: 42px;
background-color: #36383A; background-color: #36383a;
color: #EEEEEE; color: #eeeeee;
font-size: 14px; font-size: 14px;
display: flex; display: flex;
align-items: center; align-items: center;
@ -104,8 +132,8 @@
.language-select-warpper { .language-select-warpper {
position: relative; position: relative;
border-radius: 5px; border-radius: 5px;
background: #36383A; background: #36383a;
border: 1px solid #5B5B5B; border: 1px solid #5b5b5b;
box-shadow: 0px 3px 0px 0px rgba(0, 0, 0, 0.3); 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 i18n from "i18next";
import languageImg from "./images/language.png"; import languageImg from "./images/language.png";
import Arrow from './images/arrow.svg' import Arrow from './images/arrow.svg'
import logoPanePng from "./images/logo-pane.png";
import SvgIcon from '@mui/material/SvgIcon'; 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 { class App extends React.Component {
constructor(props) { constructor(props) {
super(); super();
this.state = { this.state = {
mode: "normal",
projects: [], projects: [],
selectedProject: {}, selectedProject: {},
selectedProjectName: "", selectedProjectName: "",
@ -61,10 +66,16 @@ class App extends React.Component {
keepLogin: false, keepLogin: false,
}, },
language: localStorage.getItem("lang") ?? "zh", language: localStorage.getItem("lang") ?? "zh",
isMobile: isMobile(),
}; };
this.t = props.t; this.t = props.t;
} }
componentDidMount() { componentDidMount() {
window.addEventListener('resize', () => {
this.setState({ isMobile: isMobile() });
})
const loginInfo = getLoginInfo(); const loginInfo = getLoginInfo();
var tenant = utils.getTenant(); var tenant = utils.getTenant();
const hideLogo = queryString.parseUrl(window.location.href)?.query 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) { setLoginForm(form) {
this.setState({ this.setState({
loginForm: { loginForm: {
@ -208,18 +213,7 @@ class App extends React.Component {
} }
render() { render() {
var { const { device, projects, dataUrl, loading, loginOpen, loginForm, hideLogo, language, isMobile } = this.state;
mode,
device,
projects,
selectedProject,
dataUrl,
loading,
loginOpen,
loginForm,
hideLogo,
language,
} = this.state;
const { t } = this.props; const { t } = this.props;
return ( return (
@ -277,44 +271,52 @@ class App extends React.Component {
<Button onClick={() => this.login()}>{t("submit")}</Button> <Button onClick={() => this.login()}>{t("submit")}</Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
<Pane
mode={mode} {
onModeChange={(_mode) => this.setMode(_mode)} <Pane
projects={projects} isMobile={isMobile}
device={device} projects={projects}
loading={loading} device={device}
hideLogo={hideLogo} loading={loading}
onProjectSelect={(project) => { hideLogo={hideLogo}
this.setSelectedProject(project); onProjectSelect={(project) => {
}} this.setSelectedProject(project);
onDeviceChange={(_device) => this.setDevice(_device)} }}
/> 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" !isMobile &&
value={language} <div className="language-select-container">
label={t("language")} <div className="language-select-warpper">
IconComponent={CustomIcon} <img className="language-icon" src={languageImg} style={{ width: "18px" }} alt="" />
onChange={(e) => { <Select
let lang = e.target.value; className="language-select"
this.setState({ value={language}
language: lang, label={t("language")}
}); IconComponent={CustomIcon}
i18n.changeLanguage(lang); onChange={(e) => {
localStorage.setItem("lang", lang); let lang = e.target.value;
}} this.setState({
> language: lang,
<MenuItem style={{ fontSize: "14px" }} value="en"> });
English i18n.changeLanguage(lang);
</MenuItem> localStorage.setItem("lang", lang);
<MenuItem style={{ fontSize: "14px" }} value="zh"> }}
简体中文 >
</MenuItem> <MenuItem style={{ fontSize: "14px" }} value="en">
</Select> English
</MenuItem>
<MenuItem style={{ fontSize: "14px" }} value="zh">
简体中文
</MenuItem>
</Select>
</div>
</div> </div>
</div> }
<div <div
style={{ style={{
display: "flex", display: "flex",
@ -326,20 +328,13 @@ class App extends React.Component {
backgroundRepeat: "no-repeat", backgroundRepeat: "no-repeat",
}} }}
> >
{mode === "normal" ? ( <DeviceFrame
<DeviceFrame isMobile={isMobile}
htmlUrl={this.selectedProjectUrl} htmlUrl={this.selectedProjectUrl}
device={device} device={device}
qrDataUrl={dataUrl} qrDataUrl={dataUrl}
refreshQrCode={() => this.refreshQrCode()} refreshQrCode={() => this.refreshQrCode()}
/> />
) : (
<SettingFrame
setting={selectedProject?.TextObjStr}
settingValue={this.projectSettingValue}
generate={(value) => this.UpdateSetting(value)}
/>
)}
</div> </div>
</div> </div>
); );

View File

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

View File

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

View File

@ -9,6 +9,56 @@
position: relative; 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 { .modeSelect {
width: 100%; width: 100%;
border: none; border: none;
@ -38,11 +88,6 @@
cursor: pointer; cursor: pointer;
} }
.selectPager {
left: 25px !important;
width: 319px !important;
}
.bottomLogo { .bottomLogo {
position: absolute; position: absolute;
width: 322px; width: 322px;

View File

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

View File

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

BIN
src/images/menu.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB