修复几个显示问题

This commit is contained in:
zhuoda 2023-02-16 20:11:43 +08:00
parent f6651b8efe
commit 521c89119f
19 changed files with 242 additions and 173 deletions

View File

@ -1,13 +1,13 @@
### SmartAdmin
SmartAdmin 由河南·洛阳 [1024 创新实验室](https://www.1024lab.net/)使用SpringBoot2 和 Vue3 Setup标签、 Composition Api (同时支持JavaScript和TypeScript双版本) ,开发出的一套简洁、易用的中后台解决方案!
SmartAdmin 由河南·洛阳 [1024 创新实验室](https://www.1024lab.net/)使用SpringBoot2 和 Vue3 Setup语法糖、 Composition Api (同时支持JavaScript和TypeScript双版本) ,开发出的一套简洁、易用的中后台解决方案!
**我们开源一套漂亮的代码和一套整洁的代码规范**,让大家在这浮躁的代码世界里感受到一股把代码写好的清流!同时又让开发者节省大量的时间,减少加班,快乐工作,保持谦逊,保持学习,热爱代码,更热爱生活!
### 地址
在线预览: [http://preview.smartadmin.1024lab.net](http://preview.smartadmin.1024lab.net)
部署文档:[https://smartadmin.1024lab.net](https://smartadmin.1024lab.net) (文档在努力更新中)
在线预览: [https://preview.smartadmin.vip](https://preview.smartadmin.vip)
部署文档:[https://smartadmin.vip](https://smartadmin.vip)
vue2版本请查看 feature/1.x 分支
### 理念与思想

View File

@ -29,33 +29,33 @@
WHERE notice_id = #{noticeId}
</update>
<select id="queryPage" resultType="net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeVO">
SELECT tn.*,
e.actual_name AS createUserName
FROM t_notice tn
LEFT JOIN t_employee e ON tn.create_user_id = e.employee_id
SELECT t_notice.*,
t_employee.actual_name AS createUserName
FROM t_notice
LEFT JOIN t_employee ON t_notice.create_user_id = t_employee.employee_id
<where>
tn.deleted_flag = #{queryForm.deletedFlag}
t_notice.deleted_flag = #{queryForm.deletedFlag}
<if test="queryForm.keywords != null and queryForm.keywords != ''">
AND (INSTR(tn.notice_title,#{queryForm.keywords}) OR INSTR(e.actual_name,#{queryForm.keywords}))
AND (INSTR(t_notice.notice_title,#{queryForm.keywords}) OR INSTR(t_employee.actual_name,#{queryForm.keywords}))
</if>
<if test="queryForm.noticeType != null">
AND tn.notice_type = #{queryForm.noticeType}
AND t_notice.notice_type = #{queryForm.noticeType}
</if>
<if test="queryForm.noticeBelongType != null">
AND tn.notice_belong_type = #{queryForm.noticeBelongType}
AND t_notice.notice_belong_type = #{queryForm.noticeBelongType}
</if>
<if test="queryForm.startTime != null">
AND DATE_FORMAT(tn.publish_time, '%Y-%m-%d') &gt;= #{queryForm.startTime}
AND DATE_FORMAT(t_notice.publish_time, '%Y-%m-%d') &gt;= #{queryForm.startTime}
</if>
<if test="queryForm.endTime != null">
AND DATE_FORMAT(tn.publish_time, '%Y-%m-%d') &lt;= #{queryForm.endTime}
AND DATE_FORMAT(t_notice.publish_time, '%Y-%m-%d') &lt;= #{queryForm.endTime}
</if>
<if test="queryForm.disabledFlag != null">
AND tn.disabled_flag = #{queryForm.disabledFlag}
AND t_notice.disabled_flag = #{queryForm.disabledFlag}
</if>
</where>
<if test="queryForm.sortItemList == null or queryForm.sortItemList.size == 0">
ORDER BY tn.top_flag DESC,tn.publish_time DESC
ORDER BY t_notice.top_flag DESC,t_notice.publish_time DESC
</if>
</select>
<select id="getDetail" resultType="net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeVO">

View File

@ -84,6 +84,8 @@ public abstract class AbstractSecurityConfig extends WebSecurityConfigurerAdapte
// token filter 进行校验
httpSecurity.addFilterBefore(new SecurityTokenFilter(this.userFunction()), UsernamePasswordAuthenticationFilter.class);
httpSecurity.addFilterBefore(corsFilter, SecurityTokenFilter.class);
// 禁用spring security 使用 X-Frame-Options防止网页被Frame
httpSecurity.headers().frameOptions().disable();
}

View File

@ -3,7 +3,6 @@ package net.lab1024.sa.common.config;
import net.lab1024.sa.common.common.interceptor.AbstractInterceptor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
@ -28,9 +27,6 @@ public class MvcConfig implements WebMvcConfigurer {
@Autowired(required = false)
private List<HandlerInterceptor> interceptorList;
@Value("${file.storage.local.path}")
private String uploadPath;
@Override
public void addInterceptors (InterceptorRegistry registry) {
if (CollectionUtils.isEmpty(interceptorList)) {
@ -43,8 +39,7 @@ public class MvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/preview/**")
.addResourceLocations("classpath:/META-INF/resources/","classpath:/resources/","classpath:/static/","file:" + uploadPath);;
registry.addResourceHandler("/preview/**");
}
@Override

View File

@ -12,7 +12,7 @@
SmartAdmin v2.X 作者1024创新实验室 @copyright【 1024lab 】
SmartAdmin 文档地址https://smartadmin.1024lab.net
SmartAdmin 文档地址https://smartadmin.vip
1024创新实验室https://www.1024lab.net

View File

@ -1,5 +1,5 @@
VITE_APP_API_URL = 'http://preview.smartadmin.1024lab.net/smart-admin-api'
VITE_APP_API_URL = 'https://preview.smartadmin.vip/smart-admin-api'
VITE_APP_PROJECT_TITLE = 'SmartAdmin V2.X'

Binary file not shown.

View File

@ -9,14 +9,17 @@
*
-->
<template>
<a-modal title="文件预览" v-model:visible="visibleFlag" :width="768" @cancel="onClose">
<div class="container">
<img class="img-prev" :src="previewUrl" />
<a-image
class="img-prev"
:style="{ display: 'none' }"
:preview="{
visible,
onVisibleChange: setVisible,
}"
:src="previewUrl"
/>
</div>
<template #footer>
<a-button @click="onClose">关闭</a-button>
</template>
</a-modal>
</template>
<script setup>
@ -26,7 +29,6 @@
import { smartSentry } from '/@/lib/smart-sentry';
import { SmartLoading } from '/@/components/framework/smart-loading';
const visibleFlag = ref(false);
const imgFileType = ['jpg', 'jpeg', 'png', 'gif'];
const previewUrl = ref();
@ -49,10 +51,15 @@
}
}
const visible = ref(false);
const setVisible = (value) => {
visible.value = value;
};
function showFile(fileItem) {
if (isImg(fileItem.fileType)) {
previewUrl.value = fileItem.fileUrl;
visibleFlag.value = true;
setVisible(true);
return;
}
download(fileItem.fileName, fileItem.fileUrl);
@ -63,10 +70,6 @@
return imgFileType.includes(fileType);
}
function onClose() {
visibleFlag.value = false;
}
defineExpose({
showPreview,
});
@ -77,11 +80,5 @@
display: flex;
justify-content: center;
align-items: center;
.img-prev {
display: block;
width: 100%;
height: 600px;
object-fit: contain;
}
}
</style>

View File

@ -14,4 +14,11 @@ export default {
antdLocale: antd,
dayjsLocale: dayjs,
'setting.title': 'Setting',
'setting.menu.layout': 'Menu Layout',
'setting.menu.width': 'Menu Width',
'setting.menu.theme': 'Menu Theme',
'setting.bread': 'Show Bread',
'setting.pagetag': 'Show PageTag',
'setting.footer': 'Show Footer',
'setting.helpdoc': 'Show Helpdoc',
};

View File

@ -14,4 +14,11 @@ export default {
antdLocale: antd,
dayjsLocale: dayjs,
'setting.title': '网站设置',
'setting.menu.layout': '菜单布局',
'setting.menu.width': '菜单宽度',
'setting.menu.theme': '菜单主题',
'setting.bread': '面包屑',
'setting.pagetag': '标签页',
'setting.footer': '页脚',
'setting.helpdoc': '帮助文档',
};

View File

@ -16,33 +16,33 @@
<a-select-option v-for="item in i18nList" :key="item.value" :value="item.value">{{ item.text }}</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="菜单布局">
<a-form-item :label="$t('setting.menu.layout')">
<a-radio-group @change="changeLayout" button-style="solid" v-model:value="formState.layout">
<a-radio-button v-for="item in $smartEnumPlugin.getValueDescList('LAYOUT_ENUM')" :key="item.value" :value="item.value">
{{ item.desc }}
</a-radio-button>
</a-radio-group>
</a-form-item>
<a-form-item label="菜单宽度" v-if="formState.layout === LAYOUT_ENUM.SIDE.value">
<a-form-item :label="$t('setting.menu.width')" v-if="formState.layout === LAYOUT_ENUM.SIDE.value">
<a-input-number @change="changeSideMenuWidth" v-model:value="formState.sideMenuWidth" :min="1" />
像素px
</a-form-item>
<a-form-item label="菜单主题">
<a-form-item :label="$t('setting.menu.theme')">
<a-radio-group v-model:value="formState.sideMenuTheme" button-style="solid" @change="changeMenuTheme">
<a-radio-button value="dark">Dark</a-radio-button>
<a-radio-button value="light">Light</a-radio-button>
</a-radio-group>
</a-form-item>
<a-form-item label="面包屑">
<a-form-item :label="$t('setting.bread')">
<a-switch @change="changeBreadCrumbFlag" v-model:checked="formState.breadCrumbFlag" checked-children="显示" un-checked-children="隐藏" />
</a-form-item>
<a-form-item label="标签页">
<a-form-item :label="$t('setting.pagetag')">
<a-switch @change="changePageTagFlag" v-model:checked="formState.pageTagFlag" checked-children="显示" un-checked-children="隐藏" />
</a-form-item>
<a-form-item label="页脚">
<a-form-item :label="$t('setting.footer')">
<a-switch @change="changeFooterFlag" v-model:checked="formState.footerFlag" checked-children="显示" un-checked-children="隐藏" />
</a-form-item>
<a-form-item label="帮助文档">
<a-form-item :label="$t('setting.helpdoc')">
<a-switch @change="changeHelpDocFlag" v-model:checked="formState.helpDocFlag" checked-children="显示" un-checked-children="隐藏" />
</a-form-item>
</a-form>

View File

@ -42,7 +42,7 @@
<!-----文档列表---->
<div class="help-doc-list">
<div class="help-doc-item-all">
<router-link tag="a" target="_blank" :to="{ path: '/help-doc/detail' }">查看全部文档 >></router-link>
<router-link tag="a" target="_blank" :to="{ path: '/help-doc/detail' }">系统手册文档 >></router-link>
</div>
<div class="help-doc-item" v-for="item in helpDocList" :key="item.helpDocId">
<router-link tag="a" target="_blank" :to="{ path: '/help-doc/detail', query: { helpDocId: item.helpDocId } }">{{ item.title }}</router-link>
@ -64,7 +64,8 @@
import FeedbackModal from './components/feedback-modal.vue';
import { useAppConfigStore } from '/@/store/modules/system/app-config';
import { feedbackApi } from '/@/api/support/feedback/feedback-api';
import { smartSentry } from '/@/lib/smart-sentry';
import { HOME_PAGE_NAME } from '/@/constants/system/home-const';
import { smartSentry } from '/@/lib/smart-sentry';
function hideHelpDoc() {
useAppConfigStore().hideHelpDoc();
@ -142,11 +143,15 @@ import { smartSentry } from '/@/lib/smart-sentry';
//SmartAdmin routername menuid
let menuId = -1;
try {
if(currentRoute.name === HOME_PAGE_NAME){
menuId = 0;
}else{
menuId = _.toNumber(currentRoute.name);
}
} catch (e) {
smartSentry.captureError(e);
}
if (menuId > 0) {
if (menuId > -1) {
queryHelpDocList(menuId);
}
},

View File

@ -27,6 +27,11 @@ import { useUserStore } from '/@/store/modules/system/user';
import '/@/theme/index.less';
import { getTokenFromCookie } from '/@/utils/cookie-util';
let url = location.href;
if(url.indexOf('1024lab.net') > -1){
location.href = "https://preview.smartadmin.vip";
}
/*
* -------------------- 着重 解释说明下main.js的初始化逻辑 begin --------------------

View File

@ -9,7 +9,7 @@
-->
<template>
<a-drawer
:title="formData.helpDocId ? '编辑' : '新建'"
:title="formData.helpDocId ? '编辑系统手册' : '新建系统手册'"
:visible="visibleFlag"
:width="1000"
:footerStyle="{ textAlign: 'right' }"
@ -29,7 +29,13 @@
<a-form-item label="排序" name="sort">
<a-input-number v-model:value="formData.sort" placeholder="值越小越靠前" />值越小越靠前
</a-form-item>
<a-form-item label="关联菜单">
<a-form-item label="是否首页显示">
<a-radio-group v-model:value="relateHomeFlag" button-style="solid">
<a-radio-button :value="true">首页显示</a-radio-button>
<a-radio-button :value="false">首页不用显示</a-radio-button>
</a-radio-group>
</a-form-item>
<a-form-item label="关联菜单" v-if="!relateHomeFlag">
<MenuTreeSelect v-model:value="formData.relationIdList" ref="menuTreeSelect" />
</a-form-item>
<a-form-item label="公告内容" name="contentHtml">
@ -69,7 +75,7 @@
import HelpDocCatalogTreeSelect from './help-doc-catalog-tree-select.vue';
import MenuTreeSelect from '/@/components/system/menu-tree-select/index.vue';
import _ from 'lodash';
import { smartSentry } from '/@/lib/smart-sentry';
import { smartSentry } from '/@/lib/smart-sentry';
const emits = defineEmits(['reloadList']);
@ -99,6 +105,7 @@ import { smartSentry } from '/@/lib/smart-sentry';
const formRef = ref();
const contentRef = ref();
const noticeFormVisibleModal = ref();
const relateHomeFlag = ref(false);
const defaultFormData = {
helpDocId: undefined,
@ -135,6 +142,11 @@ import { smartSentry } from '/@/lib/smart-sentry';
}
Object.assign(formData, result.data);
formData.relationIdList = result.data.relationList ? result.data.relationList.map((e) => e.relationId) : [];
if (formData.relationIdList.length === 1 && formData.relationIdList[0].relationId === 0) {
relateHomeFlag.value = true;
} else {
relateHomeFlag.value = false;
}
} catch (err) {
smartSentry.captureError(err);
} finally {
@ -161,8 +173,18 @@ import { smartSentry } from '/@/lib/smart-sentry';
try {
SmartLoading.show();
let param = _.cloneDeep(formData);
// 0
if (relateHomeFlag.value) {
param.relationList = [
{
relationName: '首页',
relationId: 0,
},
];
} else {
let relationList = menuTreeSelect.value.getMenuListByIdList(formData.relationIdList);
param.relationList = relationList.map((e) => Object.assign({}, { relationId: e.menuId, relationName: e.menuName }));
}
if (param.helpDocId) {
await helpDocApi.update(param);

View File

@ -14,7 +14,6 @@
<div>
关键字
<a-input style="width: 250px" v-model:value="queryForm.keywords" placeholder="姓名/手机号/登录账号" />
<a-button class="button-style" v-if="selectRoleId" type="primary" @click="queryRoleEmployee">搜索</a-button>
<a-button class="button-style" v-if="selectRoleId" type="default" @click="resetQueryRoleEmployee">重置</a-button>
</div>
@ -28,6 +27,7 @@
>
</div>
</div>
<a-table
:loading="tableLoading"
:dataSource="tableData"

View File

@ -14,7 +14,7 @@
<a-col flex="200px">
<RoleList ref="roleList" />
</a-col>
<a-col flex="1">
<a-col flex="1" class="role-setting">
<RoleSetting />
</a-col>
</a-row>
@ -42,4 +42,7 @@
.height100 {
height: 100%;
}
.role-setting{
width:calc(100% - 250px)
}
</style>

View File

@ -32,7 +32,7 @@
height="60"
frameborder="0"
allowtransparency="true"
src="//i.tianqi.com/index.php?c=code&id=12&icon=1&num=5&site=12"
src="//i.tianqi.com/index.php?c=code&id=12&icon=1&num=3&site=12"
></iframe>
</div>
</a-row>
@ -136,7 +136,7 @@
margin-bottom: 10px;
.heart-sentence {
width: calc(100% - 660px);
width: calc(100% - 420px);
h3 {
color: rgba(0, 0, 0, 0.75);
}
@ -146,7 +146,7 @@
display: flex;
justify-content: space-between;
.weather {
width: 650px;
width: 400px;
}
}

View File

@ -70,11 +70,12 @@
align-items: center;
justify-content: center;
flex-direction: column;
width:50%;
width: 50%;
> img {
width: 112px;
height: 112px;
}
.qr-desc {
display: flex;
align-items: center;
@ -89,6 +90,37 @@
margin-right: 9px;
}
}
.qr-desc-marquee {
width: 100%;
display: flex;
align-items: center;
margin-top: 11px;
font-size: 12px;
font-weight: 500;
text-align: center;
color: #ffffff;
@keyframes marquee {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-220%);
}
}
.marquee {
flex: 1;
overflow: hidden;
span {
display: inline-block;
width: 100%;
white-space: nowrap;
animation: marquee 15s linear infinite;
}
}
}
}
}
.login-title {

View File

@ -15,9 +15,8 @@
<p>欢迎登录 SmartAdmin V2</p>
<p class="desc">
SmartAdmin 是由 河南·洛阳
<a target="_blank" href="https://www.1024lab.net" style="color: white; weight: bolder; font-size: 15px; text-decoration: underline"
>1024创新实验室1024Lab</a
>
<a target="_blank" href="https://www.1024lab.net"
style="color: white; weight: bolder; font-size: 15px; text-decoration: underline">1024创新实验室1024Lab</a>
使用SpringBoot2.x Vue3.2 Setup语法糖 Composition Api (同时支持JavaScript和TypeScript双版本) 开发出的一套简洁易用的中后台解决方案
<br />
<br />
@ -29,8 +28,9 @@
保持谦逊保持学习热爱代码更热爱生活 !<br />
永远年轻永远前行 !<br />
<span class="author">
<a target="_blank" href="https://zhuoda.vip" style="color: white; font-size: 13px; text-decoration: underline">
1024创新实验室-主任卓大 ( 2022 · 洛阳
<a target="_blank" href="https://zhuoda.vip"
style="color: white; font-size: 13px; text-decoration: underline">
1024创新实验室-主任卓大
</a>
</span>
</span>
@ -43,7 +43,7 @@
</div>
<div class="app-qr">
<img :src="xiaozhen" />
<marquee class="qr-desc" scrolldelay="130"> 关注小镇程序员了解二三线城市程序员的代码与钱途技术与生活城市可能无法选择但未来可以拼搏</marquee>
<div class="qr-desc-marquee"><div class="marquee"><span>关注小镇程序员了解二三线城市程序员的代码与钱途技术与生活城市可能无法选择但未来可以拼搏</span></div></div>
</div>
</div>
</div>
@ -55,12 +55,8 @@
<a-input v-model:value.trim="loginForm.loginName" placeholder="请输入用户名" />
</a-form-item>
<a-form-item name="password">
<a-input-password
v-model:value="loginForm.password"
autocomplete="on"
:type="showPassword ? 'text' : 'password'"
placeholder="请输入密码"
/>
<a-input-password v-model:value="loginForm.password" autocomplete="on"
:type="showPassword ? 'text' : 'password'" placeholder="请输入密码" />
</a-form-item>
<a-form-item name="captchaCode">
<a-input class="captcha-input" v-model:value.trim="loginForm.captchaCode" placeholder="请输入验证码" />
@ -88,65 +84,65 @@
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { message } from 'ant-design-vue';
import { onMounted, onUnmounted, reactive, ref } from 'vue';
import { useRouter } from 'vue-router';
import { loginApi } from '/@/api/system/login/login-api';
import { SmartLoading } from '/@/components/framework/smart-loading';
import { LOGIN_DEVICE_ENUM } from '/@/constants/system/login-device-const';
import { useUserStore } from '/@/store/modules/system/user';
import { saveTokenToCookie } from '/@/utils/cookie-util';
import { message } from 'ant-design-vue';
import { onMounted, onUnmounted, reactive, ref } from 'vue';
import { useRouter } from 'vue-router';
import { loginApi } from '/@/api/system/login/login-api';
import { SmartLoading } from '/@/components/framework/smart-loading';
import { LOGIN_DEVICE_ENUM } from '/@/constants/system/login-device-const';
import { useUserStore } from '/@/store/modules/system/user';
import { saveTokenToCookie } from '/@/utils/cookie-util';
import gongzhonghao from '/@/assets/images/1024lab/1024lab-gzh.jpg';
import zhuoda from '/@/assets/images/1024lab/zhuoda-wechat.jpg';
import loginQR from '/@/assets/images/login/login-qr.png';
import xiaozhen from '/@/assets/images/1024lab/xiaozhen-gzh.jpg';
import gongzhonghao from '/@/assets/images/1024lab/1024lab-gzh.jpg';
import zhuoda from '/@/assets/images/1024lab/zhuoda-wechat.jpg';
import loginQR from '/@/assets/images/login/login-qr.png';
import xiaozhen from '/@/assets/images/1024lab/xiaozhen-gzh.jpg';
import aliLogin from '/@/assets/images/login/ali-icon.png';
import googleLogin from '/@/assets/images/login/google-icon.png';
import qqLogin from '/@/assets/images/login/qq-icon.png';
import weiboLogin from '/@/assets/images/login/weibo-icon.png';
import aliLogin from '/@/assets/images/login/ali-icon.png';
import googleLogin from '/@/assets/images/login/google-icon.png';
import qqLogin from '/@/assets/images/login/qq-icon.png';
import weiboLogin from '/@/assets/images/login/weibo-icon.png';
import { buildRoutes } from '/@/router/index';
import { smartSentry } from '/@/lib/smart-sentry';
import { buildRoutes } from '/@/router/index';
import { smartSentry } from '/@/lib/smart-sentry';
//--------------------- ---------------------------------
//--------------------- ---------------------------------
const loginForm = reactive({
const loginForm = reactive({
loginName: 'admin',
password: '',
captchaCode: '',
captchaUuid: '',
loginDevice: LOGIN_DEVICE_ENUM.PC.value,
});
const rules = {
});
const rules = {
loginName: [{ required: true, message: '用户名不能为空' }],
password: [{ required: true, message: '密码不能为空' }],
captchaCode: [{ required: true, message: '验证码不能为空' }],
};
};
const showPassword = ref(false);
const router = useRouter();
const formRef = ref();
const rememberPwd = ref(false);
const showPassword = ref(false);
const router = useRouter();
const formRef = ref();
const rememberPwd = ref(false);
onMounted(() => {
onMounted(() => {
document.onkeyup = (e) => {
if (e.keyCode == 13) {
onLogin();
}
};
});
});
onUnmounted(() => {
onUnmounted(() => {
document.onkeyup = null;
});
});
//
async function onLogin() {
//
async function onLogin() {
formRef.value.validate().then(async () => {
try {
SmartLoading.show();
@ -169,12 +165,12 @@
SmartLoading.hide();
}
});
}
}
//--------------------- ---------------------------------
//--------------------- ---------------------------------
const captchaBase64Image = ref('');
async function getCaptcha() {
const captchaBase64Image = ref('');
async function getCaptcha() {
try {
let captchaResult = await loginApi.getCaptcha();
captchaBase64Image.value = captchaResult.data.captchaBase64Image;
@ -183,24 +179,22 @@
} catch (e) {
console.log(e);
}
}
}
let refrestCaptchaInterval = null;
function beginRefrestCaptchaInterval(expireSeconds) {
let refrestCaptchaInterval = null;
function beginRefrestCaptchaInterval(expireSeconds) {
if (refrestCaptchaInterval === null) {
refrestCaptchaInterval = setInterval(getCaptcha, (expireSeconds - 5) * 1000);
}
}
}
function stopRefrestCaptchaInterval() {
function stopRefrestCaptchaInterval() {
if (refrestCaptchaInterval != null) {
clearInterval(refrestCaptchaInterval);
refrestCaptchaInterval = null;
}
}
}
onMounted(getCaptcha);
onMounted(getCaptcha);
</script>
<style lang="less" scoped>
@import './login.less';
</style>
<style lang="less" scoped>@import './login.less';</style>