Browse Source

调整 文件管理,图片管理

王飞 1 year ago
parent
commit
d6b27dd54f

+ 4 - 0
src/api/common/index.ts

@@ -9,3 +9,7 @@ export const getDictApi = () => {
 export const getDictOneApi = async () => {
   return request.get({ url: '/dict/one' })
 }
+
+export const uploadFile = async (data: any) => {
+  return request.post({ url: '/api/sysApk/uploadFile', headersType: 'multipart/form-data', data })
+}

+ 1 - 0
src/config/axios/config.ts

@@ -108,6 +108,7 @@ const defaultResponseInterceptors = (response: AxiosResponse<any>) => {
           resetRouter() // 重置静态路由表
           router.replace('/login')
           isReLogin = false
+          location.reload()
         }
       })
     }

+ 37 - 25
src/views/Authorization/User/User.vue

@@ -3,7 +3,7 @@ import { ContentWrap } from '@/components/ContentWrap'
 import { useI18n } from '@/hooks/web/useI18n'
 import { Table } from '@/components/Table'
 import { ref, unref, watch, reactive, nextTick } from 'vue'
-import { ElButton, ElTree } from 'element-plus'
+import { ElButton, ElTree, ElTooltip, ElButtonGroup } from 'element-plus'
 import { getUserList, addUser, updataUser, deleteUserById, getRoleApi } from '@/api/department'
 import type { DepartmentUserItem } from '@/api/department/types'
 import { useTable } from '@/hooks/web/useTable'
@@ -12,6 +12,9 @@ import Write from './components/Write.vue'
 import Detail from './components/Detail.vue'
 import { Dialog } from '@/components/Dialog'
 import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas'
+import { useIcon } from '@/hooks/web/useIcon'
+const EditIcon = useIcon({ icon: 'ep:edit' })
+const DeleteIcon = useIcon({ icon: 'ep:delete' })
 
 const { t } = useI18n()
 
@@ -37,29 +40,16 @@ const { total, loading, dataList, pageSize, currentPage } = tableState
 const { getList, delList } = tableMethods
 
 const crudSchemas = reactive<CrudSchema[]>([
-  {
-    field: 'index',
-    label: t('userDemo.index'),
-    form: {
-      hidden: true
-    },
-    search: {
-      hidden: true
-    },
-    detail: {
-      hidden: true
-    },
-    table: {
-      type: 'index'
-    }
-  },
   {
     field: 'name',
     label: t('userDemo.username')
   },
   {
     field: 'account',
-    label: t('userDemo.account')
+    label: t('userDemo.account'),
+    search: {
+      hidden: true
+    }
   },
   {
     field: 'isActive',
@@ -73,6 +63,21 @@ const crudSchemas = reactive<CrudSchema[]>([
         activeValue: '1',
         inactiveValue: '0'
       }
+    },
+    search: {
+      component: 'Select',
+      componentProps: {
+        options: [
+          {
+            value: '1',
+            label: '启用'
+          },
+          {
+            value: '0',
+            label: '禁用'
+          }
+        ]
+      }
     }
   },
   {
@@ -163,19 +168,26 @@ const crudSchemas = reactive<CrudSchema[]>([
       hidden: true
     },
     table: {
-      width: 160,
+      width: 120,
       fixed: 'right',
       slots: {
         default: (data: any) => {
           const row = data.row as DepartmentUserItem
           return (
             <>
-              <ElButton type="primary" onClick={() => action(row, 'edit')}>
-                {t('exampleDemo.edit')}
-              </ElButton>
-              <ElButton type="danger" onClick={() => delData(row)}>
-                {t('exampleDemo.del')}
-              </ElButton>
+              <ElButtonGroup>
+                <ElTooltip content="编辑">
+                  <ElButton text icon={EditIcon} onClick={() => action(row, 'edit')} />
+                </ElTooltip>
+                <ElTooltip content="删除">
+                  <ElButton
+                    text
+                    icon={DeleteIcon}
+                    type="danger"
+                    onClick={() => delData(data.row)}
+                  />
+                </ElTooltip>
+              </ElButtonGroup>
             </>
           )
         }

+ 10 - 1
src/views/Manage/Company/CompanyPage.vue

@@ -23,6 +23,7 @@ import { CompanyData } from '@/api/manage/types'
 import Write from './components/Write.vue'
 import { useIcon } from '@/hooks/web/useIcon'
 import { Icon } from '@/components/Icon'
+import { uploadFile } from '@/api/common'
 
 defineOptions({
   name: 'CompanyPage'
@@ -216,7 +217,15 @@ const crudSchemas: CrudSchema[] = [
       },
       component: 'Upload',
       componentProps: {
-        action: '/api/sysApk/uploadFile',
+        httpRequest: (data: any) => {
+          let file = data.file
+          let formData = new FormData()
+          formData.append('file', file)
+          uploadFile(formData).then((response) => {
+            wechatImg.value = response.data.virtualPath
+            currentRow.value.wechatImg = response.data.virtualPath
+          })
+        },
         limit: 1,
         showFileList: false,
         class: 'companyUploader',

+ 18 - 8
src/views/Manage/File/FilePage.vue

@@ -18,6 +18,7 @@ import { FileData } from '@/api/manage/types'
 import Write from './components/Write.vue'
 import { useIcon } from '@/hooks/web/useIcon'
 import { Qrcode } from '@/components/Qrcode'
+import { uploadFile } from '@/api/common'
 defineOptions({
   name: 'FilePage'
 })
@@ -142,8 +143,19 @@ const crudSchemas: CrudSchema[] = [
       },
       component: 'Upload',
       componentProps: {
-        action: '/api/sysApk/uploadFile',
-        limit: 1,
+        httpRequest: (data: any) => {
+          delLoading.value = true
+          let file = data.file
+          let formData = new FormData()
+          formData.append('file', file)
+          uploadFile(formData).then((response) => {
+            currentRow.value = {
+              ...currentRow.value,
+              ...response.data
+            }
+            delLoading.value = false
+          })
+        },
         class: 'filePageUploader',
         fileList: currentRow.value.virtualPath
           ? [
@@ -160,12 +172,10 @@ const crudSchemas: CrudSchema[] = [
             ...currentRow.value,
             ...response.data
           }
-        },
-        onExceed: (_files, responses) => {
-          currentRow.value = {
-            ...currentRow.value,
-            ...responses[0].response.data
-          }
+          const write = unref(writeRef)
+          write?.setValues({
+            ...response.data
+          })
         },
         slots: {
           default: () => <ElButton type="primary">上传文件</ElButton>

+ 15 - 5
src/views/Manage/Img/ImgPage.vue

@@ -17,6 +17,7 @@ import { Dialog } from '@/components/Dialog'
 import { ImgData } from '@/api/manage/types'
 import Write from './components/Write.vue'
 import { useIcon } from '@/hooks/web/useIcon'
+import { uploadFile } from '@/api/common'
 import { Qrcode } from '@/components/Qrcode'
 defineOptions({
   name: 'ImgPage'
@@ -131,8 +132,20 @@ const crudSchemas: CrudSchema[] = [
       },
       component: 'Upload',
       componentProps: {
-        action: '/api/sysApk/uploadFile',
-        limit: 1,
+        httpRequest: (data: any) => {
+          delLoading.value = true
+          let file = data.file
+          let formData = new FormData()
+          formData.append('file', file)
+          uploadFile(formData).then((response) => {
+            currentRow.value.bannerUrl = response.data.virtualPath
+            const write = unref(writeRef)
+            write?.setValues({
+              bannerUrl: response.data.virtualPath
+            })
+            delLoading.value = false
+          })
+        },
         class: 'filePageUploader',
         fileList: currentRow.value.bannerUrl
           ? [
@@ -147,9 +160,6 @@ const crudSchemas: CrudSchema[] = [
         onSuccess: (response) => {
           currentRow.value.bannerUrl = response.data.virtualPath
         },
-        onExceed: (_files, responses) => {
-          currentRow.value.bannerUrl = responses[0].response.data.virtualPath
-        },
         slots: {
           default: () => <ElButton type="primary">上传文件</ElButton>
         }

+ 14 - 0
src/views/Manage/Img/components/Write.vue

@@ -46,6 +46,20 @@ watch(
   (currentRow) => {
     if (!currentRow) return
     setValues(currentRow)
+    setSchema([
+      {
+        field: 'bannerUrl',
+        path: 'componentProps.fileList',
+        value: props.currentRow?.bannerUrl
+          ? [
+              {
+                url: props.currentRow.bannerUrl,
+                name: props.currentRow.bannerUrl
+              }
+            ]
+          : []
+      }
+    ])
   },
   {
     deep: true,

+ 56 - 4
src/views/Manage/News/components/Write.vue

@@ -7,6 +7,7 @@ import { useValidator } from '@/hooks/web/useValidator'
 import { IDomEditor } from '@wangeditor/editor'
 import { useStorage } from '@/hooks/web/useStorage'
 import { Icon } from '@/components/Icon'
+import { uploadFile } from '@/api/common'
 const { required } = useValidator()
 const { getStorage } = useStorage()
 const props = defineProps({
@@ -48,6 +49,21 @@ const schema = reactive<FormSchema[]>([
       placeholder: '请输入'
     }
   },
+  {
+    field: 'date',
+    label: '日期范围',
+    component: 'DatePicker',
+    formItemProps: {
+      rules: [required()]
+    },
+    colProps: {
+      span: 24
+    },
+    componentProps: {
+      type: 'daterange',
+      placeholder: '请输入'
+    }
+  },
   {
     field: 'categoryId',
     label: '文章类目',
@@ -105,7 +121,17 @@ const schema = reactive<FormSchema[]>([
     component: 'Upload',
     label: '文章展图',
     componentProps: {
-      action: '/api/sysApk/uploadFile',
+      httpRequest: (data: any) => {
+        let file = data.file
+        let formData = new FormData()
+        formData.append('file', file)
+        uploadFile(formData).then((response) => {
+          setValues({
+            articlePic: response.data.virtualPath
+          })
+          articlePic.value = response.data.virtualPath
+        })
+      },
       showFileList: false,
       class: 'NewsUploader',
       headers: {
@@ -153,22 +179,38 @@ const schema = reactive<FormSchema[]>([
       editorConfig: {
         MENU_CONF: {
           uploadImage: {
-            server: '/api/sysApk/uploadFile',
             fieldName: 'file',
             headers: {
               token: getStorage('token')
             },
+            async customUpload(file: File, insertFn: InsertFnType) {
+              // 定义表单数据
+              let formData = new FormData()
+              formData.append('file', file)
+              // 上传文件
+              uploadFile(formData).then((res) => {
+                // 调用 insertFn 方法插入图片
+                insertFn(res.data.virtualPath, res.data.fileName, '')
+              })
+            },
             customInsert(res: any, insertFn: InsertFnType) {
               // 从 res 中找到 url alt href ,然后插入图片
               insertFn(res.data.virtualPath, res.fileName, '')
             }
           },
           uploadVideo: {
-            server: '/api/sysApk/uploadFile',
             fieldName: 'file',
             headers: {
               token: getStorage('token')
             },
+            async customUpload(file: File, insertFn: InsertFnType) {
+              let formData = new FormData()
+              formData.append('file', file)
+              uploadFile(formData).then((res) => {
+                // 将视频上传成功后的路径和文件名插入到指定位置
+                insertFn(res.data.virtualPath, res.data.fileName, '')
+              })
+            },
             customInsert(res: any, insertFn: InsertFnType) {
               // 从 res 中找到 url alt href ,然后插入视频
               insertFn(res.data.virtualPath, res.fileName, '')
@@ -188,13 +230,19 @@ const schema = reactive<FormSchema[]>([
 
 const rules = reactive({})
 
+// 定义一个submit函数,用于提交表单
 const submit = async () => {
+  // 获取表单元素
   const elForm = await getElFormExpose()
+  // 调用表单元素的validate方法,获取表单验证结果
   const valid = await elForm?.validate().catch((err) => {
+    // 如果表单验证失败,输出错误信息
     console.log(err)
   })
+  // 如果表单验证成功,获取表单数据
   if (valid) {
     const formData = await getFormData()
+    // 返回表单数据
     return formData
   }
 }
@@ -202,8 +250,11 @@ const submit = async () => {
 watch(
   () => props.currentRow,
   (currentRow) => {
+    // 如果当前行为空,则返回
     if (!currentRow) return
+    // 设置值
     setValues(currentRow)
+    // 设置模式
     setSchema([
       {
         field: 'articleContent',
@@ -211,6 +262,7 @@ watch(
         value: currentRow.articleContent
       }
     ])
+    // 设置图片
     articlePic.value = currentRow.articlePic
   },
   {
@@ -218,7 +270,6 @@ watch(
     immediate: true
   }
 )
-
 defineExpose({
   submit
 })
@@ -237,6 +288,7 @@ defineExpose({
 </style>
 
 <style lang="less">
+/**添加图片上传组件样式 */
 .NewsUploader .el-upload {
   border: 1px dashed var(--el-border-color);
   border-radius: 6px;

+ 26 - 3
src/views/Manage/Product/components/Write.vue

@@ -7,6 +7,7 @@ import { useValidator } from '@/hooks/web/useValidator'
 import { IDomEditor } from '@wangeditor/editor'
 import { useStorage } from '@/hooks/web/useStorage'
 import { Icon } from '@/components/Icon'
+import { uploadFile } from '@/api/common'
 const { required } = useValidator()
 const { getStorage } = useStorage()
 const props = defineProps({
@@ -82,7 +83,17 @@ const schema = reactive<FormSchema[]>([
     component: 'Upload',
     label: '产品图片',
     componentProps: {
-      action: '/api/sysApk/uploadFile',
+      httpRequest: (data: any) => {
+        let file = data.file
+        let formData = new FormData()
+        formData.append('file', file)
+        uploadFile(formData).then((response) => {
+          setValues({
+            productPic: response.data.virtualPath
+          })
+          productPic.value = response.data.virtualPath
+        })
+      },
       showFileList: false,
       class: 'productUploader',
       headers: {
@@ -129,7 +140,13 @@ const schema = reactive<FormSchema[]>([
       editorConfig: {
         MENU_CONF: {
           uploadImage: {
-            server: '/api/sysApk/uploadFile',
+            async customUpload(file: File, insertFn: InsertFnType) {
+              let formData = new FormData()
+              formData.append('file', file)
+              uploadFile(formData).then((res) => {
+                insertFn(res.data.virtualPath, res.data.fileName, '')
+              })
+            },
             fieldName: 'file',
             headers: {
               token: getStorage('token')
@@ -140,7 +157,13 @@ const schema = reactive<FormSchema[]>([
             }
           },
           uploadVideo: {
-            server: '/api/sysApk/uploadFile',
+            async customUpload(file: File, insertFn: InsertFnType) {
+              let formData = new FormData()
+              formData.append('file', file)
+              uploadFile(formData).then((res) => {
+                insertFn(res.data.virtualPath, res.data.fileName, '')
+              })
+            },
             fieldName: 'file',
             headers: {
               token: getStorage('token')

+ 11 - 11
vite.config.ts

@@ -6,7 +6,7 @@ import VueJsx from '@vitejs/plugin-vue-jsx'
 import progress from 'vite-plugin-progress'
 import EslintPlugin from 'vite-plugin-eslint'
 import { ViteEjsPlugin } from "vite-plugin-ejs"
-import { viteMockServe } from 'vite-plugin-mock'
+// import { viteMockServe } from 'vite-plugin-mock'
 import PurgeIcons from 'vite-plugin-purge-icons'
 import VueI18nPlugin from "@intlify/unplugin-vue-i18n/vite"
 import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
@@ -64,17 +64,17 @@ export default ({ command, mode }: ConfigEnv): UserConfig => {
         svgoOptions: true
       }),
       PurgeIcons(),
-      viteMockServe({
-        ignore: /^\_/,
-        mockPath: 'mock',
-        localEnabled: !isBuild,
-        prodEnabled: isBuild,
-        injectCode: `
-          import { setupProdMockServer } from '../mock/_createProductionServer'
+      // viteMockServe({
+      //   ignore: /^\_/,
+      //   mockPath: 'mock',
+      //   localEnabled: !isBuild,
+      //   prodEnabled: isBuild,
+      //   injectCode: `
+      //     import { setupProdMockServer } from '../mock/_createProductionServer'
 
-          setupProdMockServer()
-          `
-      }),
+      //     setupProdMockServer()
+      //     `
+      // }),
       DefineOptions(),
       ViteEjsPlugin({
         title: env.VITE_APP_TITLE