feat: 添加直链功能
- 新增直链相关 API 和工具函数 - 实现直链对话框组件 - 在文件上下文菜单中添加直链相关选项 - 优化文件上下文菜单样式和布局
This commit is contained in:
parent
0d07b963b7
commit
b8b0471f48
1
public/resource/font_2024484_0fh6xrzocbtk.js
Normal file
1
public/resource/font_2024484_0fh6xrzocbtk.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
40
src/api/direct-file.js
Normal file
40
src/api/direct-file.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
/**
|
||||||
|
* 创建直链
|
||||||
|
* @param params
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
createDirectLink: function(params) {
|
||||||
|
return request({
|
||||||
|
url: 'direct-link/create',
|
||||||
|
method: 'post',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 重置直链
|
||||||
|
* @param params
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
resetDirectLink: function(params) {
|
||||||
|
return request({
|
||||||
|
url: 'direct-link/reset',
|
||||||
|
method: 'put',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 重置直链
|
||||||
|
* @param params
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
resetAllDirectLink: function(params) {
|
||||||
|
return request({
|
||||||
|
url: 'direct-link/reset-all',
|
||||||
|
method: 'delete',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
118
src/components/DirectLinkDialog/index.vue
Normal file
118
src/components/DirectLinkDialog/index.vue
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<!--直链-->
|
||||||
|
<el-dialog :title="'直链 - ' + filename" :style="{ fontWeight: 600 }" :visible.sync="dialogVisible" @close="dialogClose">
|
||||||
|
<div>
|
||||||
|
<div class="direct-file-content">
|
||||||
|
<el-input placeholder="" v-model="directUrl" readonly></el-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button round size="small" type="danger" @click="resetAllDirectLink" :loading="resetAllLoading">重置所有直链</el-button>
|
||||||
|
<el-button round size="small" @click="resetDirectLink" :loading="resetLoading">重置直链</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
|
||||||
|
import directFileApi from '@/api/direct-file'
|
||||||
|
import fileConfig from '@/utils/file-config'
|
||||||
|
import { copyText } from '@/utils/copy-text'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "DirectLinkDialog",
|
||||||
|
components: {
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
status: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
file: {
|
||||||
|
type: Object,
|
||||||
|
default: function () {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dialogVisible: false,
|
||||||
|
filename: '',
|
||||||
|
directUrl: '',
|
||||||
|
resetLoading: false,
|
||||||
|
resetAllLoading: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
status(visible) {
|
||||||
|
if (visible) {
|
||||||
|
this.dialogVisible = true
|
||||||
|
this.filename = this.file.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
dialogClose() {
|
||||||
|
this.$emit('update:status', this.dialogVisible)
|
||||||
|
},
|
||||||
|
getDirectLink(file, isCopy) {
|
||||||
|
directFileApi.createDirectLink({ fileId: file.id }).then(res => {
|
||||||
|
this.directUrl = fileConfig.directFileUrl(res.data, file)
|
||||||
|
if (isCopy) {
|
||||||
|
copyText(this.directUrl)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
resetDirectLink() {
|
||||||
|
this.resetLoading = true
|
||||||
|
this.$confirm('确定要重置该直链吗?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
directFileApi.resetDirectLink({ fileId: this.file.id }).then(res => {
|
||||||
|
this.directUrl = fileConfig.directFileUrl(res.data, this.file)
|
||||||
|
this.resetLoading = false
|
||||||
|
this.$message.success('重置成功')
|
||||||
|
}).catch(() => {
|
||||||
|
this.resetLoading = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}).catch(() => {
|
||||||
|
this.resetLoading = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
resetAllDirectLink() {
|
||||||
|
this.resetAllLoading = true
|
||||||
|
|
||||||
|
this.$confirm('确定要重置所有直链吗? 此用户下的所有直链都将失效', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
directFileApi.resetAllDirectLink({ fileId: this.file.id }).then(res => {
|
||||||
|
this.directUrl = fileConfig.directFileUrl(res.data, this.file)
|
||||||
|
this.resetAllLoading = false
|
||||||
|
this.$message.success('重置所有直链成功')
|
||||||
|
}).catch(() => {
|
||||||
|
this.resetAllLoading = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}).catch(() => {
|
||||||
|
this.resetAllLoading = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
||||||
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import { Icon } from 'ant-design-vue'
|
import { Icon } from 'ant-design-vue'
|
||||||
const IconFont = Icon.createFromIconfontCN({
|
const IconFont = Icon.createFromIconfontCN({
|
||||||
scriptUrl: document.location.protocol + '/resource/font_2024484_3m5puxhkyzz.js'
|
scriptUrl: document.location.protocol + '/resource/font_2024484_0fh6xrzocbtk.js'
|
||||||
})
|
})
|
||||||
|
|
||||||
// 把此段代码贴到iconfont项目页面的控制台中, 以获取图标列表
|
// 把此段代码贴到iconfont项目页面的控制台中, 以获取图标列表
|
||||||
@ -15,7 +15,7 @@ const IconFont = Icon.createFromIconfontCN({
|
|||||||
// console.log(iconNames.slice(80,160))
|
// console.log(iconNames.slice(80,160))
|
||||||
|
|
||||||
export const iconFonts = {
|
export const iconFonts = {
|
||||||
list: ['surge', 'dwg', 'epub', 'huanyuan', 'huishouzhan', 'glb', 'gengxinjindu', 'duigou', 'bars-solid', 'sort-amount-down-solid', 'sort-amount-up-alt-solid', 'tag2', 'guazai', 'duplicate', 'play1', "qrcode", "arrow1_left", "wulianwang-","zuji","disk-drive", "menu-fuzhi", "iso", "zuijinhuoyue","key", "shouquan", "sort", "grid", "list", "emoji-a", "emoji-bizui", "emoji-baiyan", "emoji-aixin", "emoji-dajing", "emoji-ziya", "emoji-daxiao", "emoji-esi", "emoji-fadai", "emoji-fankun", "emoji-ganga", "emoji-fennu", "emoji-hanyan", "emoji-jingkong", "emoji-haochi", "emoji-emo", "emoji-jingsong", "emoji-jingya", "emoji-kaixin", "emoji-lengku", "emoji-danao", "emoji-liukoushui", "emoji-liulei", "emoji-mengbi", "mianwubiaoqing", "nanguo", "shuizhuo", "taoyan", "tanchi", "siliao", "tiaopi", "xiaochulei", "wuliao", "xingxingyan", "xieyan", "xiasi", "xiaolian", "ku", "shengqi", "yousiliao", "en", "bushufu", "bianbian", "fankun1", "feiwen", "ganmao", "huaixiao", "liuhan", "outu", "keshui", "renzhe", "santiaoxian", "guaiwu", "shoushang", "tianshi", "shuai", "xianwen", "xiaodiaodaya", "xiong", "yiwen", "yun", "liubixie", "shimo", "dianzan", "biti", "fendou", "huqi", "heng", "kulou", "leng", "taoyan1", "shuixing", "aini", "aixin1", "zhadan", "xinsui",
|
list: ['a-editlink_nor', 'link', 'copy-link', 'surge', 'dwg', 'epub', 'huanyuan', 'huishouzhan', 'glb', 'gengxinjindu', 'duigou', 'bars-solid', 'sort-amount-down-solid', 'sort-amount-up-alt-solid', 'tag2', 'guazai', 'duplicate', 'play1', "qrcode", "arrow1_left", "wulianwang-","zuji","disk-drive", "menu-fuzhi", "iso", "zuijinhuoyue","key", "shouquan", "sort", "grid", "list", "emoji-a", "emoji-bizui", "emoji-baiyan", "emoji-aixin", "emoji-dajing", "emoji-ziya", "emoji-daxiao", "emoji-esi", "emoji-fadai", "emoji-fankun", "emoji-ganga", "emoji-fennu", "emoji-hanyan", "emoji-jingkong", "emoji-haochi", "emoji-emo", "emoji-jingsong", "emoji-jingya", "emoji-kaixin", "emoji-lengku", "emoji-danao", "emoji-liukoushui", "emoji-liulei", "emoji-mengbi", "mianwubiaoqing", "nanguo", "shuizhuo", "taoyan", "tanchi", "siliao", "tiaopi", "xiaochulei", "wuliao", "xingxingyan", "xieyan", "xiasi", "xiaolian", "ku", "shengqi", "yousiliao", "en", "bushufu", "bianbian", "fankun1", "feiwen", "ganmao", "huaixiao", "liuhan", "outu", "keshui", "renzhe", "santiaoxian", "guaiwu", "shoushang", "tianshi", "shuai", "xianwen", "xiaodiaodaya", "xiong", "yiwen", "yun", "liubixie", "shimo", "dianzan", "biti", "fendou", "huqi", "heng", "kulou", "leng", "taoyan1", "shuixing", "aini", "aixin1", "zhadan", "xinsui",
|
||||||
"maren", "zhutou", "qie", "youling", "apple-fill", "attachment", "android-fill", "apple", "download", "arrow-up-circle", "arrow-right-circle", "arrow-down", "ashbin", "add", "file_music", "menu", "role", "jiaoseguanli", "yemianshezhi", "drop_down", "yuandian", "tag", "service-directory", "fabu", "wailian", "bianji-", "WEBSITE", "wangzhanguanli", "Up", "up", "fenlei", "guanlizhuanjiawenzhang", "pifu", "tuichudenglu", "shezhi", "wangzhan", "huaban", "yunshezhi", "UserSettings", "blogger", "biaoqian", "myself", "guidang", "quxiaoyulan1-copy", "yulan-copy", "quxiaoyulan1", "yulan"]
|
"maren", "zhutou", "qie", "youling", "apple-fill", "attachment", "android-fill", "apple", "download", "arrow-up-circle", "arrow-right-circle", "arrow-down", "ashbin", "add", "file_music", "menu", "role", "jiaoseguanli", "yemianshezhi", "drop_down", "yuandian", "tag", "service-directory", "fabu", "wailian", "bianji-", "WEBSITE", "wangzhanguanli", "Up", "up", "fenlei", "guanlizhuanjiawenzhang", "pifu", "tuichudenglu", "shezhi", "wangzhan", "huaban", "yunshezhi", "UserSettings", "blogger", "biaoqian", "myself", "guidang", "quxiaoyulan1-copy", "yulan-copy", "quxiaoyulan1", "yulan"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -775,6 +775,7 @@
|
|||||||
@onSuccess="shareSuccess"
|
@onSuccess="shareSuccess"
|
||||||
@onCancelShare="onCancelShare"
|
@onCancelShare="onCancelShare"
|
||||||
></share-dialog>
|
></share-dialog>
|
||||||
|
<direct-link-dialog ref="directLinkDialog" :status.sync="directLinkDialogVisible" :file="rowContextData"/>
|
||||||
<el-dialog
|
<el-dialog
|
||||||
class="new-text-file-dialog"
|
class="new-text-file-dialog"
|
||||||
:title="newCreateFileDialogTitle"
|
:title="newCreateFileDialogTitle"
|
||||||
@ -858,6 +859,7 @@
|
|||||||
import api from '@/api/file-api'
|
import api from '@/api/file-api'
|
||||||
import BreadcrumbFilePath from '@/components/Breadcrumb/BreadcrumbFilePath'
|
import BreadcrumbFilePath from '@/components/Breadcrumb/BreadcrumbFilePath'
|
||||||
import ButtonUpload from '@/components/button/ButtonUpload'
|
import ButtonUpload from '@/components/button/ButtonUpload'
|
||||||
|
import DirectLinkDialog from '@/components/DirectLinkDialog/index.vue'
|
||||||
import EmptyFile from '@/components/EmptyFile'
|
import EmptyFile from '@/components/EmptyFile'
|
||||||
|
|
||||||
import FileTree from '@/components/FileTree'
|
import FileTree from '@/components/FileTree'
|
||||||
@ -881,7 +883,7 @@ import store from '@/store'
|
|||||||
import { getElementToPageLeft } from '@/utils/dom'
|
import { getElementToPageLeft } from '@/utils/dom'
|
||||||
|
|
||||||
import fileConfig from '@/utils/file-config'
|
import fileConfig from '@/utils/file-config'
|
||||||
import { fileOperations } from '@/utils/file-operations'
|
import { directLinkSubMenus, fileOperations } from '@/utils/file-operations'
|
||||||
import { suffix } from '@/utils/file-type'
|
import { suffix } from '@/utils/file-type'
|
||||||
import { formatExif, formatVideo } from '@/utils/media'
|
import { formatExif, formatVideo } from '@/utils/media'
|
||||||
import { formatSize, formatTime } from '@/utils/number'
|
import { formatSize, formatTime } from '@/utils/number'
|
||||||
@ -895,6 +897,7 @@ import { mapGetters, mapState } from 'vuex'
|
|||||||
export default {
|
export default {
|
||||||
name: 'ShowFile',
|
name: 'ShowFile',
|
||||||
components: {
|
components: {
|
||||||
|
DirectLinkDialog,
|
||||||
FileContextmenu,
|
FileContextmenu,
|
||||||
FileClipboard,
|
FileClipboard,
|
||||||
DialogFileList,
|
DialogFileList,
|
||||||
@ -982,6 +985,7 @@ export default {
|
|||||||
default: function() {
|
default: function() {
|
||||||
return [
|
return [
|
||||||
fileOperations.open,
|
fileOperations.open,
|
||||||
|
{ iconClass: 'link', label: '直链', operation: 'directLink', child: directLinkSubMenus },
|
||||||
fileOperations.download,
|
fileOperations.download,
|
||||||
{ iconClass: 'share', label: '分享...', operation: 'share' },
|
{ iconClass: 'share', label: '分享...', operation: 'share' },
|
||||||
{ iconClass: 'tag', label: '标签...' , operation: 'tag'},
|
{ iconClass: 'tag', label: '标签...' , operation: 'tag'},
|
||||||
@ -1122,6 +1126,7 @@ export default {
|
|||||||
allChecked: false,
|
allChecked: false,
|
||||||
summaries: '',
|
summaries: '',
|
||||||
shareDialogVisible: false,
|
shareDialogVisible: false,
|
||||||
|
directLinkDialogVisible: false,
|
||||||
shareDialogObject: {},
|
shareDialogObject: {},
|
||||||
tagDialogVisible: false,
|
tagDialogVisible: false,
|
||||||
tagDialogObjectList: [],
|
tagDialogObjectList: [],
|
||||||
@ -3542,11 +3547,11 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (row.ossFolder) {
|
if (row.ossFolder) {
|
||||||
// 删除分享选项
|
const reservations = ['open', 'tag']
|
||||||
let index = this.getIndexOfFileContextMenus('share')
|
// 删除this.menus中不要的菜单, 仅保留reservations中的菜单
|
||||||
if (index > -1) {
|
this.menus = this.menus.filter(item =>
|
||||||
this.menus.splice(index, 1)
|
reservations.includes(item.operation)
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
this.setMenusCopyDownLoadLinks(row)
|
this.setMenusCopyDownLoadLinks(row)
|
||||||
}
|
}
|
||||||
@ -3656,20 +3661,20 @@ export default {
|
|||||||
e.clientX = event.clientX + 50
|
e.clientX = event.clientX + 50
|
||||||
e.clientY = event.clientY + 2
|
e.clientY = event.clientY + 2
|
||||||
e.top = event.clientY
|
e.top = event.clientY
|
||||||
e.left = event.clientX
|
e.left = event.clientX + 2
|
||||||
|
|
||||||
const dividerSize = this.menus.filter(item => item.divider).length
|
const dividerSize = this.menus.filter(item => item.divider).length
|
||||||
|
|
||||||
const containerWidth = 180 + 5
|
const containerWidth = 180 + 10
|
||||||
const containerHeight = (this.menus.length - dividerSize) * 35 + (dividerSize * 10) + 21
|
const containerHeight = (this.menus.length - dividerSize) * 35 + (dividerSize * 11) + 18 + 10
|
||||||
const distanceToBottom = document.documentElement.clientHeight - event.clientY
|
const distanceToBottom = document.documentElement.clientHeight - event.clientY
|
||||||
const distanceToRight = document.documentElement.clientWidth - event.clientX
|
const distanceToRight = document.documentElement.clientWidth - event.clientX
|
||||||
|
|
||||||
if (distanceToBottom < containerHeight) {
|
if (distanceToBottom < containerHeight) {
|
||||||
e.top = event.clientY - containerHeight
|
e.top = event.clientY - (containerHeight - distanceToBottom)
|
||||||
}
|
}
|
||||||
if (distanceToRight < containerWidth) {
|
if (distanceToRight < containerWidth) {
|
||||||
e.left = event.clientX - containerWidth
|
e.left = event.clientX - containerWidth + 8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3896,6 +3901,15 @@ export default {
|
|||||||
// 返回原处
|
// 返回原处
|
||||||
this.restoreFile()
|
this.restoreFile()
|
||||||
break
|
break
|
||||||
|
case 'manageDirectLink':
|
||||||
|
// 管理直链
|
||||||
|
this.directLinkDialogVisible = true
|
||||||
|
this.$refs.directLinkDialog.getDirectLink(this.rowContextData)
|
||||||
|
break
|
||||||
|
case 'copyDirectLink':
|
||||||
|
// 复制直链
|
||||||
|
this.$refs.directLinkDialog.getDirectLink(this.rowContextData, true)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
this.$refs.contextShow.hideMenu()
|
this.$refs.contextShow.hideMenu()
|
||||||
},
|
},
|
||||||
@ -4769,6 +4783,9 @@ export default {
|
|||||||
if (this.shareDialogVisible) {
|
if (this.shareDialogVisible) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if (this.directLinkDialogVisible) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
if (this.tagDialogVisible) {
|
if (this.tagDialogVisible) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@ -124,7 +124,7 @@ export default {
|
|||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: flex-start;
|
||||||
|
|
||||||
>>> .svg-icon {
|
>>> .svg-icon {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
|
|||||||
36
src/utils/copy-text.js
Normal file
36
src/utils/copy-text.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
export async function copyText(text) {
|
||||||
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(text);
|
||||||
|
this.$message.success('复制成功');
|
||||||
|
} catch (err) {
|
||||||
|
fallbackCopyText(text);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fallbackCopyText(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fallbackCopyText(text) {
|
||||||
|
const textarea = document.createElement('textarea');
|
||||||
|
textarea.value = text;
|
||||||
|
textarea.setAttribute('readonly', ''); // 防止手机端弹出键盘
|
||||||
|
textarea.style.position = 'absolute';
|
||||||
|
textarea.style.left = '-9999px';
|
||||||
|
document.body.appendChild(textarea);
|
||||||
|
// 兼容 Safari 和 Chrome 的选中文本方式
|
||||||
|
textarea.select();
|
||||||
|
textarea.setSelectionRange(0, textarea.value.length); // 额外设置范围,兼容 Safari
|
||||||
|
try {
|
||||||
|
const successful = document.execCommand('copy');
|
||||||
|
if (successful) {
|
||||||
|
Vue.prototype.$message.success('复制成功');
|
||||||
|
} else {
|
||||||
|
Vue.prototype.$message.error('复制失败');
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('execCommand 复制失败:', err);
|
||||||
|
Vue.prototype.$message.error('复制失败');
|
||||||
|
}
|
||||||
|
document.body.removeChild(textarea);
|
||||||
|
}
|
||||||
@ -143,4 +143,11 @@ export default {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
directFileUrl: function(mark, file) {
|
||||||
|
if (file.isFolder) {
|
||||||
|
return window.location.origin + `${this.baseUrl}/direct-file/${mark}/${file.name}.zip`
|
||||||
|
} else {
|
||||||
|
return window.location.origin + `${this.baseUrl}/direct-file/${mark}/${file.name}`
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,11 @@ export const fileOperations = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const directLinkSubMenus = [
|
||||||
|
{ label: '管理...', operation: 'manageDirectLink', iconClass: 'a-editlink_nor'},
|
||||||
|
{ label: '复制', operation: 'copyDirectLink', iconClass: 'copy-link'},
|
||||||
|
]
|
||||||
|
|
||||||
export const fileArrangements = [
|
export const fileArrangements = [
|
||||||
{ label: '名称', operation: 'orderName', orderProp: 'name'},
|
{ label: '名称', operation: 'orderName', orderProp: 'name'},
|
||||||
{ label: '大小', operation: 'orderSize', orderProp: 'size'},
|
{ label: '大小', operation: 'orderSize', orderProp: 'size'},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user