2个文件已删除
2 文件已重命名
4个文件已添加
12个文件已修改
| New file |
| | |
| | | package com.zy.acs.common.enums; |
| | | |
| | | public enum SystemModeType { |
| | | |
| | | ONLINE, |
| | | OFFLINE, |
| | | ; |
| | | |
| | | } |
| | |
| | | import DataProvider from "./config/dataProvider"; |
| | | import Dashboard from "./page/dashboard/Dashboard"; |
| | | import Settings from "./page/settings/Settings"; |
| | | import Login from "./page/login/Login"; |
| | | import Login from "./page/login"; |
| | | import * as Common from './utils/common' |
| | | import { themes } from './themes/themes'; |
| | | import { SPA_NAME, SPA_VERSION, DEFAULT_THEME_NAME, DEFAULT_THEME_MODE, DATA_PROVIDER_SPRING } from "./config/setting"; |
| | |
| | | import request from '../../utils/request'; |
| | | |
| | | export async function getSystemInfo() { |
| | | const res = await request.get('/system/info'); |
| | | if (res.data.code === 200) { |
| | | return res.data.data; |
| | | } |
| | | return Promise.reject(new Error(res.data.msg)); |
| | | } |
| | | |
| | | export async function tenants(_params) { |
| | | const res = await request.get('/tenant/list', { params: _params }); |
| | | if (res.data.code === 200) { |
| | | return res.data.data; |
| | | } |
| | | return Promise.reject(new Error(res.data.msg)); |
| | | } |
| | | |
| | | export async function login(_params) { |
| | | const res = await request.post('/login', _params); |
| | | if (res.data.code === 200) { |
| | |
| | | return Promise.reject(new Error(res.data.msg)); |
| | | } |
| | | |
| | | export async function register(_params) { |
| | | const res = await request.post('/register', _params); |
| | | return res.data; |
| | | } |
| | | |
| | | export async function menus(_params) { |
| | | return await request.get('/auth/menu', _params); |
| | | if (res.data.code === 200) { |
| | | return res.data.data; |
| | | } |
| | | return Promise.reject(new Error(res.data.msg)); |
| | | } |
| | | |
| | | export async function sendEmailCode(_params) { |
| | | const res = await request.get('/email/code', { params: _params }); |
| | | return res.data; |
| | | } |
| | |
| | | |
| | | export const EDIT_MODE = 'pessimistic'; // pessimistic | undoable |
| | | |
| | | export const LOGIN_BACKGROUND = 'image'; // image | media |
| | | export const LOGIN_BACKGROUND = 'media'; // image | media |
| | | |
| | | export const CUSTOM_PAGES_DATA_INTERVAL = 1000; |
| | |
| | | } |
| | | }, |
| | | page: { |
| | | login: { |
| | | title: 'Welcome to', |
| | | footer: '', |
| | | tenant: 'Company', |
| | | email: 'Email Address', |
| | | username: 'Username', |
| | | password: 'Password', |
| | | confirmPwd: 'Confirm Password', |
| | | code: 'Verification Code', |
| | | tab: { |
| | | login: 'SIGN IN', |
| | | register: 'SIGN UP', |
| | | }, |
| | | button: { |
| | | login: 'SIGN IN', |
| | | register: 'SIGN UP', |
| | | code: 'Send Code', |
| | | }, |
| | | }, |
| | | code: { |
| | | dirRule: { |
| | | helper: 'Select one direction to disable; other directions remain available.', |
| | |
| | | } |
| | | }, |
| | | page: { |
| | | login: { |
| | | title: '欢迎使用', |
| | | footer: '', |
| | | tenant: '公司', |
| | | email: '邮箱地址', |
| | | username: '登录账号', |
| | | password: '密码', |
| | | confirmPwd: '确认密码', |
| | | code: '验证码', |
| | | tab: { |
| | | login: '登录', |
| | | register: '注册', |
| | | }, |
| | | button: { |
| | | login: '登录', |
| | | register: '注册', |
| | | code: '获取验证码', |
| | | }, |
| | | }, |
| | | code: { |
| | | dirRule: { |
| | | helper: '选择一个方向禁用,其余方向保持可用', |
| | |
| | | }); |
| | | |
| | | const handleResize = () => { |
| | | if (!contentRef) { return; } |
| | | if (!contentRef.current || !player) { |
| | | return; |
| | | } |
| | | const width = contentRef.current.offsetWidth; |
| | | const height = contentRef.current.offsetHeight; |
| | | player.resize(width, height); |
| | |
| | | }, [sidebarOpen]); |
| | | |
| | | useEffect(() => { |
| | | if (!player) { |
| | | return; |
| | | } |
| | | player.setTheme(themeMode); |
| | | Tool.setThemeMode(themeMode); |
| | | }, [themeMode]) |
| | |
| | | import * as React from 'react'; |
| | | import { useState } from 'react'; |
| | | import React, { useState, useRef, useEffect, useMemo } from "react"; |
| | | import { useLocation } from 'react-router-dom'; |
| | | import { |
| | | Avatar, |
| | | Box, |
| | | Button, |
| | | Card, |
| | | CardActions, |
| | | CircularProgress, |
| | | Typography, |
| | | Button, |
| | | TextField, |
| | | Stack, |
| | | Autocomplete, |
| | | InputAdornment, |
| | | IconButton, |
| | | } from '@mui/material'; |
| | | import LockIcon from '@mui/icons-material/Lock'; |
| | | import { |
| | | Form, |
| | | required, |
| | | TextInput, |
| | | useTranslate, |
| | | useLogin, |
| | | useNotify, |
| | | } from 'react-admin'; |
| | | import { LOGIN_BACKGROUND } from '@/config/setting'; |
| | | import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form"; |
| | | import Visibility from '@mui/icons-material/Visibility'; |
| | | import VisibilityOff from '@mui/icons-material/VisibilityOff'; |
| | | |
| | | const Login = () => { |
| | | const [loading, setLoading] = useState(false); |
| | | const Login = (props) => { |
| | | const translate = useTranslate(); |
| | | |
| | | const notify = useNotify(); |
| | | const login = useLogin(); |
| | | const location = useLocation(); |
| | | |
| | | const handleSubmit = (auth) => { |
| | | const { control, handleSubmit, watch, setValue, getValues, setError, clearErrors } = useForm(); |
| | | |
| | | const [loading, setLoading] = useState(false); |
| | | const [showPassword, setShowPassword] = useState(false); |
| | | |
| | | const username = watch('username'); |
| | | const password = watch('password'); |
| | | |
| | | const onSubmit = (data) => { |
| | | setLoading(true); |
| | | // js native confirm && root |
| | | login( |
| | | auth, |
| | | data, |
| | | location.state ? (location.state).nextPathname : '/' |
| | | ).catch((error) => { |
| | | ).catch((res) => { |
| | | setLoading(false); |
| | | notify( |
| | | typeof error === 'string' |
| | | ? error |
| | | : typeof error === 'undefined' || !error.message |
| | | ? 'ra.auth.sign_in_error' |
| | | : error.message, |
| | | { |
| | | type: 'error', |
| | | messageArgs: { |
| | | _: |
| | | typeof error === 'string' |
| | | ? error |
| | | : error && error.message |
| | | ? error.message |
| | | : undefined, |
| | | }, |
| | | } |
| | | ); |
| | | const { code, msg, data } = res; |
| | | if (code === 10003) { |
| | | setError('username', { |
| | | message: msg |
| | | }) |
| | | } else if (code === 10004) { |
| | | setError('username', { |
| | | message: msg |
| | | }) |
| | | } else if (code === 10001) { |
| | | setError('password', { |
| | | message: msg |
| | | }) |
| | | } else { |
| | | notify(msg, { type: 'error', messageArgs: { _: msg } }); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | return ( |
| | | <Form onSubmit={handleSubmit} noValidate> |
| | | {/* https://unsplash.com/ */} |
| | | <> |
| | | <Box |
| | | sx={{ |
| | | display: 'flex', |
| | | flexDirection: 'column', |
| | | minHeight: '100vh', |
| | | alignItems: 'center', |
| | | justifyContent: 'flex-start', |
| | | // justifyContent: 'center', |
| | | background: `url(/login_bg2.jpg)`, |
| | | backgroundRepeat: 'no-repeat', |
| | | backgroundSize: 'cover', |
| | | }} |
| | | p={2} |
| | | display="flex" |
| | | flexDirection='column' |
| | | component="form" |
| | | onSubmit={handleSubmit(onSubmit)} |
| | | noValidate |
| | | > |
| | | <video |
| | | autoPlay |
| | | loop |
| | | muted |
| | | style={{ |
| | | position: 'fixed', |
| | | top: 0, |
| | | left: 0, |
| | | width: '100%', |
| | | height: '100%', |
| | | // objectFit: 'cover', |
| | | // objectFit: 'contain', |
| | | objectFit: 'fill', |
| | | // objectFit: 'scale-down', |
| | | zIndex: 0, |
| | | }} |
| | | > |
| | | {LOGIN_BACKGROUND === 'media' && ( |
| | | <source src="/login_bg1.mp4" type="video/mp4" /> |
| | | )} |
| | | </video> |
| | | |
| | | <Card sx={{ |
| | | minWidth: 300, |
| | | marginTop: '6em', |
| | | zIndex: 1 |
| | | }}> |
| | | <Box |
| | | sx={{ |
| | | margin: '1em', |
| | | display: 'flex', |
| | | justifyContent: 'center', |
| | | }} |
| | | > |
| | | <Avatar sx={{ bgcolor: 'secondary.main' }}> |
| | | <LockIcon /> |
| | | </Avatar> |
| | | </Box> |
| | | <Box |
| | | sx={{ |
| | | marginTop: '1em', |
| | | display: 'flex', |
| | | justifyContent: 'center', |
| | | color: theme => theme.palette.grey[500], |
| | | }} |
| | | > |
| | | Hint: root / 123456 |
| | | </Box> |
| | | <Box sx={{ padding: '0 1em 1em 1em' }}> |
| | | <Box sx={{ marginTop: '1em' }}> |
| | | <TextInput |
| | | <Stack spacing={2}> |
| | | <Controller |
| | | name="username" |
| | | control={control} |
| | | defaultValue="" |
| | | rules={{ required: true }} |
| | | render={({ field, fieldState: { error } }) => ( |
| | | <TextField |
| | | {...field} |
| | | label={translate("page.login.username")} |
| | | variant="standard" |
| | | disabled={loading} |
| | | autoFocus |
| | | source="username" |
| | | label={translate('ra.auth.username')} |
| | | disabled={loading} |
| | | validate={required()} |
| | | autoComplete="off" |
| | | error={!!error} |
| | | helperText={error?.message || ""} |
| | | /> |
| | | </Box> |
| | | <Box sx={{ marginTop: '1em' }}> |
| | | <TextInput |
| | | source="password" |
| | | label={translate('ra.auth.password')} |
| | | type="password" |
| | | )} |
| | | /> |
| | | |
| | | <Controller |
| | | name="password" |
| | | control={control} |
| | | defaultValue="" |
| | | rules={{ required: true }} |
| | | render={({ field, fieldState: { error } }) => ( |
| | | <TextField |
| | | {...field} |
| | | label={translate("page.login.password")} |
| | | type={showPassword ? 'text' : 'password'} |
| | | variant="standard" |
| | | disabled={loading} |
| | | validate={required()} |
| | | autoComplete="off" |
| | | error={!!error} |
| | | helperText={error?.message || ""} |
| | | InputProps={{ |
| | | endAdornment: ( |
| | | <InputAdornment position="end"> |
| | | <IconButton |
| | | aria-label="toggle password visibility" |
| | | onClick={() => setShowPassword((show) => !show)} |
| | | onMouseDown={(event) => { event.preventDefault() }} |
| | | edge="end" |
| | | > |
| | | {showPassword ? <VisibilityOff /> : <Visibility />} |
| | | </IconButton> |
| | | </InputAdornment> |
| | | ), |
| | | }} |
| | | /> |
| | | </Box> |
| | | </Box> |
| | | <CardActions sx={{ padding: '0 1em 1em 1em' }}> |
| | | <Button |
| | | variant="contained" |
| | | type="submit" |
| | | color="primary" |
| | | disabled={loading} |
| | | fullWidth |
| | | > |
| | | {loading && ( |
| | | <CircularProgress size={25} thickness={2} /> |
| | | )} |
| | | {translate('ra.auth.sign_in')} |
| | | </Button> |
| | | </CardActions> |
| | | </Card> |
| | | </Box> |
| | | </Form> |
| | | ); |
| | | }; |
| | | )} |
| | | /> |
| | | |
| | | <Box /> |
| | | |
| | | <Button |
| | | type="submit" |
| | | variant="contained" |
| | | disabled={loading || !username || !password} |
| | | > |
| | | {loading && <CircularProgress size={25} thickness={2} />} |
| | | {translate('page.login.button.login')} |
| | | </Button> |
| | | |
| | | </Stack> |
| | | </Box > |
| | | </> |
| | | ) |
| | | } |
| | | |
| | | export default Login; |
| New file |
| | |
| | | import React, { useState, useRef, useEffect, useMemo } from "react"; |
| | | import { |
| | | Box, |
| | | AppBar, |
| | | Card, |
| | | Toolbar, |
| | | CircularProgress, |
| | | Typography, |
| | | Tabs, |
| | | Tab, |
| | | useTheme, |
| | | useMediaQuery, |
| | | Button, |
| | | } from '@mui/material'; |
| | | import { |
| | | useTranslate, |
| | | useLogin, |
| | | useNotify, |
| | | } from 'react-admin'; |
| | | import { LOGIN_BACKGROUND, DEFAULT_THEME_MODE } from '@/config/setting'; |
| | | import Login from "./Login"; |
| | | |
| | | const Index = () => { |
| | | const translate = useTranslate(); |
| | | const theme = useTheme(); |
| | | const isSmallScreen = useMediaQuery(theme.breakpoints.down('md')); |
| | | |
| | | const [tab, setTab] = useState(0) |
| | | |
| | | const formPosition = isSmallScreen ? 'middle' : 'right' |
| | | |
| | | |
| | | return ( |
| | | <Box |
| | | sx={{ |
| | | display: 'flex', |
| | | flexDirection: 'column', |
| | | minHeight: '100vh', |
| | | alignItems: formPosition === 'middle' ? 'center' : 'flex-end', |
| | | paddingRight: formPosition === 'middle' ? 0 : '6em', |
| | | justifyContent: formPosition === 'middle' ? 'flex-start' : 'center', |
| | | background: `url(/login_bg.jpg)`, // https://unsplash.com/ |
| | | backgroundRepeat: 'no-repeat', |
| | | backgroundSize: 'cover', |
| | | }} |
| | | > |
| | | <video |
| | | autoPlay |
| | | loop |
| | | muted |
| | | style={{ |
| | | position: 'fixed', |
| | | top: 0, |
| | | left: 0, |
| | | width: '100%', |
| | | height: '100%', |
| | | // objectFit: 'cover', |
| | | // objectFit: 'contain', |
| | | objectFit: 'fill', |
| | | // objectFit: 'scale-down', |
| | | zIndex: 0, |
| | | }} |
| | | > |
| | | {LOGIN_BACKGROUND === 'media' && ( |
| | | <source src="/login_bg.mp4" type="video/mp4" /> |
| | | )} |
| | | </video> |
| | | |
| | | <Card sx={{ |
| | | width: 400, |
| | | marginTop: formPosition === 'middle' ? '6em' : 0, |
| | | zIndex: 1, |
| | | bgcolor: DEFAULT_THEME_MODE === 'light' ? '#fff' : '#121212', |
| | | border: 'inherit' |
| | | }}> |
| | | <div> |
| | | <AppBar position="static" sx={{ |
| | | backgroundColor: '#3D4BA7', |
| | | border: 'inherit', |
| | | }}> |
| | | <Toolbar sx={{ |
| | | display: 'flex', |
| | | justifyContent: 'space-between' |
| | | }}> |
| | | <Typography variant="h6" color="inherit">{translate("page.login.title")} {"RMS"}</Typography> |
| | | </Toolbar> |
| | | </AppBar> |
| | | </div> |
| | | |
| | | <Login /> |
| | | <Box mb={1} sx={{ textAlign: 'center' }}> |
| | | <Typography variant="caption" align="center">{translate("page.login.footer")}</Typography> |
| | | </Box> |
| | | </Card> |
| | | </Box > |
| | | ); |
| | | }; |
| | | |
| | | export default Index; |
| | |
| | | package com.zy.acs.manager.common.config; |
| | | |
| | | import com.zy.acs.common.enums.SystemModeType; |
| | | import lombok.Data; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | import org.springframework.context.annotation.Configuration; |
| | | |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * 系统配置属性 |
| | |
| | | */ |
| | | private String tokenKey; |
| | | |
| | | /** |
| | | * 系统名称 |
| | | */ |
| | | private String systemName; |
| | | |
| | | /** |
| | | * 系统版本 |
| | | */ |
| | | private String systemVersion; |
| | | |
| | | /** |
| | | * 系统模式( ONLINE / OFFLINE ) |
| | | */ |
| | | private String systemMode; |
| | | |
| | | /** |
| | | * 超级管理员 |
| | | */ |
| | | private String superUsername; |
| | | |
| | | /** |
| | | * 验证码长度 |
| | | */ |
| | | private Integer codeLength = 4; |
| | | |
| | | /** |
| | | * 验证码有效期 ( 秒 ) |
| | | */ |
| | | private Integer codeTime = 300; |
| | | |
| | | /** |
| | | * 超级验证码 |
| | | */ |
| | | private String securityCode; |
| | | |
| | | /** |
| | | * 文件保存路径 |
| | | */ |
| | | private String fileSavePath; |
| | | |
| | | /** |
| | | * 文件服务器url前缀 |
| | | */ |
| | | private String fileDomainPrefix; |
| | | |
| | | /** |
| | | * 图片最大体积 |
| | | */ |
| | | private Integer imageMaxSize; |
| | | |
| | | public List<String> getSuperUserList() { |
| | | return Arrays.stream(superUsername.split(",")).collect(Collectors.toList()); |
| | | } |
| | | |
| | | public SystemModeType getSystemMode() { |
| | | return SystemModeType.valueOf(systemMode); |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | package com.zy.acs.manager.common.domain; |
| | | |
| | | |
| | | import com.zy.acs.framework.common.BaseRes; |
| | | |
| | | public class BusinessRes implements BaseRes { |
| | | |
| | | public final static String INVALID_PASSWORD = "10001 - The current password was incorrect"; |
| | | |
| | | public final static String USERNAME_EXIST = "10002 - Username already exist"; |
| | | |
| | | public final static String USERNAME_NOT_EXIST = "10003 - Username doesn't exist"; |
| | | |
| | | public final static String USERNAME_FROZEN = "10004 - Account frozen"; |
| | | |
| | | public final static String INVALID_EMAIL = "10005 - Invalid email address"; |
| | | |
| | | public final static String EMAIL_EXIT = "10006 - Email address already exist"; |
| | | |
| | | } |
| | |
| | | public class SecurityConfig extends WebSecurityConfigurerAdapter { |
| | | |
| | | public static final String[] FILTER_PATH = new String[]{ |
| | | "/api/system/info", |
| | | "/api/tenant/list", |
| | | "/api/open/**", |
| | | "/demo/**", |
| | | "/test/**", |
| | |
| | | import com.zy.acs.framework.common.R; |
| | | import com.zy.acs.manager.common.annotation.OperationLog; |
| | | import com.zy.acs.manager.common.config.ConfigProperties; |
| | | import com.zy.acs.manager.common.domain.BusinessRes; |
| | | import com.zy.acs.manager.common.security.JwtSubject; |
| | | import com.zy.acs.manager.common.utils.JwtUtil; |
| | | import com.zy.acs.manager.manager.enums.StatusType; |
| | | import com.zy.acs.manager.system.controller.param.LoginParam; |
| | | import com.zy.acs.manager.system.controller.param.UpdatePasswordParam; |
| | | import com.zy.acs.manager.system.controller.result.LoginResult; |
| | | import com.zy.acs.manager.system.controller.result.MenuVo; |
| | | import com.zy.acs.manager.system.controller.result.SystemInfoVo; |
| | | import com.zy.acs.manager.system.entity.Menu; |
| | | import com.zy.acs.manager.system.entity.User; |
| | | import com.zy.acs.manager.system.entity.UserLogin; |
| | |
| | | Long tenantId = param.getTenantId(); |
| | | User user = userService.getByUsername(username, tenantId); |
| | | if (user == null) { |
| | | return R.error("Username Does Not Exist"); |
| | | return R.parse(BusinessRes.USERNAME_NOT_EXIST); |
| | | } |
| | | if (!user.getStatus().equals(1)) { |
| | | return R.error("Account Frozen"); |
| | | if (!user.getStatus().equals(StatusType.ENABLE.val)) { |
| | | return R.parse(BusinessRes.USERNAME_FROZEN); |
| | | } |
| | | if (!userService.comparePassword(user.getPassword(), param.getPassword())) { |
| | | return R.error("Wrong Password"); |
| | | return R.parse(BusinessRes.INVALID_PASSWORD); |
| | | } |
| | | String accessToken = JwtUtil.buildToken(new JwtSubject(username, user.getTenantId()), |
| | | configProperties.getTokenExpireTime(), configProperties.getTokenKey()); |
| | | userLoginService.saveAsync(user.getId(), accessToken, UserLogin.TYPE_LOGIN, tenantId, null, request); |
| | | return R.ok("Login Success").add(new LoginResult(accessToken, user)); |
| | | return R.ok("Sign In Success").add(new LoginResult(accessToken, user)); |
| | | } |
| | | |
| | | @GetMapping("/auth/user") |
| | |
| | | // return R.ok().add(Utils.toTreeData(menus, 0L, Menu::getParentId, Menu::getId, Menu::setChildren)); |
| | | List<MenuVo> voList = menus.stream().map(this::convertToVo).collect(Collectors.toList()); |
| | | return R.ok().add(Utils.toTreeData(voList, 0L, MenuVo::getParentId, MenuVo::getId, MenuVo::setChildren)); |
| | | } |
| | | |
| | | |
| | | |
| | | @GetMapping("/auth/tenant") |
| | | public R authHost() { |
| | | return R.ok().add(tenantService.list()); |
| | | } |
| | | |
| | | @PreAuthorize("hasAuthority('sys:auth:user')") |
| | |
| | | return R.error("Update Fail"); |
| | | } |
| | | |
| | | @GetMapping("/system/info") |
| | | public R systemInfo() { |
| | | SystemInfoVo infoVo = new SystemInfoVo(); |
| | | infoVo.setName(configProperties.getSystemName()); |
| | | infoVo.setVersion(configProperties.getSystemVersion()); |
| | | infoVo.setMode(configProperties.getSystemMode().toString()); |
| | | return R.ok(infoVo); |
| | | } |
| | | |
| | | // ---------------------------------------------------- |
| | | |
| New file |
| | |
| | | package com.zy.acs.manager.system.controller.result; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | @Data |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class SystemInfoVo { |
| | | |
| | | private String name; |
| | | |
| | | private String version; |
| | | |
| | | private String mode; |
| | | |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableLogic; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.zy.acs.framework.common.Cools; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | | |
| | | @Data |
| | |
| | | default: |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | public String getCreateTime$(){ |
| | | if (Cools.isEmpty(this.createTime)){ |
| | | return ""; |
| | | } |
| | | return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.createTime); |
| | | } |
| | | |
| | | public String getUpdateTime$(){ |
| | | if (Cools.isEmpty(this.updateTime)){ |
| | | return ""; |
| | | } |
| | | return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.updateTime); |
| | | } |
| | | |
| | | } |
| | |
| | | path: stock/out/rcs-manager/logs |
| | | |
| | | config: |
| | | system-name: @pom.artifactId@ |
| | | system-version: @pom.version@ |
| | | system-mode: ONLINE |
| | | open-office-home: C |
| | | swagger-base-package: com.zy.acs |
| | | swagger-title: ACS API文档 |