| | |
| | | <template> |
| | | <div> |
| | | 电子说明书 |
| | | <a-card> |
| | | {{answer}} |
| | | </a-card> |
| | | <a-input-search placeholder="input search text" enter-button @search="onSearch"/> |
| | | <div class="page-container"> |
| | | <!--电子说明书--> |
| | | <div class="outer-container"> |
| | | <!--左侧阅读模式缩略图区域--> |
| | | <div class="left-spin-container"> |
| | | <a-spin :spinning="thumbnailSpinning" :delay="spinningDelayTime"> |
| | | <a-icon slot="indicator" type="loading" spin/> |
| | | </a-spin> |
| | | |
| | | <div class="left-container"> |
| | | <div v-for="item in imgListConfig.records" :key="item.id" class="single-thumbnail-container" |
| | | :class="[item.id===activeImageId?'single-thumbnail-active':'']" :id="'thumbnail-container-'+item.id" |
| | | @click="activeCurrentThumbnail(item.id)"> |
| | | <!--<img src="@/assets/page/electronicManual/document.png">--> |
| | | <div class="thumbnail-image-container"> |
| | | <a-skeleton :loading="item.loading" :avatar="{shape:'square'}" :title="false" :paragraph="false" active/> |
| | | <img :id="'thumbnail-image-'+item.id" :data-src="getImgView(item.imgPath+item.imgEncodeName)" |
| | | @load="imageLoadDone(item)" :style="{opacity:item.loading?0:1}"> |
| | | </div> |
| | | <div>-{{item.pageNumber}}-</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!--右侧区域--> |
| | | <div class="right-container"> |
| | | <div class="right-top-container"> |
| | | <div class="document-spin-container"> |
| | | <a-spin :spinning="documentSpinning" :delay="spinningDelayTime"> |
| | | <a-icon slot="indicator" type="loading" spin/> |
| | | </a-spin> |
| | | |
| | | <!--右上文档区域--> |
| | | <div class="document-container" @wheel="horizontalScroll"> |
| | | <div v-for="item in documentList" :key="item.id" class="single-document-container" |
| | | @click="activeCurrentDocument(item.id)" |
| | | :class="[item.id===activeDocumentId?'single-document-active':'']"> |
| | | <div><img src="@/assets/page/electronicManual/document.png"></div> |
| | | <div class="single-document-name"> |
| | | {{item.fileName?item.fileName.length>20?item.fileName.slice(0,20)+'..':item.fileName:'未命名说明书'}} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!--右上输入查询区域--> |
| | | <div class="search-container"> |
| | | <div>您当前选择的电控系统为:xxx-xxxx-xxxxx 机床型号为:xxx-xx</div> |
| | | <div class="input-container"> |
| | | <input @keydown.enter="furtherFilter" placeholder="请用一句话描述您当前遇到的问题" v-model="inputQuestion"/> |
| | | <img src="@/assets/page/electronicManual/search.png" @click="furtherFilter" |
| | | :style="{cursor:!thumbnailSpinning?'pointer':'not-allowed'}"> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!--右下区域--> |
| | | <div class="right-bottom-spin-container"> |
| | | <a-spin :spinning="largeImageSpinning" :delay="spinningDelayTime"> |
| | | <a-icon slot="indicator" type="loading" spin/> |
| | | </a-spin> |
| | | |
| | | <!--右下阅读模式区域--> |
| | | <div class="right-bottom-container" :class="[isFurtherFilter?'further-filter-container':'']"> |
| | | <template v-if="!isFurtherFilter"> |
| | | <div v-for="item in imgListConfig.records" :key="item.id" class="single-largeImg-container" |
| | | :id="'large-image-container-'+item.id"> |
| | | <a-skeleton :loading="item.loading" :avatar="{shape:'square'}" :title="false" |
| | | :paragraph="false" active/> |
| | | <img :id="'large-image-'+item.id" :data-src="getImgView(item.imgPath+item.imgEncodeName)" |
| | | @load="imageLoadDone(item)" :style="{opacity:item.loading?0:1}"> |
| | | <!--<img src="@/assets/page/electronicManual/document.png">--> |
| | | </div> |
| | | </template> |
| | | |
| | | <!--右下深层过滤区域--> |
| | | <template v-else> |
| | | <div v-for="item in furtherFilterImgList" :key="item.id" class="single-filterImg-container" |
| | | @click="locateToDocument(item)"> |
| | | <!--<img src="@/assets/page/electronicManual/document.png">--> |
| | | <a-skeleton :loading="item.loading" :avatar="{shape:'square'}" :title="false" |
| | | :paragraph="false" active/> |
| | | <img :id="'filter-image-'+item.id" :data-src="getImgView(item.imgPath+item.imgEncodeName)" |
| | | @load="imageLoadDone(item)" :style="{opacity:item.loading?0:1}" |
| | | > |
| | | </div> |
| | | <img src="@/assets/page/electronicManual/back.png" id="back-to-largeImg" @click="cancelFurtherFilter" |
| | | v-if="!largeImageSpinning"> |
| | | </template> |
| | | </div> |
| | | </div> |
| | | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { getDataAfterSearchByApi } from '@/api/AI' |
| | | import { getPdfImgApi, getPdfDocumentApi, getFurtherFilterImgApi } from '@/api/ai' |
| | | import { getFileAccessHttpUrl } from '@/api/manage' |
| | | import { message } from 'ant-design-vue' |
| | | |
| | | message.config({ |
| | | maxCount: 1, |
| | | duration: 2 |
| | | }) |
| | | |
| | | export default { |
| | | name: 'ElectronicManual', |
| | | components: {}, |
| | | data() { |
| | | return { |
| | | answer:'' |
| | | rightBottomContainer: null, |
| | | activeDocumentId: null, |
| | | activeImageId: null, |
| | | inputQuestion: '', |
| | | isFurtherFilter: false, |
| | | beforeFilterActiveDocumentId: null, |
| | | beforeFilterActiveImageId: null, |
| | | documentList: [], |
| | | // documentList: [ |
| | | // { |
| | | // id: 1, |
| | | // fileName: '机床手册1' |
| | | // }, |
| | | // { |
| | | // id: 2, |
| | | // fileName: '机床手册2' |
| | | // }, |
| | | // { |
| | | // id: 3, |
| | | // fileName: '机床手册3' |
| | | // }, |
| | | // { |
| | | // id: 4, |
| | | // fileName: '机床手册4' |
| | | // }, |
| | | // { |
| | | // id: 5, |
| | | // fileName: '机床手册5' |
| | | // }, |
| | | // { |
| | | // id: 6, |
| | | // fileName: '机床手册6' |
| | | // }, |
| | | // { |
| | | // id: 7, |
| | | // fileName: '机床手册7' |
| | | // }, |
| | | // { |
| | | // id: 8, |
| | | // fileName: '机床手册8' |
| | | // }, |
| | | // { |
| | | // id: 9, |
| | | // fileName: '机床手册9' |
| | | // }, |
| | | // { |
| | | // id: 10, |
| | | // fileName: '机床手册10' |
| | | // } |
| | | // ], |
| | | imgListParams: { |
| | | pageNo: 1, |
| | | pageSize: 20 |
| | | }, |
| | | imgListConfig: { |
| | | records: [] |
| | | }, |
| | | scrollToMarginConfig: { |
| | | hasScrollToTopCount: 0, |
| | | hasScrollToBottomCount: 0 |
| | | }, |
| | | thumbnailSpinning: false, |
| | | documentSpinning: false, |
| | | largeImageSpinning: false, |
| | | spinningDelayTime: 500, |
| | | furtherFilterImgListParams: {}, |
| | | furtherFilterImgList: [] |
| | | } |
| | | }, |
| | | created() { |
| | | this.getPdfDocumentByApi() |
| | | }, |
| | | mounted() { |
| | | this.leftContainer = document.querySelector('.left-container') |
| | | this.rightBottomContainer = document.querySelector('.right-bottom-container') |
| | | this.handleScrollEventSwitch(true) |
| | | }, |
| | | methods: { |
| | | onSearch() { |
| | | const param = { |
| | | 'id': '683a65fd-8feb-4446-ad32-714c4785f667', |
| | | 'messages': [ |
| | | { |
| | | 'role': 'user', |
| | | 'content': '给我讲个故事?' |
| | | /* 调用接口获取pdf文档 */ |
| | | getPdfDocumentByApi() { |
| | | this.documentSpinning = true |
| | | getPdfDocumentApi() |
| | | .then(res => { |
| | | if (res.success) { |
| | | this.documentList = res.result |
| | | this.documentSpinning = false |
| | | this.activeCurrentDocument(res.result[0].id) |
| | | } |
| | | ], |
| | | 'stream': false, |
| | | 'max_tokens': 500 |
| | | }) |
| | | }, |
| | | |
| | | /** |
| | | * 点击文档后触发 |
| | | * @param pdfFileId 文档Id |
| | | * @param furtherFilterImageId 深层过滤模式中点击的图片Id |
| | | */ |
| | | activeCurrentDocument(pdfFileId, furtherFilterImageId = null, furtherFilterImagePageNumber = null) { |
| | | if (pdfFileId === this.activeDocumentId && !furtherFilterImageId) return |
| | | if (this.isFurtherFilter) { |
| | | this.isFurtherFilter = false |
| | | this.handleScrollEventSwitch(true) |
| | | } |
| | | getDataAfterSearchByApi() |
| | | if (!furtherFilterImageId) this.scrollToTop() |
| | | this.imgListConfig = {} |
| | | this.activeDocumentId = pdfFileId |
| | | |
| | | this.imgListParams.pageNo = 1 |
| | | this.resetImgListScrollConfig() |
| | | if (furtherFilterImagePageNumber && furtherFilterImagePageNumber > this.imgListParams.pageSize) this.computeImgListPageNo(furtherFilterImagePageNumber) |
| | | |
| | | const params = Object.assign({ pdfFileId }, this.imgListParams) |
| | | this.thumbnailSpinning = true |
| | | this.largeImageSpinning = true |
| | | |
| | | getPdfImgApi(params) |
| | | .then(res => { |
| | | if (res.success) { |
| | | this.imgListConfig = res.result |
| | | this.imgListConfig.records = this.imgListConfig.records.map(item => { |
| | | return { |
| | | ...item, |
| | | loading: true |
| | | } |
| | | }) |
| | | this.activeImageId = res.result.records[0].id |
| | | this.$nextTick(() => { |
| | | this.lazyLoadImgByIntersectionObserver(res.result.records, 'thumbnail-image', 4, furtherFilterImageId) |
| | | this.lazyLoadImgByIntersectionObserver(res.result.records, 'large-image', 1, furtherFilterImageId) |
| | | }) |
| | | this.thumbnailSpinning = false |
| | | this.largeImageSpinning = false |
| | | // 如果点击的是深层过滤的图片则返回阅读模式并放大选中的图片 |
| | | if (furtherFilterImageId) this.$nextTick(() => this.activeCurrentThumbnail(furtherFilterImageId, true)) |
| | | } |
| | | }) |
| | | }, |
| | | |
| | | /** |
| | | * 点击缩略图后触发在右侧放大缩略图 |
| | | * @param id 缩略图Id |
| | | * @param isFromFurtherFilter 是否通过深层过滤模式触发 |
| | | */ |
| | | activeCurrentThumbnail(id, isFromFurtherFilter = false) { |
| | | if (id === this.activeImageId && !isFromFurtherFilter) return |
| | | this.activeImageId = id |
| | | if (isFromFurtherFilter) this.scrollToImagePosition('thumbnail-container', true, 'left', 0) |
| | | this.scrollToImagePosition() |
| | | }, |
| | | |
| | | computeImgListPageNo(furtherFilterImagePageNumber) { |
| | | const integer = Math.floor(furtherFilterImagePageNumber / this.imgListParams.pageSize) |
| | | const remainder = furtherFilterImagePageNumber % this.imgListParams.pageSize |
| | | if (remainder !== 0) { |
| | | // 不为整数 |
| | | this.imgListParams.pageNo = integer + 1 |
| | | } else { |
| | | // 为整数 |
| | | this.imgListParams.pageNo = integer |
| | | } |
| | | }, |
| | | |
| | | /* 阅读模式下的滚动触顶底刷新 */ |
| | | lazyLoadData(event) { |
| | | if (this.thumbnailSpinning && this.largeImageSpinning) return // 加载中时取消调用 |
| | | const containerScrollTop = event.target.scrollTop |
| | | const containerClientHeight = event.target.clientHeight |
| | | const containerScrollHeight = event.target.scrollHeight |
| | | |
| | | if (containerScrollTop + containerClientHeight >= containerScrollHeight) { |
| | | console.log('触底') |
| | | this.scrollToMarginConfig.hasScrollToBottomCount++ |
| | | const params = Object.assign({ pdfFileId: this.activeDocumentId }, this.imgListParams) |
| | | params.pageNo = params.pageNo + this.scrollToMarginConfig.hasScrollToBottomCount |
| | | this.thumbnailSpinning = true |
| | | this.largeImageSpinning = true |
| | | getPdfImgApi(params) |
| | | .then(res => { |
| | | if (res.success) { |
| | | const newImgList = res.result.records.map(item => { |
| | | return { |
| | | ...item, |
| | | loading: true |
| | | } |
| | | }) |
| | | this.imgListConfig.records.push(...newImgList) |
| | | this.$nextTick(() => { |
| | | this.lazyLoadImgByIntersectionObserver(newImgList, 'thumbnail-image', 4) |
| | | this.lazyLoadImgByIntersectionObserver(newImgList, 'large-image', 1) |
| | | }) |
| | | this.thumbnailSpinning = false |
| | | this.largeImageSpinning = false |
| | | } |
| | | }) |
| | | } else if (containerScrollTop <= 0 && this.imgListConfig.records[0].pageNumber !== 1) { |
| | | console.log('触顶') |
| | | this.scrollToMarginConfig.hasScrollToTopCount++ |
| | | const params = Object.assign({ pdfFileId: this.activeDocumentId }, this.imgListParams) |
| | | params.pageNo = params.pageNo - this.scrollToMarginConfig.hasScrollToTopCount |
| | | this.thumbnailSpinning = true |
| | | this.largeImageSpinning = true |
| | | getPdfImgApi(params) |
| | | .then(res => { |
| | | if (res.success) { |
| | | const newImgList = res.result.records.map(item => { |
| | | return { |
| | | ...item, |
| | | loading: true |
| | | } |
| | | }) |
| | | this.imgListConfig.records.unshift(...newImgList) |
| | | this.$nextTick(() => { |
| | | this.lazyLoadImgByIntersectionObserver(newImgList, 'thumbnail-image', 4) |
| | | this.lazyLoadImgByIntersectionObserver(newImgList, 'large-image', 1) |
| | | }) |
| | | event.target.scrollTo({ top: 1 }) // 解决触顶刷新数据后滚动条至最顶部问题,但不知道为什么 |
| | | this.thumbnailSpinning = false |
| | | this.largeImageSpinning = false |
| | | } |
| | | }) |
| | | } |
| | | }, |
| | | |
| | | /* 开启深层过滤模式 */ |
| | | furtherFilter() { |
| | | if (this.thumbnailSpinning) return |
| | | if (!this.inputQuestion) { |
| | | this.$message.error('你没有输入内容哦') |
| | | return |
| | | } |
| | | |
| | | this.furtherFilterImgList = [] |
| | | this.isFurtherFilter = true |
| | | |
| | | // 开启深层过滤时取消文件选中并移除滚动刷新事件 |
| | | this.beforeFilterActiveDocumentId = this.activeDocumentId |
| | | this.activeDocumentId = null |
| | | this.imgListConfig = {} |
| | | this.handleScrollEventSwitch(false) |
| | | |
| | | const params = Object.assign({}, this.furtherFilterImgListParams) |
| | | params.pdfFileId = '1823231131943862273' |
| | | params.pdfContent = this.inputQuestion |
| | | this.largeImageSpinning = true |
| | | |
| | | getFurtherFilterImgApi(params) |
| | | .then(res => { |
| | | console.log('res', res) |
| | | this.answer = res.result |
| | | if (res.success) { |
| | | this.furtherFilterImgList = res.result.map(item => { |
| | | return { |
| | | ...item, |
| | | loading: true |
| | | } |
| | | }) |
| | | this.largeImageSpinning = false |
| | | this.$nextTick(() => this.lazyLoadImgByIntersectionObserver(res.result, 'filter-image', 2)) |
| | | } |
| | | }) |
| | | }, |
| | | |
| | | /* 点击深层过滤中的图片后定位至文件 */ |
| | | locateToDocument(record) { |
| | | this.isFurtherFilter = false |
| | | this.handleScrollEventSwitch(true) |
| | | this.$nextTick(() => this.activeCurrentDocument(record.fileId, record.id, record.pageNumber)) |
| | | }, |
| | | |
| | | /* 点击返回按钮退出深层过滤模式 */ |
| | | cancelFurtherFilter() { |
| | | const beforeFilterActiveRecord = { fileId: this.beforeFilterActiveDocumentId, id: this.activeImageId } |
| | | this.locateToDocument(beforeFilterActiveRecord) |
| | | this.inputQuestion = '' |
| | | }, |
| | | |
| | | /** |
| | | * 滚动至图片相应位置顶部 |
| | | * @param activePreId 滚动至某元素的Id前缀 |
| | | * @param isParentNodeOpenPosition 父元素是否开启定位 |
| | | * @param parentNodePreClass 父元素类名前缀 |
| | | * @param marginValue 边距值 正值为top,负值为bottom |
| | | */ |
| | | scrollToImagePosition(activePreId = 'large-image-container', isParentNodeOpenPosition = true, parentNodePreClass = 'rightBottom', marginValue = 25) { |
| | | console.log(activePreId + '-' + this.activeImageId) |
| | | const activeLargeImageContainer = document.getElementById(activePreId + '-' + this.activeImageId) |
| | | console.log('activeLargeImageContainer', activeLargeImageContainer) |
| | | let scrollTop |
| | | if (isParentNodeOpenPosition) { |
| | | console.log('父元素开启定位') |
| | | scrollTop = activeLargeImageContainer.offsetTop - marginValue |
| | | } else { |
| | | console.log('父元素未开启定位') |
| | | scrollTop = activeLargeImageContainer.offsetTop - this[parentNodePreClass + 'Container'].offsetTop - marginValue |
| | | } |
| | | |
| | | this[parentNodePreClass + 'Container'].scrollTo({ top: scrollTop }) |
| | | }, |
| | | |
| | | /** |
| | | * 采用浏览器监测者API实现图片懒加载 |
| | | * @param dataList 元素对应数据集合用来映射对应元素 |
| | | * @param targetPreClass 目标元素类名前缀 |
| | | * @param loadCount 加载数量 |
| | | * @param furtherFilterImageId 深层过滤模式中点击的图片Id |
| | | */ |
| | | lazyLoadImgByIntersectionObserver(dataList, targetPreClass, loadCount, furtherFilterImageId = null) { |
| | | let hasLoadImageCount = 0 |
| | | let observer = new IntersectionObserver(entries => { |
| | | const furtherFilterImageIndex = entries.findIndex(item => item.target.id === targetPreClass + '-' + furtherFilterImageId) |
| | | // 深层过滤选中图片后减少数组循环次数,仅加载包含选中图片的可视图片数量 |
| | | if (furtherFilterImageIndex > 0) entries = entries.slice(furtherFilterImageIndex) |
| | | entries = entries.slice(0, loadCount) |
| | | entries.forEach(item => { |
| | | if (item.isIntersecting) { |
| | | item.target.src = item.target.dataset.src |
| | | hasLoadImageCount++ |
| | | observer.unobserve(item.target) |
| | | } |
| | | }) |
| | | if (hasLoadImageCount === dataList.length) { |
| | | observer.disconnect() |
| | | observer = null |
| | | } |
| | | }) |
| | | dataList.forEach(item => observer.observe(document.getElementById(targetPreClass + '-' + item.id))) |
| | | }, |
| | | |
| | | horizontalScroll(event) { |
| | | event.preventDefault() |
| | | const documentContainer = document.querySelector('.document-container') |
| | | // deltaY属性是鼠标滚动滚轮滚动一下,页面滚动的距离 |
| | | // Y是垂直方向 |
| | | // 鼠标滚轮向前滚动一轮,deltaY=-100;向后滚动一轮,deltaY=100; |
| | | // deltaY的内部实现肯定是监听鼠标滚轮是向前滚动还是向后滚动事件,然后更改deltaY的值为正或者负。 |
| | | // 水平滚动也需要有类似deltaY这样的状态,所以直接使用deltaY就可以了,虽然Y表示的是垂直方向的滚动。 |
| | | const deltaY = event.deltaY |
| | | // scrollLeft属性是元素左侧的滚动距离,通过改变这个属性的值,实现水平滚动的效果。 |
| | | documentContainer.scrollLeft += deltaY |
| | | }, |
| | | |
| | | imageLoadDone(record) { |
| | | console.log('图片加载完成') |
| | | record.loading = false |
| | | }, |
| | | |
| | | scrollToTop() { |
| | | console.log('触发回到顶部') |
| | | this.leftContainer.scrollTo({ top: 0 }) |
| | | this.rightBottomContainer.scrollTo({ top: 0 }) |
| | | }, |
| | | |
| | | /** |
| | | * 图片预览 |
| | | * @param text 图片地址 |
| | | */ |
| | | getImgView(text) { |
| | | if (text && text.indexOf(',') > 0) { |
| | | text = text.substring(0, text.indexOf(',')) |
| | | } |
| | | return getFileAccessHttpUrl(text) |
| | | }, |
| | | |
| | | handleScrollEventSwitch(isAddEvent) { |
| | | if (isAddEvent) { |
| | | this.leftContainer.addEventListener('scroll', this.lazyLoadData) |
| | | this.rightBottomContainer.addEventListener('scroll', this.lazyLoadData) |
| | | } else { |
| | | this.leftContainer.removeEventListener('scroll', this.lazyLoadData) |
| | | this.rightBottomContainer.removeEventListener('scroll', this.lazyLoadData) |
| | | } |
| | | }, |
| | | |
| | | resetImgListScrollConfig() { |
| | | this.scrollToMarginConfig.hasScrollToTopCount = 0 |
| | | this.scrollToMarginConfig.hasScrollToBottomCount = 0 |
| | | } |
| | | }, |
| | | beforeDestroy() { |
| | | this.handleScrollEventSwitch(false) |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | <style scoped lang="less"> |
| | | @main-container-background: rgba(255, 255, 255, .7); |
| | | @container-border-radius: 12px; |
| | | @container-padding: 10px; |
| | | @single-history-edit-border: 3px solid #ABC0CC; |
| | | @single-history-hover-background: #f1f1f1; |
| | | @single-history-active-background: #e5ebed; |
| | | @input-container-border: 3px solid #B8CAD5; |
| | | @user-question-background: #e5ebed; |
| | | @assistant-answer-background: #F0F5F5; |
| | | @conversation-content-container-box-shadow: 2px 2px 10px 0px #ddd; |
| | | @input-container-box-shadow: 2px 2px 10px 0px #ABC0CC; |
| | | @largeImg-container-box-shadow: 0 -3px 10px 0px #ddd; |
| | | @scrollbar-track-background: #f6f6f6; |
| | | @scrollbar-thumb-background: #e9e9e9; |
| | | @scrollbar-thumb-hover-background: #cfcfcf; |
| | | @scrollbar-corner-background: #f6f6f6; |
| | | |
| | | .page-container { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | -webkit-justify-content: flex-end; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | font-size: 18px; |
| | | height: 100%; |
| | | font-family: ali_r_main; |
| | | |
| | | .outer-container { |
| | | width: 100%; |
| | | height: 850px; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | |
| | | .left-spin-container { |
| | | width: 10%; |
| | | height: 100%; |
| | | background-color: @main-container-background; |
| | | border-radius: @container-border-radius; |
| | | margin-right: 25px; |
| | | font-size: 16px; |
| | | position: relative; |
| | | |
| | | .left-container { |
| | | width: 100%; |
| | | height: 100%; |
| | | padding: @container-padding; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: space-between; |
| | | overflow: auto; |
| | | |
| | | &::-webkit-scrollbar { |
| | | width: 8px; |
| | | height: 0; |
| | | } |
| | | |
| | | .single-thumbnail-container { |
| | | padding: @container-padding; |
| | | cursor: pointer; |
| | | border-radius: @container-border-radius; |
| | | |
| | | &:not(:last-child) { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | img { |
| | | width: 100%; |
| | | height: 189px; |
| | | } |
| | | |
| | | & > div:last-child { |
| | | margin-top: 10px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .thumbnail-image-container { |
| | | position: relative; |
| | | } |
| | | |
| | | &:hover { |
| | | background-color: @single-history-hover-background; |
| | | } |
| | | |
| | | &.single-thumbnail-active { |
| | | background-color: @single-history-active-background; |
| | | } |
| | | |
| | | /deep/ .ant-skeleton { |
| | | margin: 0; |
| | | position: absolute; |
| | | width: 100%; |
| | | height: 189px; |
| | | .ant-skeleton-header { |
| | | padding: 0; |
| | | .ant-skeleton-avatar-lg { |
| | | width: 100%; |
| | | height: 189px; |
| | | border-radius: @container-border-radius; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | .right-container { |
| | | width: 80%; |
| | | height: 100%; |
| | | border-radius: @container-border-radius; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: space-between; |
| | | |
| | | .right-top-container { |
| | | height: 120px; |
| | | margin-bottom: 25px; |
| | | display: flex; |
| | | justify-content: center; |
| | | |
| | | .document-spin-container { |
| | | width: 50%; |
| | | height: 100%; |
| | | font-size: 14px; |
| | | background-color: @main-container-background; |
| | | border-radius: @container-border-radius; |
| | | margin-right: 25px; |
| | | position: relative; |
| | | |
| | | .document-container { |
| | | overflow-y: hidden; |
| | | overflow-x: auto; |
| | | display: flex; |
| | | align-items: center; |
| | | padding: @container-padding; |
| | | |
| | | &::-webkit-scrollbar { |
| | | width: 0; |
| | | height: 8px; |
| | | } |
| | | |
| | | .single-document-container { |
| | | width: 22%; |
| | | height: 100%; |
| | | cursor: pointer; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: space-evenly; |
| | | align-items: center; |
| | | flex-shrink: 0; |
| | | border-radius: @container-border-radius; |
| | | padding: @container-padding; |
| | | |
| | | img { |
| | | width: 40px; |
| | | } |
| | | |
| | | .single-document-name { |
| | | width: 100%; |
| | | text-align: center; |
| | | /*overflow: hidden;*/ |
| | | /*white-space: nowrap;*/ |
| | | /*text-overflow: ellipsis;*/ |
| | | } |
| | | |
| | | &:not(:last-child) { |
| | | margin-right: 4%; |
| | | } |
| | | |
| | | &:hover { |
| | | background-color: @single-history-hover-background; |
| | | } |
| | | |
| | | &.single-document-active { |
| | | background-color: @single-history-active-background; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .search-container { |
| | | flex: 1; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: space-evenly; |
| | | align-items: center; |
| | | |
| | | .input-container { |
| | | width: 100%; |
| | | display: flex; |
| | | background-color: transparent; |
| | | border: @single-history-edit-border; |
| | | border-radius: @container-border-radius; |
| | | padding: @container-padding; |
| | | |
| | | input { |
| | | flex: 1; |
| | | outline: none; |
| | | background-color: transparent; |
| | | letter-spacing: 1px; |
| | | border: none; |
| | | |
| | | &::placeholder { |
| | | color: #9A9C9C; |
| | | } |
| | | } |
| | | |
| | | img { |
| | | width: 32px; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .right-bottom-spin-container { |
| | | width: 100%; |
| | | flex: 1; |
| | | background-color: @main-container-background; |
| | | border-radius: @container-border-radius; |
| | | position: relative; |
| | | overflow: hidden; |
| | | |
| | | .right-bottom-container { |
| | | height: 100%; |
| | | background-color: @main-container-background; |
| | | border-radius: @container-border-radius; |
| | | overflow: auto; |
| | | text-align: center; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | |
| | | .single-largeImg-container { |
| | | box-shadow: @largeImg-container-box-shadow; |
| | | width: 70%; |
| | | margin-top: 25px; |
| | | position: relative; |
| | | } |
| | | |
| | | &.further-filter-container { |
| | | flex-direction: row; |
| | | justify-content: left; |
| | | flex-wrap: wrap; |
| | | padding: 12px 0; |
| | | |
| | | .single-filterImg-container { |
| | | box-shadow: @largeImg-container-box-shadow; |
| | | width: 45%; |
| | | margin-top: 12px; |
| | | margin-bottom: 12px; |
| | | cursor: pointer; |
| | | position: relative; |
| | | |
| | | &:nth-child(odd) { |
| | | margin-left: 2%; |
| | | margin-right: 2%; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /deep/ .ant-skeleton { |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | margin: 0; |
| | | .ant-skeleton-header { |
| | | padding: 0; |
| | | .ant-skeleton-avatar-lg { |
| | | width: 100%; |
| | | height: 1640px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | img { |
| | | width: 100%; |
| | | height: 1640px; |
| | | } |
| | | |
| | | #back-to-largeImg { |
| | | width: 3%; |
| | | height: auto; |
| | | position: absolute; |
| | | right: 2%; |
| | | top: auto; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | &::-webkit-scrollbar { |
| | | width: 8px; |
| | | height: 0; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .left-container, .document-container, .right-bottom-container { |
| | | &:hover { |
| | | &::-webkit-scrollbar-track { |
| | | background: @scrollbar-track-background; |
| | | } |
| | | &::-webkit-scrollbar-thumb { |
| | | background: @scrollbar-thumb-background; |
| | | } |
| | | &::-webkit-scrollbar-thumb:hover { |
| | | background: @scrollbar-thumb-hover-background; |
| | | } |
| | | &::-webkit-scrollbar-corner { |
| | | background: @scrollbar-corner-background; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /deep/ .ant-spin { |
| | | position: absolute; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | pointer-events: none; |
| | | z-index: 999; |
| | | |
| | | .anticon { |
| | | font-size: 24px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </style> |