如何定制登录密码页和访问到期页?
1. 方案概述
当企业员工访问带有密码的文件/文件夹链接时,会先跳转到一个页面,进行密码输入和校验,这就是登录密码页。只有在登录密码页中输入正确密码,才能进入文件/文件夹进行访问。

如果文档的密码有效期过期,点击文档链接后,则显示访问链接过期页面。

通常在两种情况下,客户会有定制登录密码页和访问到期页的需求:
- 标品的密码登录页面不满足需求,需要进行个性化定制。例如,给页面添加一些组织logo或吉祥物元素。
- 当客户的定制功能涉及通过密码访问文档时,也需要定制登录密码页和访问到期页。例如,客户做了一个文档查看的定制功能叫“免登录分享”,需要在外发这类文档时开启“通过密码访问”,并给分享链接设置有效期,这种情况下,就需要定制登录密码页和访问到期页。
| 实现效果 | 用户点击文档链接-进入登录密码页-输入密码-进行文件预览![]() 中文 ![]() 繁体 ![]() 英文 | 用户点击文档链接-若超过密码的有效期-显示访问链接过期页面![]() 中文 ![]() 繁体 ![]() 英文 |
| 支持端 | 文档中心PC端、文档中心H5端 | |
| 操作系统限制 | 支持X86、XC |
2. 使用指南
👉能力
独立页面插件开发:
- 登录密码页:
/c/cid/index.html#/password/:id - 访问到期页:
/c/cid/index.html#/expire
异步请求调用:
ecissdk内部已经封装了异步请求的框架逻辑,可以直接使用sdk暴露出的异步请求方法来发送相应的业务请求
sdk.utils.request.(get|post)({
url: 'xxx', // 必传,接口url ,例如登录密码校验接口
data?: {}, // 非必传,接口参数
service: '', // 必传,私有化服务名
headers?: {} // 非必传,请求头
})
👉代码示例
- 目录结构
ecis-frontend-plugin-custom-frame/
├── src/
│ ├── components/
│ │ ├── expired/
│ │ │ ├── index.tsx //链接过期页
│ │ │ ├── index.module.less
│ │ ├── password/
│ │ │ ├── index.tsx // 登录密码页
│ │ | ├── index.module.less
| | |---header.tsx // 公共头部组件
│ ├── libs/
│ │ ├── i18n/
│ │ │ ├── locales/
│ │ │ │ ├── zh-CN.json // 包含中文语言的翻译键值对
│ │ │ │ ├── zh-HK.json // 包含繁体语言的翻译键值对
│ │ │ │ ├── en-US.json // 包含英文语言的翻译键值对
│ ├── web/
│ │ ├── bootstrap.tsx // 页面开发根节点组件路径
- 路由划分
src/web/bootstrap.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import { HashRouter as Router, Route, Switch } from 'react-router-dom';
import Expired from '../componetns/expired/index';
import Password from '../componetns/password/index';
// eslint-disable-next-line react/no-deprecated
ReactDOM.render(
<Router>
<Switch>
<Route path={'/password/:id'} exact={true} component={Password} /> // 登录密码页
<Route path={'/expired'} exact={true} component={Expired} /> // 链接过期页
</Switch>
</Router>,
document.querySelector('#app')
);
登录密码页定制
src/components/password/index.tsx
💡 注意
/c/cid/index.html#/password/:id地址为插件独立页面地址- 对输入的密码进行校验,校验正确存储到localStorage中
- 在登录密码页中密码校验成功后跳转回文件/文件夹预览页
import Header from '../header';
import styles from './index.module.less';
import lock from '../../assets/images/lock.png';
import { Button, Input, message } from 'antd';
import React, { useState, ChangeEvent } from 'react';
import { useParams, useHistory } from 'react-router-dom';
import { Base64 } from 'js-base64';
import { useTranslation } from 'react-i18next';
interface IParams {
id: string;
}
export default function Password() {
const { id } = useParams<IParams>();
const history = useHistory();
// 输入密码
const [password, setPassword] = useState<string>('1234');
const { t } = useTranslation();
// 输入密码
const changePass = (e: ChangeEvent<HTMLInputElement>) => {
setPassword(e.target.value);
};
// 校验密码
const checkPass = async () => {
const res = await sdk.utils.request.get({
url: '/xxx/api/v1/link/web/checkpass', //判断密码是否正确接口
service: 'c',
data: { //接口参数 id 、密码
sid: id,
code: password
}
})
if (res.data.code === 200) {
let cachePass: any = window.localStorage.getItem('cachePass');
cachePass = cachePass ? JSON.parse(cachePass) : {};
cachePass[id] = {
auto: true,
pass: Base64.encode(password),
};
// 密码存储到localStorage中
window.localStorage.setItem('cachePass', JSON.stringify(cachePass));
//校验通过返回预览页
//例如/preview/:id 预览独立页面
//或者通过cb获取预览地址,执行相应逻辑后跳转回预览页window.location.replace("/c/cid/index.html/#/password/:id?cb=" + encodeURIComponent(window.location.href));
history.push(`/preview/${id}`);
} else {
message.error('密码错误');
}
};
return (
<>
<Header />
<div className={styles['passwordPage']}>
<div className={styles['passwordContent']}>
<div>
<img src={lock} />
<p style={{ marginBottom: '20px' }}>{t('password.text')}</p>
<Input onChange={changePass} style={{ textAlign: 'center' }} placeholder={t('password.placeholder')} />
<Button onClick={checkPass} style={{ marginTop: '20px' }} type="primary">
{t('password.btn')}
</Button>
</div>
</div>
</div>
</>
);
}
- 访问到期页定制
src/components/expired/index.tsx
// 1./c/cid/index.html#/expired 地址为插件独立页面,可自行实现访问到期页
import styles from './index.module.less';
import Header from '../Header';
import lock from '../../../assets/lock.png';
export default function Expired() {
const { t } = useTranslation();
return (
<>
<Header />
<div className={styles['expiredPage']}>
<div className={styles['expiredContent']}>
<div>
<img src={lock} />
<p>{t('expiredText')}</p>
</div>
</div>
</div>
</>
)
}
多语言配置
src/libs/i18n/locales/en-US.json
{
"password":{
"text":"Please enter your access password",
"placeholder": "Please enter your access password",
"btn": "Enter"
},
"expiredText": "Link has expired or been revoked and is inaccessible",
}
src/libs/i18n/locales/zh-CN.json
{
"password":{
"text":"请输入访问密码",
"placeholder": "请输入密码",
"btn": "确定"
},
"expiredText": "链接已到期或被取消,无法访问",
}
src/libs/i18n/locales/zh-HK.json
{
"password":{
"text":"請輸入訪問密碼",
"placeholder": "請輸入密碼",
"btn": "確定"
},
"expiredText": "連結已到期或被取消,無法訪問",
}
👉效果截图
| 登录密码页定制 | 中文![]() | 繁体![]() | 英文![]() |
| 访问到期页定制 | 中文![]() | 繁体![]() | 英文![]() |
