diff --git a/public/resource/font_2024484_0fh6xrzocbtk.js b/public/resource/font_2024484_0fh6xrzocbtk.js new file mode 100644 index 0000000..2106d85 --- /dev/null +++ b/public/resource/font_2024484_0fh6xrzocbtk.js @@ -0,0 +1 @@ +window._iconfont_svg_string_2024484='',(c=>{var l=(a=(a=document.getElementsByTagName("script"))[a.length-1]).getAttribute("data-injectcss"),a=a.getAttribute("data-disable-injectsvg");if(!a){var h,t,p,i,M,z=function(l,a){a.parentNode.insertBefore(l,a)};if(l&&!c.__iconfont__svg__cssinject__){c.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(l){console&&console.log(l)}}h=function(){var l,a=document.createElement("div");a.innerHTML=c._iconfont_svg_string_2024484,(a=a.getElementsByTagName("svg")[0])&&(a.setAttribute("aria-hidden","true"),a.style.position="absolute",a.style.width=0,a.style.height=0,a.style.overflow="hidden",a=a,(l=document.body).firstChild?z(a,l.firstChild):l.appendChild(a))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(h,0):(t=function(){document.removeEventListener("DOMContentLoaded",t,!1),h()},document.addEventListener("DOMContentLoaded",t,!1)):document.attachEvent&&(p=h,i=c.document,M=!1,F(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,d())})}function d(){M||(M=!0,p())}function F(){try{i.documentElement.doScroll("left")}catch(l){return void setTimeout(F,50)}d()}})(window); diff --git a/public/resource/font_2024484_3m5puxhkyzz.js b/public/resource/font_2024484_3m5puxhkyzz.js deleted file mode 100644 index a51a031..0000000 --- a/public/resource/font_2024484_3m5puxhkyzz.js +++ /dev/null @@ -1 +0,0 @@ -window._iconfont_svg_string_2024484='',(c=>{var l=(a=(a=document.getElementsByTagName("script"))[a.length-1]).getAttribute("data-injectcss"),a=a.getAttribute("data-disable-injectsvg");if(!a){var h,t,p,i,M,z=function(l,a){a.parentNode.insertBefore(l,a)};if(l&&!c.__iconfont__svg__cssinject__){c.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(l){console&&console.log(l)}}h=function(){var l,a=document.createElement("div");a.innerHTML=c._iconfont_svg_string_2024484,(a=a.getElementsByTagName("svg")[0])&&(a.setAttribute("aria-hidden","true"),a.style.position="absolute",a.style.width=0,a.style.height=0,a.style.overflow="hidden",a=a,(l=document.body).firstChild?z(a,l.firstChild):l.appendChild(a))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(h,0):(t=function(){document.removeEventListener("DOMContentLoaded",t,!1),h()},document.addEventListener("DOMContentLoaded",t,!1)):document.attachEvent&&(p=h,i=c.document,M=!1,F(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,d())})}function d(){M||(M=!0,p())}function F(){try{i.documentElement.doScroll("left")}catch(l){return void setTimeout(F,50)}d()}})(window); diff --git a/src/api/direct-file.js b/src/api/direct-file.js new file mode 100644 index 0000000..d3a2980 --- /dev/null +++ b/src/api/direct-file.js @@ -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 + }) + }, +} diff --git a/src/components/DirectLinkDialog/index.vue b/src/components/DirectLinkDialog/index.vue new file mode 100644 index 0000000..625d2bc --- /dev/null +++ b/src/components/DirectLinkDialog/index.vue @@ -0,0 +1,118 @@ + + + + + diff --git a/src/components/Icon/Icon.vue b/src/components/Icon/Icon.vue index 82e4f42..0eb168c 100644 --- a/src/components/Icon/Icon.vue +++ b/src/components/Icon/Icon.vue @@ -5,7 +5,7 @@ import { Icon } from 'ant-design-vue' const IconFont = Icon.createFromIconfontCN({ - scriptUrl: document.location.protocol + '/resource/font_2024484_3m5puxhkyzz.js' + scriptUrl: document.location.protocol + '/resource/font_2024484_0fh6xrzocbtk.js' }) // 把此段代码贴到iconfont项目页面的控制台中, 以获取图标列表 @@ -15,7 +15,7 @@ const IconFont = Icon.createFromIconfontCN({ // console.log(iconNames.slice(80,160)) 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"] } diff --git a/src/components/ShowFile/ShowFile.vue b/src/components/ShowFile/ShowFile.vue index 3ea68a0..1a1dd48 100644 --- a/src/components/ShowFile/ShowFile.vue +++ b/src/components/ShowFile/ShowFile.vue @@ -775,6 +775,7 @@ @onSuccess="shareSuccess" @onCancelShare="onCancelShare" > + -1) { - this.menus.splice(index, 1) - } + const reservations = ['open', 'tag'] + // 删除this.menus中不要的菜单, 仅保留reservations中的菜单 + this.menus = this.menus.filter(item => + reservations.includes(item.operation) + ) } this.setMenusCopyDownLoadLinks(row) } @@ -3656,20 +3661,20 @@ export default { e.clientX = event.clientX + 50 e.clientY = event.clientY + 2 e.top = event.clientY - e.left = event.clientX + e.left = event.clientX + 2 const dividerSize = this.menus.filter(item => item.divider).length - const containerWidth = 180 + 5 - const containerHeight = (this.menus.length - dividerSize) * 35 + (dividerSize * 10) + 21 + const containerWidth = 180 + 10 + const containerHeight = (this.menus.length - dividerSize) * 35 + (dividerSize * 11) + 18 + 10 const distanceToBottom = document.documentElement.clientHeight - event.clientY const distanceToRight = document.documentElement.clientWidth - event.clientX if (distanceToBottom < containerHeight) { - e.top = event.clientY - containerHeight + e.top = event.clientY - (containerHeight - distanceToBottom) } if (distanceToRight < containerWidth) { - e.left = event.clientX - containerWidth + e.left = event.clientX - containerWidth + 8 } @@ -3896,6 +3901,15 @@ export default { // 返回原处 this.restoreFile() 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() }, @@ -4769,6 +4783,9 @@ export default { if (this.shareDialogVisible) { return true } + if (this.directLinkDialogVisible) { + return true + } if (this.tagDialogVisible) { return true } diff --git a/src/components/VContextmenu/file-contextmenu.vue b/src/components/VContextmenu/file-contextmenu.vue index 68e8b4e..1433cb9 100644 --- a/src/components/VContextmenu/file-contextmenu.vue +++ b/src/components/VContextmenu/file-contextmenu.vue @@ -124,7 +124,7 @@ export default { padding: 0 10px; display: flex; align-items: center; - justify-content: space-between; + justify-content: flex-start; >>> .svg-icon { margin-right: 10px; diff --git a/src/utils/copy-text.js b/src/utils/copy-text.js new file mode 100644 index 0000000..33acca2 --- /dev/null +++ b/src/utils/copy-text.js @@ -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); +} diff --git a/src/utils/file-config.js b/src/utils/file-config.js index a456e4b..c23424c 100644 --- a/src/utils/file-config.js +++ b/src/utils/file-config.js @@ -143,4 +143,11 @@ export default { } 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}` + } + } } diff --git a/src/utils/file-operations.js b/src/utils/file-operations.js index ee53f6f..0fba291 100644 --- a/src/utils/file-operations.js +++ b/src/utils/file-operations.js @@ -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 = [ { label: '名称', operation: 'orderName', orderProp: 'name'}, { label: '大小', operation: 'orderSize', orderProp: 'size'},