add login

master
Aaron Yu 2022-09-03 11:18:59 +08:00
parent b18e96d1b0
commit 7e44a00d30
6 changed files with 954 additions and 481 deletions

1118
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,9 +4,9 @@
"private": true, "private": true,
"homepage": "/preview", "homepage": "/preview",
"dependencies": { "dependencies": {
"@emotion/react": "^11.7.1", "@emotion/react": "^11.10.4",
"@emotion/styled": "^11.6.0", "@emotion/styled": "^11.10.4",
"@mui/material": "^5.2.5", "@mui/material": "^5.10.3",
"@testing-library/jest-dom": "^5.16.1", "@testing-library/jest-dom": "^5.16.1",
"@testing-library/react": "^12.1.2", "@testing-library/react": "^12.1.2",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
@ -18,6 +18,7 @@
"react": "^17.0.2", "react": "^17.0.2",
"react-copy-to-clipboard": "^5.0.4", "react-copy-to-clipboard": "^5.0.4",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-modal-login": "^2.0.7",
"react-scripts": "5.0.0", "react-scripts": "5.0.0",
"web-vitals": "^2.1.2" "web-vitals": "^2.1.2"
}, },

View File

@ -38,3 +38,7 @@
transform: rotate(360deg); transform: rotate(360deg);
} }
} }
.MuiFormControlLabel-label {
font-size: 13px !important;
}

View File

@ -1,143 +1,265 @@
import './App.css'; import "./App.css";
import * as ProjectApi from './apis/projectApi' import * as ProjectApi from "./apis/projectApi";
import Pane from './Components/pane'; import * as LoginApi from "./apis/loginApi";
import DeviceFrame from './Components/deviceFrame'; import Pane from "./Components/pane";
import waterMarkPng from './images/water-mark.png' import DeviceFrame from "./Components/deviceFrame";
import React from 'react'; import waterMarkPng from "./images/water-mark.png";
import SettingFrame from './Components/settingsFrame'; import React from "react";
import QrCode from 'qrcode' import SettingFrame from "./Components/settingsFrame";
import { getProjectSettingValue, setProjectSetting } from './storage'; import QrCode from "qrcode";
import {
getLoginInfo,
getProjectSettingValue,
setLoginInfo,
setProjectSetting,
} from "./storage";
import Button from "@mui/material/Button";
import TextField from "@mui/material/TextField";
import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
import DialogTitle from "@mui/material/DialogTitle";
import Checkbox from "@mui/material/Checkbox";
import FormControlLabel from "@mui/material/FormControlLabel";
class App extends React.Component { class App extends React.Component {
constructor() { constructor() {
super(); super();
this.state = { this.state = {
mode: 'normal', mode: "normal",
projects: [], projects: [],
selectedProject: {}, selectedProject: {},
selectedProjectName: '', selectedProjectName: "",
device: 'android-h', device: "android-h",
htmlUrl: '', htmlUrl: "",
dataUrl: '', dataUrl: "",
loading: false loading: false,
} loginOpen: false,
showLoginError: false,
loginForm: {
account: "",
password: "",
keepLogin: false,
},
};
} }
componentDidMount() { componentDidMount() {
this.fetchData(); const loginInfo = getLoginInfo();
this.refreshQrCode() if (loginInfo) {
this.fetchData();
this.refreshQrCode();
} else {
this.setState({ loginOpen: true });
}
} }
login = async () => {
var { account, password, keepLogin } = this.state.loginForm;
var user = await LoginApi.UserLogin({ account, password });
if (user) {
this.setState({
loginOpen: false,
});
if (keepLogin) {
setLoginInfo(user);
}
this.fetchData();
this.refreshQrCode();
} else {
this.setState({
showLoginError: true,
});
}
};
refreshQrCode() { refreshQrCode() {
var {selectedProject} = this.state; var { selectedProject } = this.state;
selectedProject.HtmlUrl && QrCode.toDataURL([{ data: this.selectedProjectUrl, mode: 'byte'}], { width: 120 }) selectedProject.HtmlUrl &&
.then((dataUrl) => { QrCode.toDataURL([{ data: this.selectedProjectUrl, mode: "byte" }], {
this.setState({ width: 120,
dataUrl: dataUrl }).then((dataUrl) => {
}) this.setState({
}) dataUrl: dataUrl,
});
});
} }
get selectedProjectUrl () { get selectedProjectUrl() {
var {selectedProject} = this.state; var { selectedProject } = this.state;
var settingValue = getProjectSettingValue(selectedProject?.Name) || [1, 1, 1] var settingValue = getProjectSettingValue(selectedProject?.Name) || [
var rawUrl = selectedProject?.HtmlUrl ? encodeURI(selectedProject?.HtmlUrl) : "" 1, 1, 1,
];
var rawUrl = selectedProject?.HtmlUrl
? encodeURI(selectedProject?.HtmlUrl)
: "";
if (rawUrl) { if (rawUrl) {
rawUrl += `?datanumber=${settingValue[0]}&datanumber1=${settingValue[1]}&datanumber2=${settingValue[2]}&lunaOrHtml=false` rawUrl += `?datanumber=${settingValue[0]}&datanumber1=${settingValue[1]}&datanumber2=${settingValue[2]}&lunaOrHtml=false`;
} }
return rawUrl return rawUrl;
} }
async setSelectedProject(selectedProjectName) { async setSelectedProject(selectedProjectName) {
this.setState({ this.setState({
selectedProjectName: selectedProjectName, selectedProjectName: selectedProjectName,
}); });
console.log('selected:', selectedProjectName) console.log("selected:", selectedProjectName);
await this.updateSelectedProject(selectedProjectName) await this.updateSelectedProject(selectedProjectName);
} }
async updateSelectedProject (projectName) { async updateSelectedProject(projectName) {
var projectSetting = await ProjectApi.getProjectSetting(projectName) var projectSetting = await ProjectApi.getProjectSetting(projectName);
this.setState({ this.setState({
selectedProject: projectSetting selectedProject: projectSetting,
}); });
} }
setDevice(selected) { setDevice(selected) {
this.setState({ this.setState({
device: selected device: selected,
}); });
} }
setMode(mode) { setMode(mode) {
this.setState({ this.setState({
mode: mode mode: mode,
});
}
setLoginForm(form) {
this.setState({
loginForm: {
...this.state.loginForm,
...form,
},
}); });
} }
async fetchData() { async fetchData() {
this.setState({ this.setState({
loading: true loading: true,
}) });
var projectNames = await this.fetchProjects() || ['无项目']; var projectNames = (await this.fetchProjects()) || ["无项目"];
this.setState({ this.setState({
projects: projectNames, projects: projectNames,
selectedProjectName: projectNames[0], selectedProjectName: projectNames[0],
loading: false loading: false,
}); });
await this.updateSelectedProject(projectNames[0]) await this.updateSelectedProject(projectNames[0]);
this.refreshQrCode() this.refreshQrCode();
} }
async fetchProjects() { async fetchProjects() {
return await ProjectApi.getProjects(); return await ProjectApi.getProjects();
} }
get projectSettingValue () { get projectSettingValue() {
return getProjectSettingValue(this.state.selectedProjectName) return getProjectSettingValue(this.state.selectedProjectName);
} }
UpdateSetting(obj) { UpdateSetting(obj) {
setProjectSetting(this.state.selectedProject.Name, [+obj.topType, +obj.centreType, +obj.middleType]) setProjectSetting(this.state.selectedProject.Name, [
+obj.topType,
+obj.centreType,
+obj.middleType,
]);
} }
render() { render() {
var { mode, device, projects, selectedProject, dataUrl, loading } = this.state; var {
mode,
device,
projects,
selectedProject,
dataUrl,
loading,
loginOpen,
loginForm,
} = this.state;
return ( return (
<div className="App"> <div className="App">
<Dialog open={loginOpen}>
<DialogTitle>登录</DialogTitle>
<DialogContent>
<TextField
autoFocus
margin="dense"
id="name"
label="账号"
fullWidth
value={loginForm.account}
variant="standard"
onChange={(e) => this.setLoginForm({ account: e.target.value })}
/>
<TextField
autoFocus
margin="dense"
id="name"
label="密码"
type={"password"}
fullWidth
value={loginForm.password}
variant="standard"
onChange={(e) => this.setLoginForm({ password: e.target.value })}
/>
</DialogContent>
<DialogActions>
{this.state.showLoginError && (
<span style={{ color: "red", margin: "0 auto 0 10px" }}>
账号或密码错误
</span>
)}
<FormControlLabel
control={
<Checkbox
checked={loginForm.keepLogin}
onChange={(_, checked) =>
this.setLoginForm({ keepLogin: checked })
}
/>
}
label="保持登录状态7天"
/>
<Button onClick={() => this.login()}>提交</Button>
</DialogActions>
</Dialog>
<Pane <Pane
mode={mode} mode={mode}
onModeChange={(_mode) => this.setMode(_mode) } onModeChange={(_mode) => this.setMode(_mode)}
projects={projects} projects={projects}
device={device} device={device}
loading={loading} loading={loading}
onProjectSelect={(project) => { onProjectSelect={(project) => {
this.setSelectedProject(project) this.setSelectedProject(project);
}} }}
onDeviceChange={(_device) => this.setDevice(_device)}/> onDeviceChange={(_device) => this.setDevice(_device)}
<div style={{ />
display: 'flex', <div
flex: 1, style={{
alignItems: 'center', display: "flex",
backgroundImage: `url('${waterMarkPng}')`, flex: 1,
backgroundPositionX: 'right', alignItems: "center",
backgroundPositionY: 'bottom', backgroundImage: `url('${waterMarkPng}')`,
backgroundRepeat: 'no-repeat' backgroundPositionX: "right",
}}> backgroundPositionY: "bottom",
{ backgroundRepeat: "no-repeat",
mode === "normal" }}
? <DeviceFrame >
{mode === "normal" ? (
<DeviceFrame
htmlUrl={this.selectedProjectUrl} htmlUrl={this.selectedProjectUrl}
device={device} device={device}
qrDataUrl={dataUrl} qrDataUrl={dataUrl}
refreshQrCode={() => this.refreshQrCode()}/> refreshQrCode={() => this.refreshQrCode()}
: <SettingFrame />
) : (
<SettingFrame
setting={selectedProject?.TextObjStr} setting={selectedProject?.TextObjStr}
settingValue={this.projectSettingValue} settingValue={this.projectSettingValue}
generate={(value) => this.UpdateSetting(value)}/> generate={(value) => this.UpdateSetting(value)}
} />
)}
</div> </div>
</div> </div>
); );

View File

@ -0,0 +1,20 @@
var BaseUrl = "http://api.soyootech.com/";
export async function UserLogin(loginForm) {
try {
var response = await fetch(BaseUrl + "SoyooUser/previewlogin", {
body: JSON.stringify({
account: loginForm.account,
password: loginForm.password,
}),
headers: {
"Content-Type": "application/json",
},
method: "POST",
});
var result = await response.json();
return result;
} catch (error) {
console.log(error);
return null;
}
}

View File

@ -1,14 +1,24 @@
import ls from 'localstorage-slim' import ls from "localstorage-slim";
import * as Utils from './utils' import * as Utils from "./utils";
const settingPrefix = 'ps_' const settingPrefix = "ps_";
export const setProjectSetting = (projectName, settingValueArr) => { export const setProjectSetting = (projectName, settingValueArr) => {
var tenant = Utils.getTenant() var tenant = Utils.getTenant();
ls.set(settingPrefix + tenant + '_' + projectName, settingValueArr, { ttl: 3600 * 24 * 90 }) ls.set(settingPrefix + tenant + "_" + projectName, settingValueArr, {
} ttl: 3600 * 24 * 90,
});
};
export const getProjectSettingValue = (projectName) => { export const getProjectSettingValue = (projectName) => {
var tenant = Utils.getTenant() var tenant = Utils.getTenant();
return ls.get(settingPrefix + tenant + '_' + projectName) || [1, 1, 1] return ls.get(settingPrefix + tenant + "_" + projectName) || [1, 1, 1];
} };
export const setLoginInfo = (loginInfo) => {
ls.set("loginInfo", loginInfo, { ttl: 3600 * 24 * 7 });
};
export const getLoginInfo = () => {
return ls.get("loginInfo");
};