✨ 分享链接添加过期时间

This commit is contained in:
jmal 2023-03-05 20:27:42 +08:00
parent b0e56ec12f
commit 16a778e051
5 changed files with 499 additions and 151 deletions

View File

@ -31,6 +31,7 @@
"jspdf": "^2.5.1",
"less-loader": "^6.1.0",
"lib-flexible": "^0.3.2",
"moment": "^2.29.4",
"monaco-editor": "^0.23.0",
"monaco-editor-vue": "^1.0.10",
"monaco-editor-webpack-plugin": "^3.0.1",

View File

@ -196,6 +196,14 @@ export default {
params
})
},
// 获取分享信息
getShare: function(params) {
return request({
url: '/get/share',
method: 'get',
params
})
},
// 访问分享链接里的文件夹
accessShareOpenDir: function(params) {
return request({

View File

@ -0,0 +1,384 @@
<template>
<di>
<!--分享-->
<el-dialog title="分享文件" style="{'font-weight': 600}" :visible.sync="shareDialogVisible" @close="shareDialogClose">
<div>
<div class="share-content">
<div class="share-icon">
<icon-file class="share-icon-font" :item="file" :grid="true" :details="true" :image-url="imageUrl" :audio-cover-url="audioCoverUrl"></icon-file>
</div>
<div class="share-filename">
<span>{{ file.name }}</span>
</div>
<div>
<el-form ref="form" class="share-option" :model="shareOption" label-width="82px" size="mini">
<el-form-item :label="shareOptionConfig.linkLabel">
<el-col :span="9" class="share-expires-data" v-if="!shareOptionConfig.shared">
<el-form-item prop="expiresDateOption">
<el-select size="small" v-model="shareOption.expiresDateOption" @change="expiresDateOptionChange">
<el-option label="30天有效" :value="0"></el-option>
<el-option label="永久有效" :value="1"></el-option>
<el-option label="自定义" :value="2"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" v-if="shareOptionConfig.shared" class="shared-expires-text">到期时间</el-col>
<el-col :span="1" v-if="!shareOptionConfig.shared">&nbsp</el-col>
<el-col v-if="shareOption.expiresDateOption === 2" :span="12" class="share-expires-data">
<el-form-item prop="expiresDate">
<el-date-picker
ref="expiresDatePicker"
size="small"
:clearable="false"
v-model="shareOption.expiresDate"
type="date"
:placeholder="!shareOption.expiresDate ? '永久有效' : '选择到期时间'"
align="right"
format="yyyy-MM-dd HH:mm"
value-format="timestamp"
@change="pickerChange"
:picker-options="pickerOptions">
</el-date-picker>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item v-if="!shareOptionConfig.shared" class="share-option-form" label="分享形式" width="100">
<el-col :span="9">
<el-select size="small" v-model="shareOption.isPrivacy">
<el-option label="公开链接" :value="false"></el-option>
<el-option label="私密链接" :value="true"></el-option>
</el-select>
</el-col>
</el-form-item>
<el-col class="share-link">
<el-input size="small" v-if="shareOptionConfig.shared" readonly="readonly" v-model="shareLink"></el-input>
<el-input class="share-link-code" size="small" v-if="shareOptionConfig.shared && shareOption.isPrivacy" readonly="readonly" v-model="extractionCode">
<template slot="prepend">提取码</template>
</el-input>
</el-col>
</el-form>
</div>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button size="small" v-if="!shareOptionConfig.shared" type="primary" @click="submitShare" v-loading="generateShareLinkLoading">创建分享</el-button>
<el-button size="small" class="tag-share-link" v-if="shareOptionConfig.shared && shareOption.isPrivacy" @click="copyShareLink" :data-clipboard-text="shareLink + '&code=' + extractionCode">复制链接和提取码</el-button>
<el-button size="small" class="tag-share-link" v-if="shareOptionConfig.shared" type="primary" @click="copyShareLink" :data-clipboard-text="shareLink">复制链接</el-button>
</div>
</el-dialog>
</di>
</template>
<script>
import moment from 'moment'
import IconFile from "@/components/Icon/IconFile";
import api from '@/api/file-api'
import Clipboard from "clipboard";
export default {
name: "ShareDialog",
components: {
IconFile
},
props: {
fileId: {
type: String,
default: ''
},
file: {
type: Object,
default: function () {
return {}
}
},
status: {
type: Boolean,
default: false
}
},
data() {
return {
imageUrl: process.env.VUE_APP_BASE_API + '/view/thumbnail?jmal-token=' + this.$store.state.user.token + '&id=',
audioCoverUrl: process.env.VUE_APP_BASE_API + '/view/cover?jmal-token=' + this.$store.state.user.token + '&id=',
shareDialogVisible: false,
generateShareLinkLoading: false,
pickerOptions: {
disabledDate(time) {
const dateTime = new Date();
const startDateTime = dateTime.setDate(dateTime.getDate());
const endDateTime = dateTime.setDate(dateTime.getDate() + 30000); //30000为当前日期之后多少天
return (
time.getTime() < new Date(startDateTime).getTime() ||
time.getTime() > new Date(endDateTime).getTime()
);
},
firstDayOfWeek: 1,
shortcuts: [{
text: '7天后',
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() + 3600 * 1000 * 24 * 7);
picker.$emit('pick', date);
}
}, {
text: '30天后',
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() + 3600 * 1000 * 24 * 30);
picker.$emit('pick', date);
}
}, {
text: '半年后',
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() + 3600 * 1000 * 24 * 182.5);
picker.$emit('pick', date);
}
}, {
text: '一年后',
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() + 3600 * 1000 * 24 * 365.5);
picker.$emit('pick', date);
}
}, {
text: '永久',
onClick(picker) {
picker.$emit('pick', 0);
}
}]
},
shareOption: {
expiresDateOption: 1,
isPrivacy: false,
expiresDate: '',
},
shareLink: "",
extractionCode: '',
shareOptionConfig: {
shared: false,
linkLabel: "选择有效期",
}
}
},
watch: {
file(file) {
if (file.fileId) {
console.log('file', file)
}
},
status(visible) {
if(visible){
this.shareDialogVisible = true
if (this.file.shareId) {
console.log('share', this.file)
this.shareOptionConfig.shared = true
this.shareOptionConfig.linkLabel = '分享链接'
this.shareLink = this.getShareLink(this.file.shareId)
this.shareOption.isPrivacy = this.file.isPrivacy
if (this.file.expireDate) {
this.shareOption.expiresDate = moment(this.file.expireDate).format('x')
}
this.shareOption.expiresDateOption = 2
this.extractionCode = this.file.extractionCode
} else {
this.shareOptionConfig.shared = false
this.shareOptionConfig.linkLabel = '选择有效期'
this.shareOption.isPrivacy = false
this.shareOption.expiresDate = null
this.shareOption.expiresDateOption = 1
}
}
}
},
methods: {
shareDialogClose() {
console.log('shareDialogClose')
this.shareOptionConfig.shared = false
this.$emit('update:status', this.shareDialogVisible)
},
expiresDateOptionChange() {
if (this.shareOption.expiresDateOption === 2) {
this.$nextTick(() => {
this.$refs.expiresDatePicker.focus()
})
}
},
pickerChange(time) {
if (time < new Date().getTime()) {
this.shareOption.expiresDate = null
}
if (this.shareOptionConfig.shared) {
this.createShare(true)
}
},
submitShare() {
this.$refs.form.validate((valid) => {
if (valid) {
this.createShare()
} else {
console.log('error submit!!');
return false;
}
})
},
timeFormat(time) {
return moment(time).format("yyyy-MM-DD HH:mm")
},
getShareLink(shareId) {
return window.location.origin + '/s?s=' + shareId
},
createShare(update) {
this.generateShareLinkLoading = true
let expireDate
switch (this.shareOption.expiresDateOption) {
case 0:
let time = new Date().getTime() + 3600 * 1000 * 24 * 30
expireDate = this.timeFormat(time)
this.shareOption.expiresDate = time
break
case 2:
if (this.shareOption.expiresDate) {
expireDate = this.timeFormat(this.shareOption.expiresDate)
}
}
api.generate({
userId: this.file.userId,
fileId: this.file.fileId,
isFolder: this.file.isFolder,
expireDate: expireDate,
isPrivacy: this.shareOption.isPrivacy
}).then(res => {
if (res.data) {
console.log(res.data)
let {shareId, extractionCode} = res.data
this.shareLink = this.getShareLink(shareId)
this.generateShareLinkLoading = false
this.shareOptionConfig.shared = true
this.shareOption.expiresDateOption = 2
this.shareOptionConfig.linkLabel = "分享链接"
this.extractionCode = extractionCode
this.$emit('onSuccess', shareId)
if (update) {
if (!expireDate) {
expireDate = '永久有效'
}
this.$emit("onUpdateExpireData", shareId, expireDate);
this.$message({
duration: 3000,
dangerouslyUseHTMLString: true,
iconClass: 'el-icon-success',
message: '<strong>&nbsp;&nbsp;有效期已设置为: <span>'+ expireDate + '</span> </strong>'
});
}
}
}).catch(() => {
this.generateShareLinkLoading = false
})
},
// 复制分享链接
copyShareLink() {
let clipboard = new Clipboard('.tag-share-link')
clipboard.on('success', e => {
this.$message({
message: '复制成功',
type: 'success',
duration: 1000
});
// 释放内存
clipboard.destroy()
})
clipboard.on('error', e => {
// 不支持复制
this.$message({
message: '该浏览器不支持自动复制',
type: 'warning',
duration: 1000
});
// 释放内存
clipboard.destroy()
})
},
}
}
</script>
<style lang="scss" scoped>
>>> .el-dialog {
max-width: 440px;
.el-dialog__title {
font-weight: 600;
}
}
.share-icon {
margin: 20px 0 20px 0;
text-align: center;
>>> .icon-favorite {
display: none;
}
>>> .icon-share {
display: none;
}
.share-icon-font >>> .svg-icon {
font-size: 8rem;
}
}
.share-filename {
margin: 25px 0 50px 0;
text-align: center;
}
.share-option {
>>>.el-form-item--mini.el-form-item {
margin-bottom: 10px;
}
.share-expires-data {
>>> .el-input__inner {
cursor: pointer;
padding-right: 0;
}
>>> .el-date-editor.el-input {
width: 100%;
}
}
>>> .el-form-item__label {
line-height: 32px;
}
.shared-expires-text {
text-align: right;
line-height: 32px;
padding-right: 5px;
}
}
>>> .dialog-footer {
.el-loading-spinner .circular {
width: 25px !important;
}
}
.share-link {
margin-top: -10px;
margin-bottom: 25px;
.share-link-code {
width: 130px;
margin-top: 10px;
>>> .el-input-group__prepend {
padding:0 10px;
font-weight: 500;
}
}
>>> .el-input__inner {
background-color: #84858d14;
text-align: center;
}
}
</style>

View File

@ -489,18 +489,7 @@
</div>
</el-dialog>
<!--分享-->
<el-dialog :title="'分享:'+shareFileName" :visible.sync="shareDialog" center>
<div v-loading="generateShareLinkLoading">
<el-input readonly="readonly" v-model="shareLink" @focus="setInputFocus" @blur="setInputBlur()"></el-input>
<div slot="footer" class="dialog-footer share-dialog-footer">
<el-button type="primary" class="tag-share-link" @click="copyShareLink" :data-clipboard-text="shareLink">
复制链接
</el-button>
</div>
</div>
</el-dialog>
<share-dialog :file.sync="shareDialogObject" :status.sync="shareDialogVisible" @onSuccess="shareSuccess"></share-dialog>
<el-dialog
class="new-text-file-dialog"
:title="newCreateFileDialogTitle"
@ -549,10 +538,12 @@ import '@/utils/directives.js'
import fileConfig from '@/utils/file-config'
import EditElement from "@/views/markdown/EditElement";
import OfficePreview from "@/components/preview/OfficePreview";
import ShareDialog from "@/components/ShareDialog/index.vue";
export default {
name: 'ShowFile',
components: {
ShareDialog,
OfficePreview,
EditElement,
MessageDialog, AudioPreview, VideoPreview, ImageViewer, SimTextPreview, IconFile, BreadcrumbFilePath, EmptyFile,
@ -767,14 +758,14 @@ export default {
gridColumnWidth: 120,
allChecked: false,
summaries: '',
shareDialog: false,
shareDialogVisible: false,
shareDialogObject: {},
newCreateFileDialog: false,
newCreateFileName: '',
newCreateFileDialogTitle: '',
createFileLoading: false,
shareLink: '',
shareFileName: '',
generateShareLinkLoading: true,
textPreviewVisible: false,
textPreviewRow: {},
imagePreviewRow: {},
@ -2894,52 +2885,41 @@ export default {
row = this.$refs.fileListTable.tableSelectData[0]
}
}
this.shareFileName = row.name
api.generate({
userId: row.userId,
fileId: row.id,
isFolder: row.isFolder
}).then(res => {
this.shareDialog = true
// 这3行代码是为了让vue刷新数据
const isFavorite = this.rowContextData.isFavorite
this.rowContextData.isFavorite = !isFavorite
this.rowContextData.isFavorite = isFavorite
if (res.data) {
let shareId = res.data
this.shareLink = window.location.origin + '/s?s=' + shareId
this.generateShareLinkLoading = false
this.rowContextData.shareId = shareId
}
this.rowContextData.isShare = true
}).catch(() => {
this.shareDialog = false
this.generateShareLinkLoading = false
})
this.shareDialogObject = row
this.shareDialogObject.fileId = row.id
this.shareDialogObject.shareId = undefined
this.shareDialogVisible = true
// this.shareFileName = row.name
// api.generate({
// userId: row.userId,
// fileId: row.id,
// isFolder: row.isFolder
// }).then(res => {
// this.shareDialog = true
// // 这3行代码是为了让vue刷新数据
// const isFavorite = this.rowContextData.isFavorite
// this.rowContextData.isFavorite = !isFavorite
// this.rowContextData.isFavorite = isFavorite
// if (res.data) {
// let shareId = res.data
// this.shareLink = window.location.origin + '/s?s=' + shareId
// this.generateShareLinkLoading = false
// this.rowContextData.shareId = shareId
// }
// this.rowContextData.isShare = true
// }).catch(() => {
// this.shareDialog = false
// this.generateShareLinkLoading = false
// })
},
// 复制分享链接
copyShareLink() {
var clipboard = new Clipboard('.tag-share-link')
clipboard.on('success', e => {
this.$message({
message: '复制成功',
type: 'success',
duration: 1000
});
this.shareDialog = false
// 释放内存
clipboard.destroy()
})
clipboard.on('error', e => {
// 不支持复制
this.$message({
message: '该浏览器不支持自动复制',
type: 'warning',
duration: 1000
});
// 释放内存
clipboard.destroy()
})
shareSuccess(shareId) {
console.log('shareSuccess', shareId)
// 这3行代码是为了让vue刷新数据
const isFavorite = this.rowContextData.isFavorite
this.rowContextData.isFavorite = !isFavorite
this.rowContextData.isFavorite = isFavorite
this.rowContextData.shareId = shareId
this.rowContextData.isShare = true
},
downloadFile() {
let totalSize = 0
@ -3284,6 +3264,12 @@ export default {
.drawer-icon {
text-align: center;
>>> .icon-favorite {
display: none;
}
>>> .icon-share {
display: none;
}
}
.drawer-icon-font >>> .svg-icon {

View File

@ -1,14 +1,6 @@
<template>
<div class="container">
<!--分享-->
<el-dialog :title="'分享:'+shareFileName" :visible.sync="shareDialog" center>
<div v-loading="generateShareLinkLoading">
<el-input readonly="readonly" v-model="shareLink"></el-input>
<div slot="footer" class="dialog-footer share-dialog-footer">
<el-button type="primary" class="tag-share-link" @click="copyShareLink" :data-clipboard-text="shareLink">复制链接</el-button>
</div>
</div>
</el-dialog>
<share-dialog :file.sync="shareDialogObject" :status.sync="shareDialogVisible" @onUpdateExpireData="onUpdateExpireData"></share-dialog>
<!--list布局-->
<div v-show="fileList.length > 0" :style="{'width':'100%','height': clientHeight+'px'}">
<pl-table
@ -95,11 +87,11 @@
<svg-icon title="分享" v-if="scope.row.index === cellMouseIndex" class="button-class" icon-class="cancel-share" @click="cancelShare(scope.row)"/>
</template>
</pl-table-column>
<!--时间-->
<!--创建时间-->
<pl-table-column
v-if="index === 5"
:key="index"
width="250"
width="200"
:prop="item.name"
:index="index"
:label="item.label"
@ -113,11 +105,29 @@
<span>{{scope.row.createDate}}</span>
</template>
</pl-table-column>
<!--修改时间-->
<!--分享形式-->
<pl-table-column
v-if="index === 6"
:key="index"
width="250"
width="150"
:prop="item.name"
:label="item.label"
:index="index"
:sort-orders="['ascending', 'descending']"
:sortable="item.sortable"
:show-overflow-tooltip="true"
align="center"
header-align="center"
>
<template slot-scope="scope">
<span>{{scope.row.isPrivacy ? '私密':'公开'}}</span>
</template>
</pl-table-column>
<!--修改时间-->
<pl-table-column
v-if="index === 7"
:key="index"
width="200"
:prop="item.name"
:label="item.label"
:index="index"
@ -134,17 +144,6 @@
</template>
</pl-table>
</div>
<!--<el-pagination-->
<!--background-->
<!--layout="prev, pager, next"-->
<!--:hide-on-single-page="true"-->
<!--:current-page.sync="pagination.pageIndex"-->
<!--:page-sizes="pagination.pageSizes"-->
<!--:page-size="pagination.pageSize"-->
<!--:total="pagination.total"-->
<!--@current-change="currentChange">-->
<!--</el-pagination>-->
<empty-file
v-if="fileList.length < 1 && !tableLoading"
emptyStatus="还没有分享历史哦~"
@ -158,11 +157,10 @@
import ShowFile from "@/components/ShowFile/ShowFile";
import EmptyFile from "@/components/EmptyFile";
import IconFile from "@/components/Icon/IconFile";
import { strlen, substring10, formatTime, formatSize } from '@/utils/number'
import ShareDialog from "@/components/ShareDialog/index.vue";
import api from '@/api/file-api'
import Clipboard from 'clipboard';
export default {
components: { ShowFile, EmptyFile, IconFile},
components: { ShowFile, EmptyFile, IconFile, ShareDialog},
props: {
emptyStatus: {
'type': String,
@ -245,10 +243,13 @@
name: '', label: '', more: true, index: 4
},
{
name: 'createDate', label: '时间', sortable: 'custom', index: 5
name: 'createDate', label: '链接创建时间', sortable: 'custom', index: 5
},
{
name: 'expireDate', label: '过期时间', sortable: 'custom', index: 6
name: 'isPrivacy', label: '分享形式', sortable: 'custom', index: 6
},
{
name: 'expireDate', label: '过期时间', sortable: 'custom', index: 7
}
],
rowContextData: {},
@ -256,12 +257,12 @@
tableLoading: false,
finished: false,
cellMouseIndex: -1,
editingIndex: -1,
shareDialog: false,
shareLink: '',
shareFileName: '',
generateShareLinkLoading: true,
sumFileAndFolder: ''
sumFileAndFolder: '',
shareDialogVisible: false,
shareDialogObject: {},
}
},
mounted() {
@ -341,7 +342,8 @@
const itemIcon = this.tableHead[1]
const itemName = this.tableHead[2]
const itemSize = this.tableHead[5]
const itemDate = this.tableHead[6]
const itemIsPrivacy = this.tableHead[6]
const itemDate = this.tableHead[7]
if (this.selectRowData.length > 0) {
this.sumFileAndFolder = this.getShowSumFileAndFolder(row)
itemIcon.label = '已选中'
@ -351,6 +353,8 @@
itemSize.sortable = false
itemDate.label = ''
itemDate.sortable = false
itemIsPrivacy.label = ''
itemIsPrivacy.sortable = false
} else {
itemIcon.label = ''
itemName.label = '分享文件'
@ -359,6 +363,8 @@
itemSize.sortable = 'custom'
itemDate.label = '过期时间'
itemDate.sortable = 'custom'
itemIsPrivacy.label = '分享形式'
itemIsPrivacy.sortable = 'custom'
}
},
// 统计文件和文件夹
@ -397,21 +403,10 @@
tableRowClassName({ row, rowIndex }) {
row.index = rowIndex
},
// 选择某行预备数据
preliminaryRowData(row) {
if (row) {
this.selectRowData[0] = row
this.rowContextData = row
}
const isFavorite = this.selectRowData[0].isFavorite
this.highlightFavorite(isFavorite, false)
},
// 单元格hover进入时时间
cellMouseEnter(row) {
if(this.editingIndex === -1){
if (this.indexList.length < 1) {
this.cellMouseIndex = row.index
}
if (this.indexList.length < 1) {
this.cellMouseIndex = row.index
}
},
// 单元格hover退出时时间
@ -421,27 +416,19 @@
// 单元格点击事件
cellClick(row, column) {
clearTimeout(this.Loop);
if(this.editingIndex === -1) {
const columnIndex = column.index
if (columnIndex === 0) {
// 点击选中
this.$refs.fileListTable.toggleRowSelection(row)
}
if (columnIndex === 2) {
if (this.indexList.length < 1) {
if (row.index !== this.editingIndex) {
this.fileClick(row)
this.editingIndex = -1
}
}
}
if (columnIndex === 4) {
// // 单个操作
}
if (this.indexList.length > 0 && columnIndex > 0) {
this.$refs.fileListTable.toggleRowSelection(row)
const columnIndex = column.index
if (columnIndex === 0) {
// 点击选中
this.$refs.fileListTable.toggleRowSelection(row)
}
if (columnIndex === 2) {
if (this.indexList.length < 1) {
this.fileClick(row)
}
}
if (this.indexList.length > 0 && columnIndex > 0) {
this.$refs.fileListTable.toggleRowSelection(row)
}
},
// 取消分享
cancelShare(row) {
@ -466,34 +453,16 @@
},
// 点击文件或文件夹
fileClick(row) {
this.shareDialog = true
this.shareFileName = row.fileName
this.shareLink = window.location.origin+'/s?s='+row.id
this.generateShareLinkLoading = false
this.shareDialogObject = row
this.shareDialogObject.name = row.fileName
this.shareDialogObject.shareId = row.id
this.shareDialogVisible = true
},
// 复制分享链接
copyShareLink() {
var clipboard = new Clipboard('.tag-share-link')
clipboard.on('success', e => {
this.$message({
message: '复制成功',
type: 'success',
duration: 1000
});
this.shareDialog = false
// 释放内存
clipboard.destroy()
})
clipboard.on('error', e => {
// 不支持复制
this.$message({
message: '该浏览器不支持自动复制',
type: 'warning',
duration: 1000
});
// 释放内存
clipboard.destroy()
})
onUpdateExpireData(shareId, expireDate) {
let index = this.fileList.findIndex(item => item.id === shareId)
let share = this.fileList[index]
share.expireDate = expireDate
this.fileList.splice(index, 1, share)
},
}
}