feat: 添加通知公告功能和相关页面
refactor: 重构财务类型选项为独立变量 docs: 更新版本记录规则和文档 feat(workbench): 新增通知公告列表和详情页面 feat(h5office): 添加h5office文档预览组件和相关配置 style: 优化文章页面样式和布局 fix(update): 添加版本检查日志输出
This commit is contained in:
@@ -1,22 +1,220 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="article-container">
|
||||
<!-- 加载状态 -->
|
||||
<view class="loading" v-if="loading">
|
||||
<uni-loading-icon size="24" color="#007aff"></uni-loading-icon>
|
||||
<text class="loading-text">加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 文章内容(加载完成后显示) -->
|
||||
<view class="article-content" v-else-if="article">
|
||||
<!-- 帖子标题 -->
|
||||
<view class="post-title">{{ article.title || '无标题' }}</view>
|
||||
|
||||
<!-- 用户信息 -->
|
||||
<view class="user-info">
|
||||
<image v-if="article.avatar" class="user-avatar" :src="article.avatar || '/static/default-avatar.png'" mode="cover"></image>
|
||||
<view class="user-meta">
|
||||
<view class="user-name">
|
||||
{{ article.author || '未知用户' }}
|
||||
<!-- <view class="user-level">Lv.1</view> -->
|
||||
</view>
|
||||
<view class="user-time-area">
|
||||
<text>{{ article.createTime || '未知时间' }}</text>
|
||||
<text v-if="article.area"> · {{ article.area || '未知地区' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="follow-btn">+关注</view> -->
|
||||
</view>
|
||||
|
||||
<!-- 富文本内容 -->
|
||||
<mp-html :content="article.content"></mp-html>
|
||||
</view>
|
||||
|
||||
<!-- 错误状态 -->
|
||||
<view class="error" v-else>
|
||||
<uni-icons type="warn" size="36" color="#ff4d4f"></uni-icons>
|
||||
<text class="error-text">加载失败</text>
|
||||
<button class="retry-btn" @click="reload">重试</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
import { getNotice } from '@/api/oa/notice';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
article: null,
|
||||
loading: true,
|
||||
};
|
||||
},
|
||||
onLoad(options) {
|
||||
const { type, id } = options;
|
||||
if (!type || !id) {
|
||||
uni.showToast({ title: '参数错误', icon: 'none' });
|
||||
setTimeout(() => uni.navigateBack(), 1000);
|
||||
return;
|
||||
}
|
||||
this.fetchData(type, id);
|
||||
},
|
||||
methods: {
|
||||
|
||||
fetchData(type, id) {
|
||||
this.loading = true;
|
||||
switch (type) {
|
||||
case 'notice':
|
||||
getNotice(id)
|
||||
.then(res => {
|
||||
this.article = {
|
||||
...res.data,
|
||||
author: res.data.createBy,
|
||||
title: res.data.noticeTitle,
|
||||
content: res.data.noticeContent,
|
||||
};
|
||||
this.loading = false;
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('获取文章失败', err);
|
||||
this.article = null;
|
||||
this.loading = false;
|
||||
uni.showToast({ title: '加载失败', icon: 'none' });
|
||||
});
|
||||
break;
|
||||
default:
|
||||
uni.showToast({ title: '未知类型', icon: 'none' });
|
||||
setTimeout(() => uni.navigateBack(), 1000);
|
||||
break;
|
||||
}
|
||||
},
|
||||
reload() {
|
||||
const { type, id } = this.$options.onLoad.options;
|
||||
this.fetchData(type, id);
|
||||
},
|
||||
navigateBack() {
|
||||
uni.navigateBack();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style scoped>
|
||||
.article-container {
|
||||
min-height: 100vh;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.loading {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 50px 0;
|
||||
}
|
||||
.loading-text {
|
||||
margin-top: 10px;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.error {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 50px 0;
|
||||
}
|
||||
.error-text {
|
||||
margin: 15px 0;
|
||||
color: #ff4d4f;
|
||||
font-size: 16px;
|
||||
}
|
||||
.retry-btn {
|
||||
background-color: #007aff;
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
padding: 8px 20px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.article-content {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.post-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 12px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.user-avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.user-meta {
|
||||
flex: 1;
|
||||
}
|
||||
.user-name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.user-level {
|
||||
background-color: #dff0d8;
|
||||
color: #5cb85c;
|
||||
font-size: 10px;
|
||||
padding: 1px 4px;
|
||||
border-radius: 3px;
|
||||
margin-left: 6px;
|
||||
}
|
||||
.user-time-area {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
.follow-btn {
|
||||
font-size: 12px;
|
||||
color: #5cb85c;
|
||||
background-color: #e8f5e9;
|
||||
padding: 4px 8px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.mp-html {
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
line-height: 1.8;
|
||||
}
|
||||
.mp-html img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
margin: 10px 0;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.interact-area {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-top: 20px;
|
||||
padding: 10px 0;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
.interact-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
.interact-count {
|
||||
margin-top: 4px;
|
||||
}
|
||||
</style>
|
||||
@@ -109,6 +109,12 @@ export default {
|
||||
url: '/pages/workbench/customer/customer',
|
||||
category: '信息中心'
|
||||
},
|
||||
{
|
||||
text: '通知公告',
|
||||
icon: '/static/images/notice.png',
|
||||
url: '/pages/workbench/notice/notice',
|
||||
category: '信息中心'
|
||||
},
|
||||
{
|
||||
text: '库存盘点',
|
||||
icon: '/static/images/stock.png',
|
||||
|
||||
@@ -1,22 +1,98 @@
|
||||
<template>
|
||||
<view>
|
||||
<!-- 通知公告列表,展示noticeTitle, createBy, createTime -->
|
||||
<div class="notice-list-container">
|
||||
<!-- 判空提示 -->
|
||||
<div class="empty-tip" v-if="notices.length === 0">
|
||||
暂无通知公告
|
||||
</div>
|
||||
|
||||
</view>
|
||||
<!-- 公告列表 -->
|
||||
<div class="notice-list" v-else>
|
||||
<div class="notice-item" v-for="(notice, index) in notices" :key="index" @click="toDetail(notice.noticeId)">
|
||||
<div class="notice-title">{{ notice.noticeTitle }}</div>
|
||||
<div class="notice-meta">
|
||||
<span class="create-by">{{ notice.createBy || '未知发布人' }}</span>
|
||||
<span class="create-time">{{ notice.createTime || '未知时间' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
import { listNotice } from '@/api/oa/notice.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
notices: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
listNotice({ pageSize: 999, pageNum: 1 }).then(res => {
|
||||
// 确保res.rows存在,避免空数据报错
|
||||
this.notices = res?.rows || [];
|
||||
}).catch(err => {
|
||||
console.error('获取通知公告失败', err);
|
||||
this.notices = [];
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
|
||||
toDetail(id) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/workbench/article/article?type=notice&id=' + id
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style scoped lang="scss">
|
||||
.notice-list-container {
|
||||
background-color: #f5f5f5; // 米色背景
|
||||
padding: 15px;
|
||||
min-height: 100vh; // 避免容器过矮
|
||||
|
||||
.empty-tip {
|
||||
text-align: center;
|
||||
padding: 30px 0;
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.notice-list {
|
||||
.notice-item {
|
||||
background-color: #fff; // 白色公告背景
|
||||
padding: 12px 15px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.05); // 轻微阴影增强层次感
|
||||
|
||||
.notice-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
margin-bottom: 8px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis; // 标题过长省略
|
||||
}
|
||||
|
||||
.notice-meta {
|
||||
display: flex;
|
||||
justify-content: space-between; // 发布人和时间两端对齐
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
|
||||
.create-by {
|
||||
&:after {
|
||||
content: '|'; // 分隔符
|
||||
margin: 0 8px;
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -64,10 +64,7 @@
|
||||
|
||||
<uni-forms ref="financeForm" :model="form" :rules="rules" label-width="150rpx">
|
||||
<uni-forms-item label="财务类型" name="financeType">
|
||||
<uni-data-checkbox mode="tag" v-model="form.financeType" :localdata="[
|
||||
{ value: "1", text: '出账' },
|
||||
{ value: '2', text: '入账' }
|
||||
]"></uni-data-checkbox>
|
||||
<uni-data-checkbox mode="tag" v-model="form.financeType" :localdata="financeTypeOption"></uni-data-checkbox>
|
||||
</uni-forms-item>
|
||||
|
||||
<uni-forms-item label="记录名称" name="financeTitle">
|
||||
@@ -282,6 +279,10 @@ export default {
|
||||
currentFinance: {
|
||||
detailList: []
|
||||
},
|
||||
financeTypeOption: [
|
||||
{ value: "1", text: '出账' },
|
||||
{ value: '2', text: '入账' }
|
||||
],
|
||||
loading: false,
|
||||
|
||||
// 表单数据 - 默认包含一条空明细
|
||||
|
||||
BIN
static/images/notice.png
Normal file
BIN
static/images/notice.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
4
uni_modules/mumu-h5office/changelog.md
Normal file
4
uni_modules/mumu-h5office/changelog.md
Normal file
@@ -0,0 +1,4 @@
|
||||
## 1.0.1(2023-02-17)
|
||||
文档更新
|
||||
## 1.0.0(2023-02-15)
|
||||
版本上架
|
||||
@@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<view class="appGetFile" id="appGetFile"></view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { BASE_URL } from './config.js'
|
||||
import { aesEncrypt } from './tool.js'
|
||||
|
||||
var wv //计划创建的webview
|
||||
let inter
|
||||
export default {
|
||||
props: {
|
||||
appid: {
|
||||
type: String
|
||||
},
|
||||
currentWebview: {
|
||||
type: Object
|
||||
},
|
||||
btnStyle: {
|
||||
type: String,
|
||||
default: 'font-size: 14px;background-color: aqua;'
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
default: '<button>按钮</button>'
|
||||
},
|
||||
isShow: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
appid: {
|
||||
handler() {
|
||||
this.appidKey = aesEncrypt(this.appid)
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
isShow: {
|
||||
handler(newVal) {
|
||||
wv.setVisible(newVal)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// #ifdef APP-PLUS
|
||||
const params = {
|
||||
btnStyle: this.btnStyle,
|
||||
content: this.content
|
||||
}
|
||||
|
||||
this.$nextTick(() => {
|
||||
wv = plus.webview.create('', 'custom-webview', {
|
||||
cachemode: 'noCache'
|
||||
})
|
||||
plus.globalEvent.addEventListener('plusMessage', e => {
|
||||
if (wv && wv['__uuid__'] === e.originId) {
|
||||
this.childEvent(e.data.args.data.arg)
|
||||
}
|
||||
})
|
||||
|
||||
wv.loadURL(this.BASE_URL + this.API + '?params=' + encodeURIComponent(JSON.stringify(params)))
|
||||
this.currentWebview.append(wv)
|
||||
this.setPosition()
|
||||
|
||||
setTimeout(() => {
|
||||
wv.evalJS("getAppidKey({type:'event',appidKey:'" + this.appidKey + "'})")
|
||||
}, 500)
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
BASE_URL: BASE_URL,
|
||||
API: '/appWebViewUploadFile',
|
||||
appidKey: '',
|
||||
top: 100
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// appGetFileClick() {
|
||||
// wv.evalJS("onGetFile({type:'event',appidKey:'" + this.appidKey + "'})")
|
||||
// },
|
||||
|
||||
childEvent(data) {
|
||||
if (data.type && data.type === 'webOffice') {
|
||||
switch (data.event) {
|
||||
case 'error':
|
||||
//this.showErrorMsg(data.msg)
|
||||
this.$emit('error', data.msg)
|
||||
break
|
||||
case 'success':
|
||||
this.$emit('success', data.msg)
|
||||
break
|
||||
case 'readFile':
|
||||
this.$emit('readFile', data.msg)
|
||||
break
|
||||
case 'complete':
|
||||
this.$emit('complete', data.msg)
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
showErrorMsg(msg) {
|
||||
uni.showModal({
|
||||
title: '系统异常!',
|
||||
content: msg,
|
||||
showCancel: false,
|
||||
success: () => {
|
||||
//this.closePre()
|
||||
}
|
||||
})
|
||||
},
|
||||
setPosition() {
|
||||
inter && clearInterval(inter)
|
||||
const h = uni.getSystemInfoSync().screenHeight - uni.getSystemInfoSync().windowHeight
|
||||
inter = setInterval(() => {
|
||||
const query = uni.createSelectorQuery()
|
||||
query.select('#appGetFile').boundingClientRect()
|
||||
query.selectViewport().scrollOffset()
|
||||
query.exec(res => {
|
||||
const dome = res[0]
|
||||
wv.setStyle({
|
||||
top: h + dome.top,
|
||||
left: dome.left,
|
||||
height: dome.height,
|
||||
width: dome.width
|
||||
})
|
||||
})
|
||||
}, 15)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.appGetFile {
|
||||
width: 200px;
|
||||
height: 80px;
|
||||
}
|
||||
</style>
|
||||
19
uni_modules/mumu-h5office/components/mumu-h5office/config.js
Normal file
19
uni_modules/mumu-h5office/components/mumu-h5office/config.js
Normal file
@@ -0,0 +1,19 @@
|
||||
/* 支持的文件 */
|
||||
export const FILE_TYPES = ['csv', 'djvu', 'doc', 'docm', 'docx', 'docxf', 'dot', 'dotm', 'dotx', 'epub', 'fb2', 'fodp',
|
||||
'fods', 'fodt', 'htm', 'html', 'mht', 'odp', 'ods', 'odt', 'oform', 'otp', 'ots', 'ott', 'oxps', 'pdf', 'pot',
|
||||
'potm', 'potx', 'pps', 'ppsm', 'ppsx', 'ppt', 'pptm', 'pptx', 'rtf', 'txt', 'xls', 'xlsb', 'xlsm', 'xlsx',
|
||||
'xlt',
|
||||
'xltm', 'xltx', 'xml', 'xps'
|
||||
]
|
||||
|
||||
/* */
|
||||
export const BASE_URL = 'https://tool.h5office.cn/index.php'
|
||||
|
||||
export const AES_KEY = "68d7eec0ba694a68"
|
||||
|
||||
export const PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmkANmC849IOntYQQdSgLvMMGm
|
||||
8V/u838ATHaoZwvweoYyd+/7Wx+bx5bdktJb46YbqS1vz3VRdXsyJIWhpNcmtKhY
|
||||
inwcl83aLtzJeKsznppqMyAIseaKIeAm6tT8uttNkr2zOymL/PbMpByTQeEFlyy1
|
||||
poLBwrol0F4USc+owwIDAQAB
|
||||
-----END PUBLIC KEY-----`
|
||||
753
uni_modules/mumu-h5office/components/mumu-h5office/index.umd.js
Normal file
753
uni_modules/mumu-h5office/components/mumu-h5office/index.umd.js
Normal file
@@ -0,0 +1,753 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
||||
typeof define === 'function' && define.amd ? define(factory) :
|
||||
(global.browserMD5File = factory());
|
||||
}(this, (function () { 'use strict';
|
||||
|
||||
function createCommonjsModule(fn, module) {
|
||||
return module = { exports: {} }, fn(module, module.exports), module.exports;
|
||||
}
|
||||
|
||||
var sparkMd5 = createCommonjsModule(function (module, exports) {
|
||||
(function (factory) {
|
||||
{
|
||||
// Node/CommonJS
|
||||
module.exports = factory();
|
||||
}
|
||||
}(function (undefined) {
|
||||
|
||||
/*
|
||||
* Fastest md5 implementation around (JKM md5).
|
||||
* Credits: Joseph Myers
|
||||
*
|
||||
* @see http://www.myersdaily.org/joseph/javascript/md5-text.html
|
||||
* @see http://jsperf.com/md5-shootout/7
|
||||
*/
|
||||
|
||||
/* this function is much faster,
|
||||
so if possible we use it. Some IEs
|
||||
are the only ones I know of that
|
||||
need the idiotic second function,
|
||||
generated by an if clause. */
|
||||
var add32 = function (a, b) {
|
||||
return (a + b) & 0xFFFFFFFF;
|
||||
},
|
||||
hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
|
||||
|
||||
|
||||
function cmn(q, a, b, x, s, t) {
|
||||
a = add32(add32(a, q), add32(x, t));
|
||||
return add32((a << s) | (a >>> (32 - s)), b);
|
||||
}
|
||||
|
||||
function ff(a, b, c, d, x, s, t) {
|
||||
return cmn((b & c) | ((~b) & d), a, b, x, s, t);
|
||||
}
|
||||
|
||||
function gg(a, b, c, d, x, s, t) {
|
||||
return cmn((b & d) | (c & (~d)), a, b, x, s, t);
|
||||
}
|
||||
|
||||
function hh(a, b, c, d, x, s, t) {
|
||||
return cmn(b ^ c ^ d, a, b, x, s, t);
|
||||
}
|
||||
|
||||
function ii(a, b, c, d, x, s, t) {
|
||||
return cmn(c ^ (b | (~d)), a, b, x, s, t);
|
||||
}
|
||||
|
||||
function md5cycle(x, k) {
|
||||
var a = x[0],
|
||||
b = x[1],
|
||||
c = x[2],
|
||||
d = x[3];
|
||||
|
||||
a = ff(a, b, c, d, k[0], 7, -680876936);
|
||||
d = ff(d, a, b, c, k[1], 12, -389564586);
|
||||
c = ff(c, d, a, b, k[2], 17, 606105819);
|
||||
b = ff(b, c, d, a, k[3], 22, -1044525330);
|
||||
a = ff(a, b, c, d, k[4], 7, -176418897);
|
||||
d = ff(d, a, b, c, k[5], 12, 1200080426);
|
||||
c = ff(c, d, a, b, k[6], 17, -1473231341);
|
||||
b = ff(b, c, d, a, k[7], 22, -45705983);
|
||||
a = ff(a, b, c, d, k[8], 7, 1770035416);
|
||||
d = ff(d, a, b, c, k[9], 12, -1958414417);
|
||||
c = ff(c, d, a, b, k[10], 17, -42063);
|
||||
b = ff(b, c, d, a, k[11], 22, -1990404162);
|
||||
a = ff(a, b, c, d, k[12], 7, 1804603682);
|
||||
d = ff(d, a, b, c, k[13], 12, -40341101);
|
||||
c = ff(c, d, a, b, k[14], 17, -1502002290);
|
||||
b = ff(b, c, d, a, k[15], 22, 1236535329);
|
||||
|
||||
a = gg(a, b, c, d, k[1], 5, -165796510);
|
||||
d = gg(d, a, b, c, k[6], 9, -1069501632);
|
||||
c = gg(c, d, a, b, k[11], 14, 643717713);
|
||||
b = gg(b, c, d, a, k[0], 20, -373897302);
|
||||
a = gg(a, b, c, d, k[5], 5, -701558691);
|
||||
d = gg(d, a, b, c, k[10], 9, 38016083);
|
||||
c = gg(c, d, a, b, k[15], 14, -660478335);
|
||||
b = gg(b, c, d, a, k[4], 20, -405537848);
|
||||
a = gg(a, b, c, d, k[9], 5, 568446438);
|
||||
d = gg(d, a, b, c, k[14], 9, -1019803690);
|
||||
c = gg(c, d, a, b, k[3], 14, -187363961);
|
||||
b = gg(b, c, d, a, k[8], 20, 1163531501);
|
||||
a = gg(a, b, c, d, k[13], 5, -1444681467);
|
||||
d = gg(d, a, b, c, k[2], 9, -51403784);
|
||||
c = gg(c, d, a, b, k[7], 14, 1735328473);
|
||||
b = gg(b, c, d, a, k[12], 20, -1926607734);
|
||||
|
||||
a = hh(a, b, c, d, k[5], 4, -378558);
|
||||
d = hh(d, a, b, c, k[8], 11, -2022574463);
|
||||
c = hh(c, d, a, b, k[11], 16, 1839030562);
|
||||
b = hh(b, c, d, a, k[14], 23, -35309556);
|
||||
a = hh(a, b, c, d, k[1], 4, -1530992060);
|
||||
d = hh(d, a, b, c, k[4], 11, 1272893353);
|
||||
c = hh(c, d, a, b, k[7], 16, -155497632);
|
||||
b = hh(b, c, d, a, k[10], 23, -1094730640);
|
||||
a = hh(a, b, c, d, k[13], 4, 681279174);
|
||||
d = hh(d, a, b, c, k[0], 11, -358537222);
|
||||
c = hh(c, d, a, b, k[3], 16, -722521979);
|
||||
b = hh(b, c, d, a, k[6], 23, 76029189);
|
||||
a = hh(a, b, c, d, k[9], 4, -640364487);
|
||||
d = hh(d, a, b, c, k[12], 11, -421815835);
|
||||
c = hh(c, d, a, b, k[15], 16, 530742520);
|
||||
b = hh(b, c, d, a, k[2], 23, -995338651);
|
||||
|
||||
a = ii(a, b, c, d, k[0], 6, -198630844);
|
||||
d = ii(d, a, b, c, k[7], 10, 1126891415);
|
||||
c = ii(c, d, a, b, k[14], 15, -1416354905);
|
||||
b = ii(b, c, d, a, k[5], 21, -57434055);
|
||||
a = ii(a, b, c, d, k[12], 6, 1700485571);
|
||||
d = ii(d, a, b, c, k[3], 10, -1894986606);
|
||||
c = ii(c, d, a, b, k[10], 15, -1051523);
|
||||
b = ii(b, c, d, a, k[1], 21, -2054922799);
|
||||
a = ii(a, b, c, d, k[8], 6, 1873313359);
|
||||
d = ii(d, a, b, c, k[15], 10, -30611744);
|
||||
c = ii(c, d, a, b, k[6], 15, -1560198380);
|
||||
b = ii(b, c, d, a, k[13], 21, 1309151649);
|
||||
a = ii(a, b, c, d, k[4], 6, -145523070);
|
||||
d = ii(d, a, b, c, k[11], 10, -1120210379);
|
||||
c = ii(c, d, a, b, k[2], 15, 718787259);
|
||||
b = ii(b, c, d, a, k[9], 21, -343485551);
|
||||
|
||||
x[0] = add32(a, x[0]);
|
||||
x[1] = add32(b, x[1]);
|
||||
x[2] = add32(c, x[2]);
|
||||
x[3] = add32(d, x[3]);
|
||||
}
|
||||
|
||||
function md5blk(s) {
|
||||
var md5blks = [],
|
||||
i; /* Andy King said do it this way. */
|
||||
|
||||
for (i = 0; i < 64; i += 4) {
|
||||
md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
|
||||
}
|
||||
return md5blks;
|
||||
}
|
||||
|
||||
function md5blk_array(a) {
|
||||
var md5blks = [],
|
||||
i; /* Andy King said do it this way. */
|
||||
|
||||
for (i = 0; i < 64; i += 4) {
|
||||
md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
|
||||
}
|
||||
return md5blks;
|
||||
}
|
||||
|
||||
function md51(s) {
|
||||
var n = s.length,
|
||||
state = [1732584193, -271733879, -1732584194, 271733878],
|
||||
i,
|
||||
length,
|
||||
tail,
|
||||
tmp,
|
||||
lo,
|
||||
hi;
|
||||
|
||||
for (i = 64; i <= n; i += 64) {
|
||||
md5cycle(state, md5blk(s.substring(i - 64, i)));
|
||||
}
|
||||
s = s.substring(i - 64);
|
||||
length = s.length;
|
||||
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
for (i = 0; i < length; i += 1) {
|
||||
tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);
|
||||
}
|
||||
tail[i >> 2] |= 0x80 << ((i % 4) << 3);
|
||||
if (i > 55) {
|
||||
md5cycle(state, tail);
|
||||
for (i = 0; i < 16; i += 1) {
|
||||
tail[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Beware that the final length might not fit in 32 bits so we take care of that
|
||||
tmp = n * 8;
|
||||
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
|
||||
lo = parseInt(tmp[2], 16);
|
||||
hi = parseInt(tmp[1], 16) || 0;
|
||||
|
||||
tail[14] = lo;
|
||||
tail[15] = hi;
|
||||
|
||||
md5cycle(state, tail);
|
||||
return state;
|
||||
}
|
||||
|
||||
function md51_array(a) {
|
||||
var n = a.length,
|
||||
state = [1732584193, -271733879, -1732584194, 271733878],
|
||||
i,
|
||||
length,
|
||||
tail,
|
||||
tmp,
|
||||
lo,
|
||||
hi;
|
||||
|
||||
for (i = 64; i <= n; i += 64) {
|
||||
md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
|
||||
}
|
||||
|
||||
// Not sure if it is a bug, however IE10 will always produce a sub array of length 1
|
||||
// containing the last element of the parent array if the sub array specified starts
|
||||
// beyond the length of the parent array - weird.
|
||||
// https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue
|
||||
a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0);
|
||||
|
||||
length = a.length;
|
||||
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
for (i = 0; i < length; i += 1) {
|
||||
tail[i >> 2] |= a[i] << ((i % 4) << 3);
|
||||
}
|
||||
|
||||
tail[i >> 2] |= 0x80 << ((i % 4) << 3);
|
||||
if (i > 55) {
|
||||
md5cycle(state, tail);
|
||||
for (i = 0; i < 16; i += 1) {
|
||||
tail[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Beware that the final length might not fit in 32 bits so we take care of that
|
||||
tmp = n * 8;
|
||||
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
|
||||
lo = parseInt(tmp[2], 16);
|
||||
hi = parseInt(tmp[1], 16) || 0;
|
||||
|
||||
tail[14] = lo;
|
||||
tail[15] = hi;
|
||||
|
||||
md5cycle(state, tail);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
function rhex(n) {
|
||||
var s = '',
|
||||
j;
|
||||
for (j = 0; j < 4; j += 1) {
|
||||
s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function hex(x) {
|
||||
var i;
|
||||
for (i = 0; i < x.length; i += 1) {
|
||||
x[i] = rhex(x[i]);
|
||||
}
|
||||
return x.join('');
|
||||
}
|
||||
|
||||
// In some cases the fast add32 function cannot be used..
|
||||
if (hex(md51('hello')) !== '5d41402abc4b2a76b9719d911017c592') {
|
||||
add32 = function (x, y) {
|
||||
var lsw = (x & 0xFFFF) + (y & 0xFFFF),
|
||||
msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
||||
return (msw << 16) | (lsw & 0xFFFF);
|
||||
};
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
|
||||
/**
|
||||
* ArrayBuffer slice polyfill.
|
||||
*
|
||||
* @see https://github.com/ttaubert/node-arraybuffer-slice
|
||||
*/
|
||||
|
||||
if (typeof ArrayBuffer !== 'undefined' && !ArrayBuffer.prototype.slice) {
|
||||
(function () {
|
||||
function clamp(val, length) {
|
||||
val = (val | 0) || 0;
|
||||
|
||||
if (val < 0) {
|
||||
return Math.max(val + length, 0);
|
||||
}
|
||||
|
||||
return Math.min(val, length);
|
||||
}
|
||||
|
||||
ArrayBuffer.prototype.slice = function (from, to) {
|
||||
var length = this.byteLength,
|
||||
begin = clamp(from, length),
|
||||
end = length,
|
||||
num,
|
||||
target,
|
||||
targetArray,
|
||||
sourceArray;
|
||||
|
||||
if (to !== undefined) {
|
||||
end = clamp(to, length);
|
||||
}
|
||||
|
||||
if (begin > end) {
|
||||
return new ArrayBuffer(0);
|
||||
}
|
||||
|
||||
num = end - begin;
|
||||
target = new ArrayBuffer(num);
|
||||
targetArray = new Uint8Array(target);
|
||||
|
||||
sourceArray = new Uint8Array(this, begin, num);
|
||||
targetArray.set(sourceArray);
|
||||
|
||||
return target;
|
||||
};
|
||||
})();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
|
||||
/**
|
||||
* Helpers.
|
||||
*/
|
||||
|
||||
function toUtf8(str) {
|
||||
if (/[\u0080-\uFFFF]/.test(str)) {
|
||||
str = unescape(encodeURIComponent(str));
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
function utf8Str2ArrayBuffer(str, returnUInt8Array) {
|
||||
var length = str.length,
|
||||
buff = new ArrayBuffer(length),
|
||||
arr = new Uint8Array(buff),
|
||||
i;
|
||||
|
||||
for (i = 0; i < length; i += 1) {
|
||||
arr[i] = str.charCodeAt(i);
|
||||
}
|
||||
|
||||
return returnUInt8Array ? arr : buff;
|
||||
}
|
||||
|
||||
function arrayBuffer2Utf8Str(buff) {
|
||||
return String.fromCharCode.apply(null, new Uint8Array(buff));
|
||||
}
|
||||
|
||||
function concatenateArrayBuffers(first, second, returnUInt8Array) {
|
||||
var result = new Uint8Array(first.byteLength + second.byteLength);
|
||||
|
||||
result.set(new Uint8Array(first));
|
||||
result.set(new Uint8Array(second), first.byteLength);
|
||||
|
||||
return returnUInt8Array ? result : result.buffer;
|
||||
}
|
||||
|
||||
function hexToBinaryString(hex) {
|
||||
var bytes = [],
|
||||
length = hex.length,
|
||||
x;
|
||||
|
||||
for (x = 0; x < length - 1; x += 2) {
|
||||
bytes.push(parseInt(hex.substr(x, 2), 16));
|
||||
}
|
||||
|
||||
return String.fromCharCode.apply(String, bytes);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------
|
||||
|
||||
/**
|
||||
* SparkMD5 OOP implementation.
|
||||
*
|
||||
* Use this class to perform an incremental md5, otherwise use the
|
||||
* static methods instead.
|
||||
*/
|
||||
|
||||
function SparkMD5() {
|
||||
// call reset to init the instance
|
||||
this.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a string.
|
||||
* A conversion will be applied if an utf8 string is detected.
|
||||
*
|
||||
* @param {String} str The string to be appended
|
||||
*
|
||||
* @return {SparkMD5} The instance itself
|
||||
*/
|
||||
SparkMD5.prototype.append = function (str) {
|
||||
// Converts the string to utf8 bytes if necessary
|
||||
// Then append as binary
|
||||
this.appendBinary(toUtf8(str));
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Appends a binary string.
|
||||
*
|
||||
* @param {String} contents The binary string to be appended
|
||||
*
|
||||
* @return {SparkMD5} The instance itself
|
||||
*/
|
||||
SparkMD5.prototype.appendBinary = function (contents) {
|
||||
this._buff += contents;
|
||||
this._length += contents.length;
|
||||
|
||||
var length = this._buff.length,
|
||||
i;
|
||||
|
||||
for (i = 64; i <= length; i += 64) {
|
||||
md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i)));
|
||||
}
|
||||
|
||||
this._buff = this._buff.substring(i - 64);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Finishes the incremental computation, reseting the internal state and
|
||||
* returning the result.
|
||||
*
|
||||
* @param {Boolean} raw True to get the raw string, false to get the hex string
|
||||
*
|
||||
* @return {String} The result
|
||||
*/
|
||||
SparkMD5.prototype.end = function (raw) {
|
||||
var buff = this._buff,
|
||||
length = buff.length,
|
||||
i,
|
||||
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
ret;
|
||||
|
||||
for (i = 0; i < length; i += 1) {
|
||||
tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3);
|
||||
}
|
||||
|
||||
this._finish(tail, length);
|
||||
ret = hex(this._hash);
|
||||
|
||||
if (raw) {
|
||||
ret = hexToBinaryString(ret);
|
||||
}
|
||||
|
||||
this.reset();
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* Resets the internal state of the computation.
|
||||
*
|
||||
* @return {SparkMD5} The instance itself
|
||||
*/
|
||||
SparkMD5.prototype.reset = function () {
|
||||
this._buff = '';
|
||||
this._length = 0;
|
||||
this._hash = [1732584193, -271733879, -1732584194, 271733878];
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the internal state of the computation.
|
||||
*
|
||||
* @return {Object} The state
|
||||
*/
|
||||
SparkMD5.prototype.getState = function () {
|
||||
return {
|
||||
buff: this._buff,
|
||||
length: this._length,
|
||||
hash: this._hash
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the internal state of the computation.
|
||||
*
|
||||
* @param {Object} state The state
|
||||
*
|
||||
* @return {SparkMD5} The instance itself
|
||||
*/
|
||||
SparkMD5.prototype.setState = function (state) {
|
||||
this._buff = state.buff;
|
||||
this._length = state.length;
|
||||
this._hash = state.hash;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Releases memory used by the incremental buffer and other additional
|
||||
* resources. If you plan to use the instance again, use reset instead.
|
||||
*/
|
||||
SparkMD5.prototype.destroy = function () {
|
||||
delete this._hash;
|
||||
delete this._buff;
|
||||
delete this._length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Finish the final calculation based on the tail.
|
||||
*
|
||||
* @param {Array} tail The tail (will be modified)
|
||||
* @param {Number} length The length of the remaining buffer
|
||||
*/
|
||||
SparkMD5.prototype._finish = function (tail, length) {
|
||||
var i = length,
|
||||
tmp,
|
||||
lo,
|
||||
hi;
|
||||
|
||||
tail[i >> 2] |= 0x80 << ((i % 4) << 3);
|
||||
if (i > 55) {
|
||||
md5cycle(this._hash, tail);
|
||||
for (i = 0; i < 16; i += 1) {
|
||||
tail[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Do the final computation based on the tail and length
|
||||
// Beware that the final length may not fit in 32 bits so we take care of that
|
||||
tmp = this._length * 8;
|
||||
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
|
||||
lo = parseInt(tmp[2], 16);
|
||||
hi = parseInt(tmp[1], 16) || 0;
|
||||
|
||||
tail[14] = lo;
|
||||
tail[15] = hi;
|
||||
md5cycle(this._hash, tail);
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs the md5 hash on a string.
|
||||
* A conversion will be applied if utf8 string is detected.
|
||||
*
|
||||
* @param {String} str The string
|
||||
* @param {Boolean} raw True to get the raw string, false to get the hex string
|
||||
*
|
||||
* @return {String} The result
|
||||
*/
|
||||
SparkMD5.hash = function (str, raw) {
|
||||
// Converts the string to utf8 bytes if necessary
|
||||
// Then compute it using the binary function
|
||||
return SparkMD5.hashBinary(toUtf8(str), raw);
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs the md5 hash on a binary string.
|
||||
*
|
||||
* @param {String} content The binary string
|
||||
* @param {Boolean} raw True to get the raw string, false to get the hex string
|
||||
*
|
||||
* @return {String} The result
|
||||
*/
|
||||
SparkMD5.hashBinary = function (content, raw) {
|
||||
var hash = md51(content),
|
||||
ret = hex(hash);
|
||||
|
||||
return raw ? hexToBinaryString(ret) : ret;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------
|
||||
|
||||
/**
|
||||
* SparkMD5 OOP implementation for array buffers.
|
||||
*
|
||||
* Use this class to perform an incremental md5 ONLY for array buffers.
|
||||
*/
|
||||
SparkMD5.ArrayBuffer = function () {
|
||||
// call reset to init the instance
|
||||
this.reset();
|
||||
};
|
||||
|
||||
/**
|
||||
* Appends an array buffer.
|
||||
*
|
||||
* @param {ArrayBuffer} arr The array to be appended
|
||||
*
|
||||
* @return {SparkMD5.ArrayBuffer} The instance itself
|
||||
*/
|
||||
SparkMD5.ArrayBuffer.prototype.append = function (arr) {
|
||||
var buff = concatenateArrayBuffers(this._buff.buffer, arr, true),
|
||||
length = buff.length,
|
||||
i;
|
||||
|
||||
this._length += arr.byteLength;
|
||||
|
||||
for (i = 64; i <= length; i += 64) {
|
||||
md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i)));
|
||||
}
|
||||
|
||||
this._buff = (i - 64) < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Finishes the incremental computation, reseting the internal state and
|
||||
* returning the result.
|
||||
*
|
||||
* @param {Boolean} raw True to get the raw string, false to get the hex string
|
||||
*
|
||||
* @return {String} The result
|
||||
*/
|
||||
SparkMD5.ArrayBuffer.prototype.end = function (raw) {
|
||||
var buff = this._buff,
|
||||
length = buff.length,
|
||||
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
i,
|
||||
ret;
|
||||
|
||||
for (i = 0; i < length; i += 1) {
|
||||
tail[i >> 2] |= buff[i] << ((i % 4) << 3);
|
||||
}
|
||||
|
||||
this._finish(tail, length);
|
||||
ret = hex(this._hash);
|
||||
|
||||
if (raw) {
|
||||
ret = hexToBinaryString(ret);
|
||||
}
|
||||
|
||||
this.reset();
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
* Resets the internal state of the computation.
|
||||
*
|
||||
* @return {SparkMD5.ArrayBuffer} The instance itself
|
||||
*/
|
||||
SparkMD5.ArrayBuffer.prototype.reset = function () {
|
||||
this._buff = new Uint8Array(0);
|
||||
this._length = 0;
|
||||
this._hash = [1732584193, -271733879, -1732584194, 271733878];
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the internal state of the computation.
|
||||
*
|
||||
* @return {Object} The state
|
||||
*/
|
||||
SparkMD5.ArrayBuffer.prototype.getState = function () {
|
||||
var state = SparkMD5.prototype.getState.call(this);
|
||||
|
||||
// Convert buffer to a string
|
||||
state.buff = arrayBuffer2Utf8Str(state.buff);
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the internal state of the computation.
|
||||
*
|
||||
* @param {Object} state The state
|
||||
*
|
||||
* @return {SparkMD5.ArrayBuffer} The instance itself
|
||||
*/
|
||||
SparkMD5.ArrayBuffer.prototype.setState = function (state) {
|
||||
// Convert string to buffer
|
||||
state.buff = utf8Str2ArrayBuffer(state.buff, true);
|
||||
|
||||
return SparkMD5.prototype.setState.call(this, state);
|
||||
};
|
||||
|
||||
SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;
|
||||
|
||||
SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;
|
||||
|
||||
/**
|
||||
* Performs the md5 hash on an array buffer.
|
||||
*
|
||||
* @param {ArrayBuffer} arr The array buffer
|
||||
* @param {Boolean} raw True to get the raw string, false to get the hex one
|
||||
*
|
||||
* @return {String} The result
|
||||
*/
|
||||
SparkMD5.ArrayBuffer.hash = function (arr, raw) {
|
||||
var hash = md51_array(new Uint8Array(arr)),
|
||||
ret = hex(hash);
|
||||
|
||||
return raw ? hexToBinaryString(ret) : ret;
|
||||
};
|
||||
|
||||
return SparkMD5;
|
||||
}));
|
||||
});
|
||||
|
||||
class BMF {
|
||||
md5(file, md5Fn, progressFn) {
|
||||
this.aborted = false;
|
||||
this.progress = 0;
|
||||
let currentChunk = 0;
|
||||
const blobSlice =
|
||||
File.prototype.slice ||
|
||||
File.prototype.mozSlice ||
|
||||
File.prototype.webkitSlice;
|
||||
const chunkSize = 2097152;
|
||||
const chunks = Math.ceil(file.size / chunkSize);
|
||||
const spark = new sparkMd5.ArrayBuffer();
|
||||
const reader = new FileReader();
|
||||
|
||||
loadNext();
|
||||
|
||||
reader.onloadend = e => {
|
||||
spark.append(e.target.result); // Append array buffer
|
||||
currentChunk++;
|
||||
this.progress = currentChunk / chunks;
|
||||
|
||||
if (progressFn && typeof progressFn === 'function') {
|
||||
progressFn(this.progress);
|
||||
}
|
||||
|
||||
if (this.aborted) {
|
||||
md5Fn('aborted');
|
||||
return
|
||||
}
|
||||
|
||||
if (currentChunk < chunks) {
|
||||
loadNext();
|
||||
} else {
|
||||
md5Fn(null, spark.end());
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////
|
||||
function loadNext() {
|
||||
const start = currentChunk * chunkSize;
|
||||
const end = start + chunkSize >= file.size ? file.size : start + chunkSize;
|
||||
reader.readAsArrayBuffer(blobSlice.call(file, start, end));
|
||||
}
|
||||
}
|
||||
|
||||
abort() {
|
||||
this.aborted = true;
|
||||
}
|
||||
}
|
||||
|
||||
return BMF;
|
||||
|
||||
})));
|
||||
2
uni_modules/mumu-h5office/components/mumu-h5office/jsencrypt.min.js
vendored
Normal file
2
uni_modules/mumu-h5office/components/mumu-h5office/jsencrypt.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
219
uni_modules/mumu-h5office/components/mumu-h5office/md5.js
Normal file
219
uni_modules/mumu-h5office/components/mumu-h5office/md5.js
Normal file
@@ -0,0 +1,219 @@
|
||||
|
||||
var hexcase = 0;
|
||||
var b64pad = "";
|
||||
var chrsz = 8;
|
||||
|
||||
|
||||
export function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
|
||||
function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
|
||||
function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
|
||||
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
|
||||
function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
|
||||
function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
|
||||
|
||||
|
||||
function md5_vm_test()
|
||||
{
|
||||
return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
|
||||
}
|
||||
|
||||
|
||||
function core_md5(x, len)
|
||||
{
|
||||
x[len >> 5] |= 0x80 << ((len) % 32);
|
||||
x[(((len + 64) >>> 9) << 4) + 14] = len;
|
||||
|
||||
var a = 1732584193;
|
||||
var b = -271733879;
|
||||
var c = -1732584194;
|
||||
var d = 271733878;
|
||||
|
||||
for(var i = 0; i < x.length; i += 16)
|
||||
{
|
||||
var olda = a;
|
||||
var oldb = b;
|
||||
var oldc = c;
|
||||
var oldd = d;
|
||||
|
||||
a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
|
||||
d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
|
||||
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
|
||||
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
|
||||
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
|
||||
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
|
||||
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
|
||||
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
|
||||
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
|
||||
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
|
||||
c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
|
||||
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
|
||||
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
|
||||
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
|
||||
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
|
||||
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
|
||||
|
||||
a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
|
||||
d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
|
||||
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
|
||||
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
|
||||
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
|
||||
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
|
||||
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
|
||||
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
|
||||
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
|
||||
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
|
||||
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
|
||||
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
|
||||
a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
|
||||
d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
|
||||
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
|
||||
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
|
||||
|
||||
a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
|
||||
d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
|
||||
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
|
||||
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
|
||||
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
|
||||
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
|
||||
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
|
||||
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
|
||||
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
|
||||
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
|
||||
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
|
||||
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
|
||||
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
|
||||
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
|
||||
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
|
||||
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
|
||||
|
||||
a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
|
||||
d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
|
||||
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
|
||||
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
|
||||
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
|
||||
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
|
||||
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
|
||||
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
|
||||
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
|
||||
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
|
||||
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
|
||||
b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
|
||||
a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
|
||||
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
|
||||
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
|
||||
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
|
||||
|
||||
a = safe_add(a, olda);
|
||||
b = safe_add(b, oldb);
|
||||
c = safe_add(c, oldc);
|
||||
d = safe_add(d, oldd);
|
||||
}
|
||||
return Array(a, b, c, d);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function md5_cmn(q, a, b, x, s, t)
|
||||
{
|
||||
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
|
||||
}
|
||||
function md5_ff(a, b, c, d, x, s, t)
|
||||
{
|
||||
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
|
||||
}
|
||||
function md5_gg(a, b, c, d, x, s, t)
|
||||
{
|
||||
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
|
||||
}
|
||||
function md5_hh(a, b, c, d, x, s, t)
|
||||
{
|
||||
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
|
||||
}
|
||||
function md5_ii(a, b, c, d, x, s, t)
|
||||
{
|
||||
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
|
||||
}
|
||||
|
||||
|
||||
function core_hmac_md5(key, data)
|
||||
{
|
||||
var bkey = str2binl(key);
|
||||
if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
|
||||
|
||||
var ipad = Array(16), opad = Array(16);
|
||||
for(var i = 0; i < 16; i++)
|
||||
{
|
||||
ipad[i] = bkey[i] ^ 0x36363636;
|
||||
opad[i] = bkey[i] ^ 0x5C5C5C5C;
|
||||
}
|
||||
|
||||
var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
|
||||
return core_md5(opad.concat(hash), 512 + 128);
|
||||
}
|
||||
|
||||
|
||||
function safe_add(x, y)
|
||||
{
|
||||
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
|
||||
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
||||
return (msw << 16) | (lsw & 0xFFFF);
|
||||
}
|
||||
|
||||
|
||||
function bit_rol(num, cnt)
|
||||
{
|
||||
return (num << cnt) | (num >>> (32 - cnt));
|
||||
}
|
||||
|
||||
|
||||
function str2binl(str)
|
||||
{
|
||||
var bin = Array();
|
||||
var mask = (1 << chrsz) - 1;
|
||||
for(var i = 0; i < str.length * chrsz; i += chrsz)
|
||||
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
|
||||
return bin;
|
||||
}
|
||||
|
||||
|
||||
function binl2str(bin)
|
||||
{
|
||||
var str = "";
|
||||
var mask = (1 << chrsz) - 1;
|
||||
for(var i = 0; i < bin.length * 32; i += chrsz)
|
||||
str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
function binl2hex(binarray)
|
||||
{
|
||||
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
|
||||
var str = "";
|
||||
for(var i = 0; i < binarray.length * 4; i++)
|
||||
{
|
||||
str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
|
||||
hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
function binl2b64(binarray)
|
||||
{
|
||||
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
var str = "";
|
||||
for(var i = 0; i < binarray.length * 4; i += 3)
|
||||
{
|
||||
var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)
|
||||
| (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
|
||||
| ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
|
||||
for(var j = 0; j < 4; j++)
|
||||
{
|
||||
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
|
||||
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,405 @@
|
||||
<template>
|
||||
<view class="preview" v-if="isShow">
|
||||
<template v-if="src">
|
||||
<!-- #ifdef APP -->
|
||||
<web-view :src="src" @message="webMess"></web-view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<iframe
|
||||
id="if"
|
||||
:src="src"
|
||||
align="top"
|
||||
frameborder="0"
|
||||
name="frameEditor"
|
||||
allowfullscreen=""
|
||||
onmousewheel=""
|
||||
allow="autoplay; camera; microphone; display-capture; clipboard-write;"
|
||||
style="position: fixed; overflow: hidden;"
|
||||
></iframe>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
<!-- <template v-else>
|
||||
{{ tps }}
|
||||
</template> -->
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import { FILE_TYPES, BASE_URL } from './config.js'
|
||||
import { hex_md5 } from './md5.js'
|
||||
import {
|
||||
browserFileToMd5,
|
||||
browserUploadFile,
|
||||
request,
|
||||
plus_io_getFileInfo,
|
||||
plus_uploader,
|
||||
aesEncrypt,
|
||||
colorRGBtoHex
|
||||
} from './tool.js'
|
||||
|
||||
export default {
|
||||
model: {
|
||||
prop: 'isShow',
|
||||
event: 'change'
|
||||
},
|
||||
props: {
|
||||
isShow: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
appid: {
|
||||
type: String
|
||||
},
|
||||
// #ifdef APP-PLUS
|
||||
file: {
|
||||
type: [String],
|
||||
default: ''
|
||||
},
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
file: {
|
||||
type: [String, File],
|
||||
default: ''
|
||||
},
|
||||
// #endif
|
||||
fileName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
privilege: {
|
||||
type: Array,
|
||||
default: () => ['copy', 'download', 'print']
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
isShow: {
|
||||
async handler() {
|
||||
this.src = ''
|
||||
if (!this.isShow) return
|
||||
if (!this.appid) return this.showErrorMsg('请填写appid')
|
||||
this.$emit('create')
|
||||
|
||||
let params = {
|
||||
fileUrl: '',
|
||||
fileName: '',
|
||||
fileExit: '',
|
||||
digest: '',
|
||||
type: '',
|
||||
privilege: this.privilege,
|
||||
appid: this.appidKey
|
||||
}
|
||||
|
||||
if (typeof this.file === 'string') {
|
||||
if (this.file.indexOf('http://') === 0 || this.file.indexOf('https://') === 0) {
|
||||
// 走网络文件
|
||||
const res = this.getHttpFileInfo(this.file, this.fileName)
|
||||
if (typeof res === 'string') return this.showErrorMsg(res)
|
||||
else
|
||||
params = {
|
||||
...params,
|
||||
...res
|
||||
}
|
||||
} else if (this.file.indexOf('md5::') === 0) {
|
||||
// app 外部上传
|
||||
const res = await this.getAppFileInfoToMd5(this.file)
|
||||
if (typeof res === 'string') return this.showErrorMsg(res)
|
||||
else
|
||||
params = {
|
||||
...params,
|
||||
...res
|
||||
}
|
||||
} else {
|
||||
// 走 app 内部本地上传
|
||||
try {
|
||||
const res = await this.getAppFileInfo(this.file)
|
||||
if (typeof res === 'string') return this.showErrorMsg(res)
|
||||
else
|
||||
params = {
|
||||
...params,
|
||||
...res
|
||||
}
|
||||
} catch (e) {
|
||||
return this.showErrorMsg('本地文件异常 001:' + e.msg ?? e.message)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 走浏览器本地上传
|
||||
try {
|
||||
if (this.file.lastModifiedDate) {
|
||||
const res = await this.getInputFileInfo(this.file)
|
||||
if (typeof res === 'string') return this.showErrorMsg(res)
|
||||
else
|
||||
params = {
|
||||
...params,
|
||||
...res
|
||||
}
|
||||
} else {
|
||||
return this.showErrorMsg('本地文件异常 002')
|
||||
}
|
||||
} catch (e) {
|
||||
return this.showErrorMsg('本地文件异常 001:' + e.msg ?? e.message)
|
||||
}
|
||||
}
|
||||
this.src = this.paseUrl(params)
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
appid: {
|
||||
handler() {
|
||||
this.appidKey = aesEncrypt(this.appid)
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
src: {
|
||||
handler(newVal) {
|
||||
if (newVal) {
|
||||
this.$emit('created')
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// #ifdef H5
|
||||
this.addH5Event()
|
||||
// #endif
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
src: '',
|
||||
tps: '文件读取中...',
|
||||
appidKey: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
closePre() {
|
||||
this.$emit('change', false)
|
||||
//this.$emit('update:openLocalFile', '')
|
||||
this.src = ''
|
||||
},
|
||||
paseUrl(param) {
|
||||
param['host'] = 'app'
|
||||
// #ifdef H5
|
||||
param['host'] = origin
|
||||
// #endif
|
||||
param = encodeURIComponent(JSON.stringify(param))
|
||||
return BASE_URL + '?param=' + param
|
||||
},
|
||||
getHttpFileInfo(src, fileName) {
|
||||
if (!fileName) {
|
||||
let path = src.split('/')
|
||||
if (!path.length) return '传入文件路径格式不正确或者文件名称后缀不正确'
|
||||
fileName = path.pop()
|
||||
}
|
||||
let exit = fileName.split('.')
|
||||
if (!exit.length) return '传入文件名称未添加后缀类型'
|
||||
exit = exit.pop()
|
||||
if (!FILE_TYPES.includes(exit)) return '传入文件格式不正确或者文件名称后缀不正确'
|
||||
return {
|
||||
fileUrl: src,
|
||||
fileName: fileName,
|
||||
fileExit: exit,
|
||||
digest: hex_md5(src),
|
||||
type: 'src'
|
||||
}
|
||||
},
|
||||
async getInputFileInfo(fileLocal) {
|
||||
try {
|
||||
const fileName = fileLocal.name
|
||||
let exit = fileName.split('.')
|
||||
if (!exit.length) return '传入文件名称未添加后缀类型'
|
||||
exit = exit.pop()
|
||||
if (!FILE_TYPES.includes(exit)) return '传入文件格式不正确或者文件名称后缀不正确'
|
||||
const fileMd5 = await browserFileToMd5(fileLocal)
|
||||
const fileInfo = {
|
||||
size: fileLocal.size,
|
||||
fileMd5: fileMd5,
|
||||
appid: this.appidKey
|
||||
}
|
||||
const checkRes = await request({
|
||||
url: '/checkFileInfo',
|
||||
type: 'POST',
|
||||
data: fileInfo
|
||||
})
|
||||
|
||||
if (checkRes.msg === 0) {
|
||||
const res = await browserUploadFile('/uploadLocalFile', fileLocal, {
|
||||
fileMd5: fileMd5,
|
||||
appid: this.appidKey,
|
||||
size: fileLocal.size,
|
||||
fileExit: exit,
|
||||
fileName: fileName + '(无缓存)',
|
||||
host: origin
|
||||
})
|
||||
}
|
||||
const fileUrl = 'http://localhost/' + fileMd5 + '.' + exit
|
||||
return {
|
||||
fileMd5: fileMd5,
|
||||
fileUrl: fileUrl,
|
||||
fileName: fileName,
|
||||
fileExit: exit,
|
||||
digest: hex_md5(fileUrl),
|
||||
type: 'localhost'
|
||||
}
|
||||
} catch (e) {
|
||||
throw e
|
||||
}
|
||||
},
|
||||
async getAppFileInfo(fileLocalPath) {
|
||||
try {
|
||||
let { size, digest: fileMd5 } = await plus_io_getFileInfo(fileLocalPath)
|
||||
fileMd5 = fileMd5.toLowerCase()
|
||||
const fileName = fileLocalPath.split('/').pop()
|
||||
let exit = fileName.split('.')
|
||||
if (!exit.length) return '传入文件名称未添加后缀类型'
|
||||
exit = exit.pop()
|
||||
if (!FILE_TYPES.includes(exit)) return '传入文件格式不正确或者文件名称后缀不正确'
|
||||
|
||||
const fileInfo = {
|
||||
size: size,
|
||||
fileMd5: fileMd5,
|
||||
appid: this.appidKey
|
||||
}
|
||||
const checkRes = await request({
|
||||
url: '/checkFileInfo',
|
||||
type: 'POST',
|
||||
data: fileInfo
|
||||
})
|
||||
if (checkRes.msg === 0) {
|
||||
const res = await plus_uploader('/uploadLocalFile', fileLocalPath, {
|
||||
fileMd5: fileMd5,
|
||||
appid: this.appidKey,
|
||||
size: size + '',
|
||||
fileExit: exit,
|
||||
fileName: fileName + '(无缓存)',
|
||||
host: 'app'
|
||||
})
|
||||
}
|
||||
|
||||
const fileUrl = 'http://localhost/' + fileMd5 + '.' + exit
|
||||
return {
|
||||
fileMd5: fileMd5,
|
||||
fileUrl: fileUrl,
|
||||
fileName: fileName,
|
||||
fileExit: exit,
|
||||
digest: hex_md5(fileUrl),
|
||||
type: 'localhost'
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e, 'err')
|
||||
throw e
|
||||
}
|
||||
},
|
||||
getAppFileInfoToMd5(fileLocalPath) {
|
||||
const fileName = fileLocalPath.replace('md5::', '')
|
||||
let exit = fileName.split('.')
|
||||
if (!exit.length) return '传入文件名称未添加后缀类型'
|
||||
const fileMd5 = exit[0]
|
||||
exit = exit.pop()
|
||||
if (!FILE_TYPES.includes(exit)) return '传入文件格式不正确或者文件名称后缀不正确'
|
||||
|
||||
const fileUrl = 'http://localhost/' + fileMd5 + '.' + exit
|
||||
return {
|
||||
fileMd5: fileMd5,
|
||||
fileUrl: fileUrl,
|
||||
fileName: fileName,
|
||||
fileExit: exit,
|
||||
digest: hex_md5(fileUrl),
|
||||
type: 'localhost'
|
||||
}
|
||||
},
|
||||
|
||||
addH5Event() {
|
||||
window.addEventListener(
|
||||
'message',
|
||||
e => {
|
||||
if (e.data && typeof e.data === 'string') {
|
||||
const data = JSON.parse(e.data)
|
||||
this.childEvent(data)
|
||||
}
|
||||
},
|
||||
false
|
||||
)
|
||||
},
|
||||
webMess(e) {
|
||||
this.childEvent(e.detail.data[0])
|
||||
},
|
||||
childEvent(data) {
|
||||
if (data.type && data.type === 'webOffice') {
|
||||
switch (data.event) {
|
||||
case 'close':
|
||||
this.closePre()
|
||||
this.$emit('close')
|
||||
break
|
||||
case 'error':
|
||||
this.showErrorMsg(data.msg)
|
||||
break
|
||||
case 'download':
|
||||
this.$emit('download', data.msg)
|
||||
break
|
||||
case 'init':
|
||||
let params = JSON.parse(data.msg)
|
||||
params.backgroundColor = colorRGBtoHex(params.backgroundColor)
|
||||
this.$emit('init', params)
|
||||
break
|
||||
case 'inited':
|
||||
let paramss = JSON.parse(data.msg)
|
||||
paramss.backgroundColor = colorRGBtoHex(paramss.backgroundColor)
|
||||
this.$emit('inited', paramss)
|
||||
break
|
||||
case 'readFiled':
|
||||
this.$emit('readFiled', data.msg)
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
showErrorMsg(msg) {
|
||||
this.$emit('error', msg)
|
||||
uni.showModal({
|
||||
title: '系统异常!',
|
||||
content: msg,
|
||||
showCancel: false,
|
||||
success: () => {
|
||||
this.closePre()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.preview {
|
||||
position: fixed;
|
||||
top: var(--window-top);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
background-color: #fff;
|
||||
|
||||
.error {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 10px;
|
||||
background-color: #ccc;
|
||||
color: #fff;
|
||||
padding: 5px 10px;
|
||||
border-radius: 5px;
|
||||
font-size: 12px;
|
||||
z-index: 102;
|
||||
}
|
||||
|
||||
#if {
|
||||
position: relative;
|
||||
z-index: 101;
|
||||
width: 100%;
|
||||
height: calc(100% - var(--window-top));
|
||||
}
|
||||
}
|
||||
</style>
|
||||
127
uni_modules/mumu-h5office/components/mumu-h5office/tool.js
Normal file
127
uni_modules/mumu-h5office/components/mumu-h5office/tool.js
Normal file
@@ -0,0 +1,127 @@
|
||||
import FileMd5 from './index.umd.js'
|
||||
import {
|
||||
BASE_URL,
|
||||
AES_KEY as aa,
|
||||
PUBLIC_KEY
|
||||
} from './config.js'
|
||||
import JSEncrypt from './jsencrypt.min.js'
|
||||
import {
|
||||
hex_md5
|
||||
} from './md5.js'
|
||||
|
||||
|
||||
|
||||
/** 浏览器获取文件 md5 */
|
||||
export const browserFileToMd5 = (file) => {
|
||||
return new Promise((resove, reject) => {
|
||||
const bmf = new FileMd5()
|
||||
bmf.md5(file, (err, md5) => {
|
||||
if (err) reject(err)
|
||||
resove(md5)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/** 浏览器上传文件 */
|
||||
export const browserUploadFile = (url, file, addData = {}) => {
|
||||
return new Promise((resove, reject) => {
|
||||
uni.uploadFile({
|
||||
url: BASE_URL + url,
|
||||
file,
|
||||
name: 'file',
|
||||
formData: addData,
|
||||
timeout: 1000 * 60 * 100,
|
||||
success({
|
||||
data
|
||||
}) {
|
||||
data = JSON.parse(data)
|
||||
if (data.code !== 200) reject(data)
|
||||
resove(data)
|
||||
},
|
||||
fail(err) {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/* 网络请求 */
|
||||
export const request = (options = {
|
||||
type: 'GET',
|
||||
url: '',
|
||||
data: {}
|
||||
}) => {
|
||||
return new Promise((resove, reject) => {
|
||||
uni.request({
|
||||
url: BASE_URL + options.url,
|
||||
method: options.type,
|
||||
data: options.data,
|
||||
success({
|
||||
data
|
||||
}) {
|
||||
if (data.code !== 200) reject(data)
|
||||
resove(data)
|
||||
},
|
||||
fail(err) {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
//
|
||||
/* 获取app文件信息 */
|
||||
export const plus_io_getFileInfo = (filePath) => {
|
||||
return new Promise((resove, reject) => {
|
||||
plus.io.getFileInfo({
|
||||
filePath,
|
||||
digestAlgorithm: 'md5',
|
||||
success: res => {
|
||||
resove(res)
|
||||
},
|
||||
fail: (err) => {
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/* app 文件上传 */
|
||||
export const plus_uploader = (url, filePath, addData = {}) => {
|
||||
return new Promise((resove, reject) => {
|
||||
const task = plus.uploader.createUpload(BASE_URL + url, {
|
||||
method: "POST",
|
||||
priority: 0
|
||||
},
|
||||
function(res, status) {
|
||||
if (status !== 200) reject(res)
|
||||
res = JSON.parse(res.responseText)
|
||||
if (res.code !== 200) reject(res)
|
||||
resove(res)
|
||||
}
|
||||
);
|
||||
task.addFile(filePath, {
|
||||
key: "file"
|
||||
});
|
||||
for (let key in addData) {
|
||||
task.addData(key, addData[key]);
|
||||
}
|
||||
task.start();
|
||||
})
|
||||
}
|
||||
|
||||
export const aesEncrypt = (value) => {
|
||||
const e = new JSEncrypt()
|
||||
e.setPublicKey(PUBLIC_KEY);
|
||||
const s = e.encrypt(value)
|
||||
return s
|
||||
}
|
||||
|
||||
// rgb 转 16
|
||||
export function colorRGBtoHex(color) {
|
||||
var rgb = color.split(',');
|
||||
var r = parseInt(rgb[0].split('(')[1]);
|
||||
var g = parseInt(rgb[1]);
|
||||
var b = parseInt(rgb[2].split(')')[0]);
|
||||
var hex = "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
|
||||
return hex;
|
||||
}
|
||||
84
uni_modules/mumu-h5office/package.json
Normal file
84
uni_modules/mumu-h5office/package.json
Normal file
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"id": "mumu-h5office",
|
||||
"displayName": "h5office。预览office文件,预览文档,打开PDF WORD PPT EXCEL 文件",
|
||||
"version": "1.0.1",
|
||||
"description": "h5office是兼容 `浏览器端(h5)` `iOS app端` `Android app端` 的文档预览工具。支持权限配置 `下载` `拷贝文字` `打印`",
|
||||
"keywords": [
|
||||
"excel",
|
||||
"PDF",
|
||||
"PDF预览",
|
||||
"文档预览"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "u"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "n"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "n",
|
||||
"阿里": "n",
|
||||
"百度": "n",
|
||||
"字节跳动": "n",
|
||||
"QQ": "n",
|
||||
"钉钉": "n",
|
||||
"快手": "n",
|
||||
"飞书": "n",
|
||||
"京东": "n"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "n",
|
||||
"联盟": "n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
94
uni_modules/mumu-h5office/readme.md
Normal file
94
uni_modules/mumu-h5office/readme.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# mumu-h5office
|
||||
|
||||
## 说明
|
||||
|
||||
h5office是兼容 `浏览器端(h5)` `iOS app端` `Android app端` 的文档预览工具。支持权限配置 `下载` `拷贝文字` `打印`。支持app端本地文件预览,网络文件预览。手机端支持触屏操作双指放大缩小,pc端UI美观好看
|
||||
|
||||
### 必读
|
||||
|
||||
服务器资源有限,每个appid都会有次数限制,
|
||||
|
||||
使用次数可以在小程序中进行刷新,刷新次数是没有限制的(需观看广告)
|
||||
|
||||
小程序中可以设置次数不足邮件提醒,当次数低于设置的数量时会通过邮件进行提示
|
||||
|
||||
当前插件的后端服务是共用一台 2核心、4G内存、30M带宽 服务器
|
||||
|
||||
可能在高峰期的时候文件预览速度会变慢。
|
||||
|
||||
如果对预览文件速度、预览次数有大量的需求,或者大文件预览。请联系开发者部署私有化的版本。
|
||||
|
||||
#### 本地文件预览功能说明
|
||||
|
||||
本地文件预览的本质,其实是先把文件上传到服务器,再通过服务器进行解析。
|
||||
|
||||
如果对文件隐私有需求,只有选择服务器端的服务进行私有部署。
|
||||
|
||||
[私有部署说明](https://h5office.cn/price)
|
||||
|
||||
### Appid 申请方法
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
## 简单使用
|
||||
|
||||
**插件已支持 uni_modules 支持组件easycom,以下代码演示的是普通使用**
|
||||
|
||||
```html
|
||||
<!-- HTML -->
|
||||
<mumu-h5office v-model="isShow" :file="inputFile" appid="你申请的Appid"></mumu-h5office>
|
||||
<button @click="openFile">打开网络文件</button>
|
||||
```
|
||||
|
||||
```javascript
|
||||
// script
|
||||
import mumuH5office
|
||||
from "@/uni_modules/mumu-h5office/components/mumu-h5office/mumu-h5office.vue"
|
||||
export default {
|
||||
components: { mumuH5office },
|
||||
data() {
|
||||
inputFile: '',
|
||||
isShow: false,
|
||||
},
|
||||
methods: {
|
||||
openFile() {
|
||||
this.inputFile = "https://h5plugin.mumudev.top/public/previewOffce/333.docx"
|
||||
this.isShow = true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## [官方文档:https://h5office.cn](https://h5office.cn)
|
||||
|
||||
## 预览
|
||||
|
||||
[浏览器中直接打开:https://h5plugin.mumudev.top/#/pages/h5office/h5office](https://h5plugin.mumudev.top/#/pages/h5office/h5office)
|
||||
|
||||
|
||||
|
||||
扫码预览:
|
||||
|
||||

|
||||
|
||||
下载完整演示代码、安卓app:
|
||||
|
||||
[官网下载页面:https://h5office.cn/uni-app/%E5%AE%89%E8%A3%85](https://h5office.cn/uni-app/%E5%AE%89%E8%A3%85)
|
||||
|
||||
|
||||
|
||||
## 属性、事件、其他组件
|
||||
|
||||
请前往官网进行查看:
|
||||
|
||||
[属性和事件文档说明:https://h5office.cn/uni-app/%E5%B1%9E%E6%80%A7%E5%92%8C%E4%BA%8B%E4%BB%B6](https://h5office.cn/uni-app/%E5%B1%9E%E6%80%A7%E5%92%8C%E4%BA%8B%E4%BB%B6)
|
||||
|
||||
|
||||
|
||||
## 支持作者
|
||||
|
||||

|
||||
@@ -70,7 +70,9 @@ function checkStorageSpace() {
|
||||
|
||||
function checkUpdate(forceCheck = false) {
|
||||
const localVersion = plus.runtime.version;
|
||||
|
||||
const localWgtVersion = uni.getStorageSync('wgtVersion') || localVersion;
|
||||
console.log(plus.runtime.version, localWgtVersion)
|
||||
uni.request({
|
||||
url: 'http://49.232.154.205:10900/fadapp-update/version.json?t=' + Date.now(),
|
||||
success: (res) => {
|
||||
|
||||
10
version.md
10
version.md
@@ -1,3 +1,8 @@
|
||||
版本记录规则:
|
||||
第一个数字表示基座版本,如果第一个数字不同代表基座变更,必须重新安装
|
||||
第二个数字表示版本大更新,用于一次更新包含了大量的更改
|
||||
第三个数字表示小更新,用于一些较小的调整
|
||||
|
||||
## 4.5.1
|
||||
+ 开始记录版本
|
||||
+ 增加版本不兼容时可以从浏览器下载安装包的功能
|
||||
@@ -53,3 +58,8 @@
|
||||
|
||||
## 5.0.0
|
||||
+ 修改页面启动图
|
||||
|
||||
## 5.1.0
|
||||
+ 增加项目明细页面
|
||||
+ 增加客户管理页面
|
||||
+ 下个版本需要增加更多页面
|
||||
Reference in New Issue
Block a user