index.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. <script setup lang="ts" name="Oss">
  2. import apis from "@a"
  3. import Rs from "@@/services/RequestService"
  4. import Config from "./_config.vue"
  5. import appStore from "@s"
  6. const serviceOptions = ref<any>([])
  7. const tableRef = ref()
  8. const modalRef = ref()
  9. const officePreviewRef = ref()
  10. const opts = reactive({
  11. columns: [
  12. { field: "ossId", name: "主键", width: 100, isSort: true, visible: false },
  13. { field: "originalName", name: "原名", visible: true, isSort: false, width: "auto" },
  14. { field: "fileSuffix", name: "文件后缀名", visible: true, isSort: false, width: 100 },
  15. { field: "url", name: "文件展示", visible: true, isSort: false, width: "auto" },
  16. { field: "service", name: "服务商", visible: true, isSort: false, width: 200 },
  17. { field: "createTime", name: "上传时间", visible: true, isSort: true, width: 185 },
  18. { field: "actions", name: `操作`, width: 150 }
  19. ] as any,
  20. queryParams: {
  21. fileName: undefined,
  22. originalName: undefined,
  23. service: undefined
  24. },
  25. searchFormItems: [
  26. {
  27. field: "fileName",
  28. label: "文件名",
  29. class: "w-100",
  30. required: false,
  31. placeholder: "请输入文件名",
  32. component: "I",
  33. listeners: {
  34. keyup: (e: KeyboardEvent) => {
  35. if (e.code == "Enter") {
  36. handleQuery()
  37. }
  38. }
  39. }
  40. },
  41. {
  42. field: "originalName",
  43. label: "原名",
  44. class: "w-100",
  45. required: false,
  46. placeholder: "请输入原名",
  47. component: "I",
  48. listeners: {
  49. keyup: (e: KeyboardEvent) => {
  50. if (e.code == "Enter") {
  51. handleQuery()
  52. }
  53. }
  54. }
  55. },
  56. {
  57. field: "service",
  58. label: "服务商",
  59. class: "w-100",
  60. required: false,
  61. component: "VS",
  62. placeholder: "请选择服务商",
  63. data: () => serviceOptions.value,
  64. props: {
  65. valueIsNumber: false,
  66. type: "select"
  67. }
  68. }
  69. ] as any,
  70. permission: "system:oss",
  71. handleBtns: [],
  72. handleFuns: {
  73. handleUpload,
  74. handleDelete,
  75. handleConfig
  76. },
  77. customBtns: [],
  78. tableListFun: apis.system.ossApi.list,
  79. getEntityFun: apis.system.ossApi.get,
  80. deleteEntityFun: apis.system.ossApi.del,
  81. exportUrl: apis.system.ossApi.exportUrl,
  82. exportName: "Oss",
  83. modalTitle: "文件上传",
  84. formItems: [
  85. {
  86. field: "uploadType",
  87. label: "上传类型",
  88. class: "w-100",
  89. required: true,
  90. placeholder: "请输入文件名",
  91. component: "VS",
  92. props: {
  93. type: "radio",
  94. data: [
  95. { label: "图片", value: "image" },
  96. { label: "文件", value: "file" }
  97. ]
  98. }
  99. },
  100. {
  101. show: () => {
  102. return form.value.uploadType == "file"
  103. },
  104. field: "s",
  105. label: "上传文件",
  106. class: "w-100",
  107. component: "VU",
  108. props: {
  109. uploadType: "file",
  110. uploadUrl: "",
  111. limit: 1,
  112. fileType: ["doc", "xls", "ppt", "txt", "pdf"]
  113. }
  114. },
  115. {
  116. show: () => {
  117. return form.value.uploadType == "image"
  118. },
  119. field: "s",
  120. label: "上传图片",
  121. class: "w-100",
  122. component: "VU",
  123. props: {
  124. prefixUrl: "/resource/oss/",
  125. uploadType: "image"
  126. },
  127. listeners: {
  128. delete: onDeleteFile
  129. }
  130. }
  131. ] as any,
  132. resetForm: () => {
  133. form.value = emptyFormData.value
  134. },
  135. labelWidth: "80px",
  136. emptyFormData: {
  137. uploadType: "image"
  138. }
  139. })
  140. const { queryParams, emptyFormData } = toRefs(opts)
  141. const form = ref<any>(emptyFormData.value)
  142. /** 搜索按钮操作 */
  143. function handleQuery(query?: any) {
  144. query = query || tableRef.value?.getQueryParams() || queryParams.value
  145. addDateRange(query, query.dateRangeCreateTime)
  146. addDateRange(query, query.dateRangeUpdateTime, "UpdateTime")
  147. tableRef.value?.query(query)
  148. }
  149. /** 重置按钮操作 */
  150. function resetQuery(query?: any) {
  151. query = query || tableRef.value?.getQueryParams() || queryParams.value
  152. query.dateRangeCreateTime = [] as any
  153. addDateRange(query, query.dateRangeCreateTime)
  154. query.dateRangeUpdateTime = [] as any
  155. addDateRange(query, query.dateRangeUpdateTime, "UpdateTime")
  156. //
  157. }
  158. /** 上传按钮操作 */
  159. function handleUpload() {
  160. opts.resetForm()
  161. modalRef.value.show()
  162. }
  163. /** 下载按钮操作 */
  164. function handleDownload(row: any) {
  165. Rs.download("/resource/oss/download/" + row.ossId, row.originalName)
  166. }
  167. /** 删除按钮操作 */
  168. function handleDelete(rows: any[]) {
  169. message.confirm("确认删除文件吗?删除后可能会影响部分页面的显示!", "删除文件").then(() => {
  170. const ids = rows.map((v: any) => v.ossId)
  171. apis.system.ossApi.del(ids).then(() => {
  172. handleQuery()
  173. })
  174. })
  175. }
  176. function handlePreviewOffice(row: any) {
  177. officePreviewRef.value.open({
  178. fileId: row.objectId,
  179. fileName: row.originalName
  180. })
  181. }
  182. function onDeleteFile(file: any) {
  183. console.log("delete", file)
  184. if (file.id) {
  185. apis.system.ossApi.del(file.id).then(() => {})
  186. }
  187. }
  188. function checkFileType(fileName: any) {
  189. if (!appStore.appConfigStore.isOssPreview()) {
  190. return false
  191. }
  192. const arr = fileName.split(".")
  193. const ext = arr[arr.length - 1]
  194. if (["png", "jpg", "jpeg"].some((item) => item === ext)) {
  195. return true
  196. }
  197. return false
  198. }
  199. const configModalRef = ref()
  200. const configViewRef = ref()
  201. function handleConfig() {
  202. configModalRef.value?.show()
  203. configViewRef.value?.query()
  204. }
  205. function getServiceOptions() {
  206. apis.system.ossConfigApi.list({ pageSize: 1000 }).then((res: any) => {
  207. serviceOptions.value = res.rows.map((item: any) => {
  208. return {
  209. label: item.configKey,
  210. value: item.configKey
  211. }
  212. })
  213. })
  214. }
  215. getServiceOptions()
  216. </script>
  217. <template>
  218. <div class="app-container">
  219. <VbTable
  220. ref="tableRef"
  221. keyField="ossId"
  222. :columns="opts.columns"
  223. :handle-perm="opts.permission"
  224. :handle-btns="opts.handleBtns"
  225. :handle-funs="opts.handleFuns"
  226. :search-form-items="opts.searchFormItems"
  227. :custom-btns="opts.customBtns"
  228. :remote-fun="opts.tableListFun"
  229. :get-entity-fun="opts.getEntityFun"
  230. :delete-entity-fun="opts.deleteEntityFun"
  231. :export-url="opts.exportUrl"
  232. :export-name="opts.exportName"
  233. :page-size="appStore.appConfigStore.isOssPreview() ? 10 : 15"
  234. :page-size-array="[appStore.appConfigStore.isOssPreview() ? 10 : 15, 25, 50]"
  235. :modal="modalRef"
  236. :reset-form-fun="opts.resetForm"
  237. v-model:form-data="form"
  238. v-model:query-params="queryParams"
  239. :check-multiple="true"
  240. :reset-search-form-fun="resetQuery"
  241. :custom-search-fun="handleQuery">
  242. <template #url="{ row }">
  243. <template v-if="checkFileType(row.originalName)">
  244. <VbImagePreview
  245. :src="row.objectId"
  246. :image-style="{ marginTop: '6px', marginBottom: '' }"></VbImagePreview>
  247. </template>
  248. <span v-else>
  249. <el-button size="small" type="primary" @click="handlePreviewOffice(row)">预览</el-button>
  250. </span>
  251. </template>
  252. <template #service="{ row }">
  253. <VbTag :data="serviceOptions" :value-is-number="false" :value="row.service"></VbTag>
  254. </template>
  255. <template #actions="{ row }">
  256. <vb-tooltip content="下载" placement="top">
  257. <el-button
  258. link
  259. type="primary"
  260. @click="handleDownload(row)"
  261. v-hasPermission="'system:oss:download'">
  262. <template #icon>
  263. <VbIcon icon-name="file-down" icon-type="duotone" class="fs-3"></VbIcon>
  264. </template>
  265. </el-button>
  266. </vb-tooltip>
  267. <vb-tooltip content="删除" placement="top">
  268. <el-button
  269. link
  270. type="primary"
  271. @click="handleDelete([row])"
  272. v-hasPermission="'system:oss:remove'">
  273. <template #icon>
  274. <VbIcon icon-name="trash-square" icon-type="duotone" class="fs-3"></VbIcon>
  275. </template>
  276. </el-button>
  277. </vb-tooltip>
  278. </template>
  279. </VbTable>
  280. <VbOfficePreview ref="officePreviewRef" />
  281. <VbModal
  282. v-model:modal="modalRef"
  283. :title="opts.modalTitle"
  284. :form-data="form"
  285. :form-items="opts.formItems"
  286. :form-label-width="opts.labelWidth"
  287. :close-btn="false"
  288. confirm-btn-text="关闭"
  289. append-to-body
  290. @confirm="handleQuery"></VbModal>
  291. <VbModal
  292. v-model:modal="configModalRef"
  293. title="文件服务器配置"
  294. modal-dialog-style="width:1600px;max-width:1600px;"
  295. modal-body-class="pt-0"
  296. append-to-body>
  297. <template #body>
  298. <Config ref="configViewRef"></Config>
  299. </template>
  300. </VbModal>
  301. </div>
  302. </template>