Commit 573947d5 by guomingpang

Merge branch 'dev' of…

Merge branch 'dev' of ssh://xmgit.ixm5.cn:10022/xiaomai-cloud-class/xiaomai-cloud-class-web into dev
parents b77bf3a8 016eaed3
......@@ -154,7 +154,7 @@ class ChooseMembersModal extends React.Component {
let rightsList = []; // 保存新加进去的成员
selectUserList.map((item) => {
rightsList.push({
rights: "LOOK_DOWNLOAD",
rights: "LOOK",
userId: item.userId
})
return rightsList
......
......@@ -19,7 +19,7 @@ class ManagingMembersModal extends React.Component {
addManagingMember: false, // 是否点击了添加成员
storeId :User.getStoreId() , // 学院Id
iconRotateList: [],
userAuthority : ['可编辑', '可查看/下载', '仅可查看', '', '创建者', '学院管理员'] , // 空 代表删除
userAuthority : ['可编辑', '可下载', '可查看', '', '创建者', '学院管理员'] , // 空 代表删除
}
}
componentDidMount() {
......@@ -64,7 +64,7 @@ class ManagingMembersModal extends React.Component {
// 修改成员权限
updateFileUserAuthority = (params, newRights = 1) => {
const rightList = ['EDIT', 'LOOK_DOWNLOAD', ''];
const rightList = ['EDIT', 'LOOK_DOWNLOAD', 'LOOK'];
let { iconRotateList } = this.state;
let _params = params;
_params.rights = rightList[newRights];
......@@ -173,10 +173,10 @@ class ManagingMembersModal extends React.Component {
<span className='menu-bottom'>下载、复制</span>
</div>
</Menu.Item>
{/* <Menu.Item key="LOOK" >
<div onClick={() => this.updateFileUserAuthority(params, 2)}>仅可查看</div>
<span className='menu-bottom'>{userAuthority[2]}</span>
</Menu.Item> */}
<Menu.Item key="LOOK" >
<div onClick={() => this.updateFileUserAuthority(params, 2)}>{userAuthority[2]}</div>
<span className='menu-bottom'>查看</span>
</Menu.Item>
<Menu.Divider key='LINE'/>
<Menu.Item key="REMOVE" >
<div className='remove' onClick={() => this.removeUser(params, userAuthority[3])}>移除</div>
......@@ -247,6 +247,8 @@ class ManagingMembersModal extends React.Component {
num = 1;
} else if (record.rights === "EDIT") {
num = 0;
}else if(record.rights=="LOOK"){
num = 2;
}
}
return (
......
/*
* @Author: wufan
* @Date: 2021-05-11 10:21:37
* @LastEditors: wufan
* @LastEditTime: 2021-06-02 16:51:26
* @LastEditors: yuananting
* @LastEditTime: 2021-06-09 14:16:08
* @Description: 企业微信api
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
import User from "@/common/js/user";
import Service from "@/common/js/service";
import Platform from "@/core/platform";
export default class WechatApi {
static async initConfig(params = { isAgentConfig: false, url: "" }) {
......@@ -29,6 +30,7 @@ export default class WechatApi {
"shareToExternalContact",
"selectExternalContact",
"selectEnterpriseContact",
'startRecord',
],
});
......@@ -129,4 +131,10 @@ export default class WechatApi {
});
});
}
static startRecord() {
if (Platform.isWorkWx()) {
wx.startRecord();
}
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -22,13 +22,15 @@ import UploadProgressModal from '@/bu-components/UploadProgressModal';
import SelectPrepareFileModal from '@/bu-components/SelectPrepareFileModal';
import CopyFileModal from '@/bu-components/CopyFileModal';
import ManagingMembersModal from '@/bu-components/ManagingMembersModal';
import PreviewFileModal from '../modal/PreviewFileModal'
import ScanFileModal from '../modal/ScanFileModal';
import CreateFolderModal from '../modal/CreateFolderModal';
import User from '@/common/js/user';
import axios from 'axios';
const appId = "yozoqvpO2Hvz8346";
const DEL_FOLDER_URL_MAP = {
'MYSELF': 'public/hadesStore/delFolder',
'COMMON': 'public/hadesStore/delFolder'
......@@ -53,7 +55,10 @@ class FolderList extends React.Component {
showCopyFileModal: false, // 复制文件弹窗
showManagingModal: false, // 管理文件查看编辑权限
nonCompliantFileList: [], // 不符合上限的文件列表
parentRights: '' // 继承父级文件夹权限
parentRights: '', // 继承父级文件夹权限
showPreviewModal:false, //是否显示loading
previewing:false, //是否正在预览
previewStatus:'UPLOAD' //预览文件的生成状态
}
}
......@@ -96,10 +101,122 @@ class FolderList extends React.Component {
break;
}
}
handleYZPreviewDataDot =(folderFormat) => {
switch (folderFormat) {
case 'PDF':
window.WEBTRACING('resource_disk_yz_file_preview_pdf', '资料云盘_点击永中预览_pdf');
break;
case 'WORD':
case 'DOCX':
case 'DOC':
window.WEBTRACING('resource_disk_yz_file_preview_word', '资料云盘_点击永中预览_word');
break;
case 'EXCEL':
window.WEBTRACING('resource_disk_yz_file_preview_excel', '资料云盘_点击永中预览_excel');
break;
case 'PPT':
case 'PPTX':
window.WEBTRACING('resource_disk_yz_file_preview_ppt', '资料云盘_点击永中预览_ppt');
break;
default:
break;
}
}
getYoZoSign = (data,type)=>{
return new Promise((resolve) => {
let uploadParams;
if(type==="UPLOAD"){
uploadParams ={
fileUrl:data,
instId:window.currentUserInstInfo.instId,
yoZoTypeEnum:'UPLOAD'
}
}else{
uploadParams ={
fileVersionId:data,
instId:window.currentUserInstInfo.instId,
yoZoTypeEnum:'VIEW'
}
}
Service.Apollo('public/apollo/getYoZoSign', uploadParams).then(res => {
const { result = [] } = res;
resolve(result)
});
})
}
saveYoZoFileVersionId = (fileVersionId,folderId)=>{
const params ={
fileVersionId,
folderId,
instId: window.currentUserInstInfo.instId,
}
Service.Apollo('public/apollo/saveYoZoFileVersionId', params).then(res => {
});
}
// 预览文件
handleScanFile = (folder) => {
const { folderFormat, folderSize, ossUrl } = folder;
handleScanFile = async (folder) => {
const { folderFormat, folderSize, ossUrl,rights,fileVersionId,id} = folder;
const {currentRootDisk } = this.props;
//如果是公共文件且只有查看的权限的用户的预览对接的三方是永中
const that = this;
if(currentRootDisk.disk==="COMMON" && rights==="LOOK"){
switch (folderFormat) {
case 'PDF':
case 'WORD':
case 'DOCX':
case 'DOC':
case 'EXCEL':
case 'PPT':
case 'PPTX':
that.handleYZPreviewDataDot(folderFormat);
if(!fileVersionId){
this.setState({
previewing:true,
showPreviewModal:true,
previewStatus:'UPLOAD'
},async ()=>{
const uploadSign = await that.getYoZoSign(ossUrl,"UPLOAD");
axios.post(`https://dmc.yozocloud.cn/api/file/http?fileUrl=${ossUrl}&appId=${appId}&sign=${uploadSign}`)
.then(async function (response){
that.saveYoZoFileVersionId(response.data.data.fileVersionId,id);
const { previewing } = that.state;
if(previewing){
const previewSign = await that.getYoZoSign(response.data.data.fileVersionId,"VIEW");
const url = `https://eic.yozocloud.cn/api/view/file?fileVersionId=${response.data.data.fileVersionId}&appId=${appId}&sign=${previewSign}`
that.setState({
previewStatus:'UPLOAD_SUCCESS',
url
})
}
})
})
}else{
const previewSign = await that.getYoZoSign(fileVersionId,"VIEW");
const url = `http://eic.yozocloud.cn/api/view/file?fileVersionId=${fileVersionId}&appId=${appId}&sign=${previewSign}`
const a = document.createElement('a');
document.body.appendChild(a);
a.setAttribute('href', url);
a.setAttribute('target', '_blank');
a.click();
document.body.removeChild(a)
}
break;
default:
const scanFileModal = (
<ScanFileModal
fileType={folderFormat}
item={folder}
close={() => {
this.setState({ scanFileModal: null });
}}
/>
);
this.setState({ scanFileModal });
break;
}
}else{
switch (folderFormat) {
case 'PDF':
window.open(ossUrl, "_blank");
......@@ -127,20 +244,20 @@ class FolderList extends React.Component {
});
break;
}
if (folderFormat === 'EXCEL') {
Modal.confirm({
title: '抱歉,不能在线预览',
content: ' 该文件类型不支持在线预览,请下载后再查看',
// icon: <Icon type="question-circle" theme="filled" style={{ color: '#FF8534' }}></Icon>,
okText: "下载",
onOk: () => {
const a = document.createElement('a');
a.href = ossUrl;
a.click();
}
});
break;
}
// if (folderFormat === 'EXCEL') {
// Modal.confirm({
// title: '抱歉,不能在线预览',
// content: ' 该文件类型不支持在线预览,请下载后再查看',
// // icon: <Icon type="question-circle" theme="filled" style={{ color: '#FF8534' }}></Icon>,
// okText: "下载",
// onOk: () => {
// const a = document.createElement('a');
// a.href = ossUrl;
// a.click();
// }
// });
// break;
// }
const prefixUrl = "https://view.officeapps.live.com/op/view.aspx?src=";
const scanUrl = `${prefixUrl}${encodeURIComponent(ossUrl)}`
window.open(scanUrl, "_blank");
......@@ -156,11 +273,19 @@ class FolderList extends React.Component {
this.setState({ scanFileModal });
break;
}
}
// 预览文件埋点
this.handleDataDot(folderFormat);
}
cancelPreview = ()=>{
const rightDom = document.querySelector('.right-container');
rightDom.style.zIndex = 1;
this.setState({
previewing:false,
showPreviewModal:false,
previewStatus:'UPLOAD'
})
}
// 选择文件夹
handleSelectFolder = (folder) => {
const { folderPathList, showResultPage, currentRootDisk } = this.props;
......@@ -647,7 +772,8 @@ class FolderList extends React.Component {
const {
currentFolder, currentFile, renameModalData, showSelectFileModal,
showUploadModal, localFileList, showCopyFileModal, showManagingModal
showUploadModal, localFileList, showCopyFileModal, showManagingModal,
showPreviewModal, previewStatus,url
} = this.state;
const {
selectedFileIds, folderList, showResultPage,
......@@ -790,7 +916,9 @@ class FolderList extends React.Component {
}}
/>
}
{ showPreviewModal &&
<PreviewFileModal onCancel={()=>this.cancelPreview()} previewStatus={previewStatus} url={url}/>
}
{ this.state.scanFileModal }
{ this.state.chargeModal }
</div>
......
import React from 'react';
import { Modal} from 'antd';
import "./PreviewFileModal.less";
class PreviewFileModal extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
cancelPreView = ()=>{
this.props.onCancel();
}
toPreView = (url)=>{
const a = document.createElement('a');
document.body.appendChild(a);
a.setAttribute('href', url);
a.setAttribute('target', '_blank');
a.click();
document.body.removeChild(a);
this.props.onCancel();
}
render() {
const { previewStatus,url} = this.props
return (
<div className="preview-modal">
<div className="preview-modal-content">
<div className="load-img-box">
{previewStatus === "UPLOAD" &&
<img className="load-img" src="https://image.xiaomaiketang.com/xm/3j32ashQst.png"></img>
}
{previewStatus === "UPLOAD_SUCCESS" &&
<img className="load-img" src="https://image.xiaomaiketang.com/xm/jJRK3bTEdc.png"></img>
}
</div>
<div className="load-text-box">
{previewStatus === "UPLOAD" &&
<div className="load-text-box-title">预览生成中</div>
}
{previewStatus === "UPLOAD_SUCCESS" &&
<div className="load-text-box-title">预览生成成功</div>
}
</div>
<div className="operate">
<span className="btn cancel-preview-btn" onClick={()=>this.cancelPreView()}>取消预览</span>
{previewStatus === "UPLOAD" &&
<span className="btn to-preview-btn__disabled to-preview-btn">去查看</span>
}
{previewStatus === "UPLOAD_SUCCESS" &&
<span className="btn to-preview-btn" onClick={()=>this.toPreView(url)}>去查看</span>
}
</div>
</div>
</div>
);
}
}
export default PreviewFileModal;
.preview-modal{
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 102;
height: 100%;
background: rgba(0, 0, 0, 0.7);
.preview-modal-content{
position:absolute;
left:calc(50% - 133px);
top:calc(50% - 87px);
color:#FFF;
text-align:center;
width:266px;
height:174px;
.load-img-box{
.load-img{
width:44px;
height:44px;
}
}
.load-text-box{
margin-top:23px;
font-size:16px;
color:#FFF;
.load-text-box-title{
margin-bottom:8px;
}
}
.operate{
margin-top:24px;
.btn {
padding:5px 12px;
border:1px solid #E8E8E8;
border-radius:2px;
}
.cancel-preview-btn{
margin-right:8px;
}
.to-preview-btn__disabled{
border:1px solid #E8E8E8;
opacity: 0.4;
}
}
}
}
\ No newline at end of file
......@@ -2,7 +2,7 @@
* @Author: 吴文洁
* @Date: 2020-03-18 10:01:28
* @LastEditors: yuananting
* @LastEditTime: 2021-03-27 14:44:31
* @LastEditTime: 2021-06-09 14:20:59
* @Description: 录音组件
*/
......@@ -12,6 +12,8 @@ import { Button, Modal } from "antd";
import UploadOss from "@/core/upload";
import { RECORD_ERROR } from "@/common/constants/academic";
import AudioRecorder from "../components/audioRecord";
import Platform from '@/core/platform';
import WechatApi from "@/common/js/wechatApi";
import "./XMRecord.less";
......@@ -84,6 +86,9 @@ class XMRecord extends Component {
};
handleStartRecord = () => {
if(Platform.isWorkWx()) { // 企业微信
WechatApi.startRecord();
} else {
navigator.mediaDevices
.getUserMedia({
audio: true,
......@@ -93,6 +98,7 @@ class XMRecord extends Component {
this.mMediaRecorder.start();
this.handleCountTime();
}, this.openDeviceFailure);
}
};
onProcessData = (audioData) => {
......
......@@ -2,7 +2,7 @@
* @Author: yuananting
* @Date: 2021-03-27 16:15:13
* @LastEditors: yuananting
* @LastEditTime: 2021-06-08 10:44:42
* @LastEditTime: 2021-06-09 12:03:58
* @Description: 助学工具-新建/复制/编辑试卷
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -73,7 +73,7 @@ class OperatePaper extends Component {
},
selectQuestionModal: null,
paperPreviewModal: null,
quickSortModalVisible: false,
quickSortModalVisible: false, // 快捷排序弹窗显隐
selectQuestionList: [],
currentOperate: "",
currentNav: "",
......@@ -736,6 +736,52 @@ class OperatePaper extends Component {
totalScore,
} = formData;
const { match } = this.props;
const selectQuestionList = [...this.state.selectQuestionList];
const questionTypeEnum = {
SINGLE_CHOICE: "【单选题】",
MULTI_CHOICE: "【多选题】",
JUDGE: "【判断题】",
GAP_FILLING: "【填空题】",
INDEFINITE_CHOICE: "【不定项选择题】",
};
const typeColumns = [
{
title: "题型",
dataIndex: "typeKey",
key: "typeKey",
render: (text, record, index) => <span style={{color: '#333333'}}>{questionTypeEnum[text]}</span>,
},
{
title: "操作",
key: "action",
align: 'right',
render: (text, record, index) => (
<Space size="middle">
<span
style={{color: index > 0 ? '#2966FF' : '#CCCCCC', cursor: 'pointer'}}
onClick={() => {
index > 0 && this.handleMoveTypeSorter(index, -1);
}}
>
上移
</span>
<span style={{color: '#BFBFBF'}}> | </span>
<span
style={{color: index < 4 ? '#2966FF' : '#CCCCCC', cursor: 'pointer'}}
onClick={() => {
index < 4 && this.handleMoveTypeSorter(index, 1);
}}
>
下移
</span>
</Space>
),
},
];
return (
<div>
<div className="page operate-paper-page">
......
......@@ -8,6 +8,7 @@
*/
import React, { Component } from "react";
import { Modal, ConfigProvider, Empty } from "antd";
import Lottie from 'react-lottie';
import User from "@/common/js/user";
import AidToolService from "@/domains/aid-tool-domain/AidToolService";
import "./PreviewPaperModal.less";
......@@ -15,6 +16,7 @@ import ScanFileModal from "@/modules/resource-disk/modal/ScanFileModal";
import _ from "underscore";
import XMAudio from "../../components/XMAudio";
import { NUM_TO_WORD_MAP } from "@/common/constants/punchClock/punchClock";
import previewEmpty from '../../../lottie/previewEmpty/data.json';
const questionTypeList = {
SINGLE_CHOICE: "单选题",
MULTI_CHOICE: "多选题",
......@@ -254,9 +256,25 @@ class PreviewPaperModal extends Component {
// 自定义空状态
customizeRenderEmpty = () => {
const defaultOptions = {
loop: true,
autoplay: true,
animationData: previewEmpty,
rendererSettings: {
preserveAspectRatio: 'xMidYMid slice'
}
}
return (
<Empty
image="https://image.xiaomaiketang.com/xm/emptyTable.png"
image={<div style={{ marginTop: 24 }}>
<Lottie
options={defaultOptions}
height={150}
width={150}
isStopped={false}
isPaused={false}
/>
</div>}
imageStyle={{
height: 100,
}}
......
......@@ -2,7 +2,7 @@
* @Author: yuananting
* @Date: 2021-02-25 14:34:29
* @LastEditors: yuananting
* @LastEditTime: 2021-06-04 17:09:25
* @LastEditTime: 2021-06-09 12:02:55
* @Description: 助学工具-题库-操作题目Tab
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/
......@@ -67,9 +67,15 @@ class OperateQuestionTab extends Component {
componentDidMount() {
const { questionTypeKey } = this.props;
const isEditCurrent = getParameterByName("id") && getParameterByName("type") === questionTypeKey;
const isEditCurrent =
getParameterByName("id") &&
getParameterByName("type") === questionTypeKey;
const optionSize = isEditCurrent ? 20 : 4;
if (["INDEFINITE_CHOICE", "MULTI_CHOICE", "SINGLE_CHOICE"].includes(questionTypeKey)) {
if (
["INDEFINITE_CHOICE", "MULTI_CHOICE", "SINGLE_CHOICE"].includes(
questionTypeKey
)
) {
// 选择题(单选 多选 不定项)-插入4条默认选项
for (var i = 0; i < optionSize; i++) {
this.handleAddOption();
......@@ -630,7 +636,7 @@ class OperateQuestionTab extends Component {
this.state.stemContent,
(contentItem) => contentItem.type === "RICH_TEXT"
);
if(stemContent.textLength > 1000) {
if (stemContent.textLength > 1000) {
validateError++;
}
let stem = stemContent.content.replace(/<[^>]+>/g, "");
......@@ -690,7 +696,7 @@ class OperateQuestionTab extends Component {
optionUnChecked = item.isCorrectAnswer
? optionUnChecked
: optionUnChecked + 1;
if(optionContent[0].textLength > 1000) {
if (optionContent[0].textLength > 1000) {
validateError++;
}
let optionInput = optionContent[0].content.replace(/<[^>]+>/g, "");
......@@ -1036,11 +1042,11 @@ class OperateQuestionTab extends Component {
return dom ? (
<div
className="question-item_question-content"
style={{
display: ["PICTURE", "VIDEO"].includes(type)
? "inline-grid"
: "flex",
}}
style={
!["PICTURE", "VIDEO"].includes(type)
? { display: "flex" }
: { float: "left" }
}
key={index}
>
{dom}
......@@ -1190,10 +1196,8 @@ class OperateQuestionTab extends Component {
data-label="正确答案"
>
{_.map(chooseOptions, (optionItem, optionIndex) => {
const {
questionOptionContentList,
isCorrectAnswer,
} = optionItem;
const { questionOptionContentList, isCorrectAnswer } =
optionItem;
optionItem.optionSort = optionIndex;
const mediaBtn = ["VOICE", "AUDIO", "PICTURE"];
const placeHold =
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment