Parcourir la source

feat: 添加上传组件

王晓东 il y a 1 mois
Parent
commit
36ec32e24d

+ 3 - 1
src/api/index.ts

@@ -9,6 +9,8 @@ import type {
 const MAX_RETRY_COUNT = 3 // 最大重试次数
 const RETRY_DELAY = 1000 // 重试延迟时间(毫秒)
 
+export const BASE_URL = (import.meta.env.DEV && import.meta.env.VITE_OPEN_PROXY) ? '/proxy/' : import.meta.env.VITE_APP_API_BASEURL
+
 // 扩展 AxiosRequestConfig 类型
 declare module 'axios' {
   export interface AxiosRequestConfig {
@@ -18,7 +20,7 @@ declare module 'axios' {
 }
 
 const api = axios.create({
-  baseURL: (import.meta.env.DEV && import.meta.env.VITE_OPEN_PROXY) ? '/proxy/' : import.meta.env.VITE_APP_API_BASEURL,
+  baseURL: BASE_URL,
   timeout: 1000 * 60,
   responseType: 'json',
   headers: {

+ 1 - 1
src/api/modules/user.ts

@@ -1,5 +1,5 @@
 import api from '../index'
-
+import { request } from '@/api'
 export default {
   // 登录
   login: (data: {

+ 92 - 0
src/components/Uploader/FileUploader.vue

@@ -0,0 +1,92 @@
+<script setup lang="ts">
+import { ref, watch } from 'vue'
+import { Plus, Upload } from '@element-plus/icons-vue'
+import { ElButton, ElUpload, } from 'element-plus'
+import type {UploadProgressEvent, UploadFile, UploadFiles } from 'element-plus'
+import { toast } from 'vue-sonner'
+import { BASE_URL } from '@/api/index'
+
+
+const props = defineProps<{
+  // 外部传入的 "当前文件",可以是单个 UploadFile 对象,或 null,或 undefined
+  'modelValue'?: UploadFile | null | undefined
+  // 添加其他 props...
+}>()
+
+
+const emit = defineEmits<{
+  // 上传成功时 emit 事件
+  'success': [response: any, file: UploadFile, fileList: UploadFiles]
+  // 更新 v-model: 必须命名为 'update:modelValue' 以支持 v-model
+  'update:modelValue': [value: UploadFile | null]
+}>()
+
+
+const internalFileList = ref<UploadFiles>(props.modelValue ? [props.modelValue] : [])
+
+watch(
+  () => props.modelValue,
+  (newVal) => {
+    // 如果父组件的 modelValue 变为 null/undefined,清空内部列表
+    if (!newVal) {
+      internalFileList.value = []
+    } else {
+      // 如果有新值,更新(避免重复添加)
+      if (internalFileList.value[0]?.uid !== newVal.uid) {
+        internalFileList.value = [newVal]
+      }
+    }
+  }
+)
+
+const loading	 = ref(false)
+
+
+function handleUploadSuccess(response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) {
+  console.log('【上传成功】响应:', response)
+  console.log('【上传成功】文件对象:', uploadFile) // 这是最新的文件对象 (包含 url 等)
+  loading.value = false
+  emit('update:modelValue', uploadFile)
+
+  // 7. 触发成功事件
+  emit('success', response, uploadFile, uploadFiles)
+
+}
+
+// 8. 上传失败的回调
+function handleUploadError(error: Error, uploadFile: UploadFile, uploadFiles: UploadFiles) {
+  console.error('【上传失败】:', error, uploadFile)
+  emit('update:modelValue', null) // 失败时也通知父组件
+  toast.error('文件上传失败')
+}
+
+function handleProgress (evt: UploadProgressEvent, uploadFile: UploadFile, uploadFiles: UploadFiles) {
+  loading.value = true
+  console.log(evt, uploadFile, uploadFiles)
+}
+
+
+</script>
+
+<template>
+  <ElUpload
+    v-model:file-list="internalFileList"
+    :action="`${BASE_URL}/anycall/import`"
+    :show-file-list="false"
+    :headers="{
+      'accessToken': 'rcOBHJ0Hb8h5xgM/CWtNd8RBhA6WS4OPyJcxrxk4xPZtzeh5PtRXVDA7Um0NZA6NQmnbnZgWB0nNPb8iCrneQj4badFveWLrFq4LrySto3pIo/Zg1dJubbwmu3Vr1LCbSYyVIFrrgt9PXiA85kb9g38FSG3KTSi3AEY/UgjLNLBtH2+91YXKEy2KRZV3v75f'
+    }"
+    :limit="1"
+    @success="handleUploadSuccess"
+    @progress="handleProgress"
+    @error="handleUploadError"
+    :auto-upload="true"
+  >
+    <ElButton :loading="loading" type="primary" :icon="Upload">Import</ElButton>
+  </ElUpload>
+</template>
+
+<!-- 可选:添加 scoped style -->
+<style scoped>
+/* .your-style { ... } */
+</style>

+ 4 - 4
src/views/login.vue

@@ -7,8 +7,8 @@ meta:
 
 <script setup lang="ts">
 import LoginForm from '@/components/AccountForm/LoginForm.vue'
-import RegisterForm from '@/components/AccountForm/RegisterForm.vue'
-import ResetPasswordForm from '@/components/AccountForm/ResetPasswordForm.vue'
+// import RegisterForm from '@/components/AccountForm/RegisterForm.vue'
+// import ResetPasswordForm from '@/components/AccountForm/ResetPasswordForm.vue'
 import ColorScheme from '@/layouts/components/Topbar/Toolbar/ColorScheme/index.vue'
 
 defineOptions({
@@ -44,7 +44,7 @@ const formType = ref<'login' | 'register' | 'resetPassword'>('login')
           @on-register="(val) => { formType = 'register'; account = val }"
           @on-reset-password="(val) => { formType = 'resetPassword'; account = val }"
         />
-        <RegisterForm
+        <!-- <RegisterForm
           v-else-if="formType === 'register'"
           :account
           @on-register="(val) => { formType = 'login'; account = val }"
@@ -55,7 +55,7 @@ const formType = ref<'login' | 'register' | 'resetPassword'>('login')
           :account
           @on-reset-password="(val) => { formType = 'login'; account = val }"
           @on-login="formType = 'login'"
-        />
+        /> -->
       </Transition>
     </div>
   </div>

+ 15 - 3
src/views/role-management/index.vue

@@ -3,15 +3,19 @@
 defineOptions({
   name: 'Role Management',
 })
-import { Plus } from '@element-plus/icons-vue'
+
+import { Plus, Upload } from '@element-plus/icons-vue'
 import { ElButton, ElDialog, ElEmpty, ElInput, ElOption, ElPagination, ElSelect, ElTable, ElTableColumn, ElTag } from 'element-plus'
-// import SearchForm from './components/SearchForm.vue'
+import { toast } from 'vue-sonner'
+import FileUploader from '@/components/Uploader/FileUploader.vue'
 
 import type { TAgent } from '@/types/role'
 import { anycallPage } from '@/api/modules/anycallService'
 import { formatDateGeneral } from '@/utils'
 
 const tableRef = ref()
+const files1 = ref<FileItem[]>([])
+
 const loading = ref(false)
 const router = useRouter()
 const route = useRoute()
@@ -97,6 +101,9 @@ function handleReset () {
   fetchData()
 }
 
+function handleUploadSuccess(res:any, file) {
+  console.log(res, file, 333)
+}
 
 // 监听URL参数变化,用于处理浏览器后退/前进
 watch(
@@ -124,8 +131,13 @@ onMounted(async () => {
 
 <template>
   <div class="absolute-container">
-    <FaPageHeader title="Role Management" />
     <FaPageMain class="flex-1 overflow-auto" main-class="flex-1 flex flex-col overflow-auto">
+      <div class="pb-4">
+        <ElSpace>
+          <FileUploader @success="handleUploadSuccess" ></FileUploader>
+          <ElButton type="primary" :icon="Plus">Create Role</ElButton>
+        </ElSpace>
+      </div>
       <ElTable
         ref="tableRef" :data="dataList" stripe highlight-current-row border height="100%"
       >