Quellcode durchsuchen

✨ feat: 完善自动化条件参数

guojing_wu vor 1 Jahr
Ursprung
Commit
7d0f9aab61

+ 1 - 1
src/components/conditionBuilder/condition-group2.vue

@@ -44,7 +44,7 @@
               </el-option>
             </el-select>
             <template v-if="conditionInfo.symbol === 'in' || conditionInfo.symbol === 'not_in'">
-              <el-select v-if="getFieldInfo(conditionInfo.dataType).options" v-model="conditionInfo.values" multiple>
+              <el-select v-if="getFieldInfo(conditionInfo.dataType).options" v-model="conditionInfo.values" multiple collapse-tags>
                 <el-option
                   v-for="info in getFieldInfo(conditionInfo.dataType).options"
                   :label="info.label"

+ 6 - 1
src/components/conditionBuilder/index.vue

@@ -33,8 +33,13 @@ const props = withDefaults(defineProps<Props>(), {
     return [
       { label: '曝光量', value: 'impressions' },
       { label: '点击量', value: 'clicks' },
-      { label: '转化率', value: 'cr', suffix: '%' },
+      { label: '花费', value: 'spend', prefix: '$' },
+      { label: '点击率', value: 'ctr', suffix: '%' },
       { label: '单次点击费用', value: 'cpc', prefix: '$' },
+      { label: '转化率', value: 'cr', suffix: '%' },
+      { label: '广告订单数', value: 'order' },
+      { label: '广告销售额', value: 'sale', prefix: '$' },
+      { label: 'ACOS', value: 'acos', suffix: '%' }
     ]
   },
 })

+ 2 - 2
src/stores/themeConfig.ts

@@ -137,9 +137,9 @@ export const useThemeConfig = defineStore('themeConfig', {
 			 * 全局网站标题 / 副标题
 			 */
 			// 网站主标题(菜单导航、浏览器当前网页标题)
-			globalTitle: 'DVAdmin',
+			globalTitle: 'Ansjer',
 			// 网站副标题(登录页顶部文字)
-			globalViceTitle: 'DVAdmin',
+			globalViceTitle: 'Ansjer',
 			// 网站副标题(登录页顶部文字)
 			globalViceTitleMsg: '广告管理系统',
 			// 默认初始语言,可选值"<zh-cn|en|zh-tw>",默认 zh-cn

+ 45 - 27
src/views/authorization/api.ts

@@ -1,42 +1,60 @@
-import { request } from '/@/utils/service';
-import { PageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud';
-import XEUtils from 'xe-utils';
+import { request } from '/@/utils/service'
+import { PageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud'
+import XEUtils from 'xe-utils'
 
-export const apiPrefix = '/api/ad_manage/';
+export const apiPrefix = '/api/ad_manage/auth_manage/'
 export function GetList(query: PageQuery) {
-    return request({
-        url: apiPrefix,
-        method: 'get',
-        params: query,
-    })
+  return request({
+    url: apiPrefix,
+    method: 'get',
+    params: query,
+  })
 }
 export function GetObj(id: InfoReq) {
-    return request({
-        url: apiPrefix + id,
-        method: 'get',
-    });
+  return request({
+    url: apiPrefix + id,
+    method: 'get',
+  })
 }
 
 export function AddObj(obj: AddReq) {
-    return request({
-        url: apiPrefix,
-        method: 'post',
-        data: obj,
-    });
+  return request({
+    url: apiPrefix,
+    method: 'post',
+    data: obj,
+  })
 }
 
 export function UpdateObj(obj: EditReq) {
-    return request({
-        url: apiPrefix + obj.id + '/',
-        method: 'put',
-        data: obj,
-    });
+  return request({
+    url: apiPrefix + obj.id + '/',
+    method: 'put',
+    data: obj,
+  })
 }
 
 export function DelObj(id: DelReq) {
+  return request({
+    url: apiPrefix + id + '/',
+    method: 'delete',
+    data: { id },
+  })
+}
+
+export function genAdAuthLink(obj: any) {
     return request({
-        url: apiPrefix + id + '/',
-        method: 'delete',
-        data: { id },
-    });
+        url: '/api/ad_manage/auth/gen_adauth/',
+        method: 'post',
+        data: obj
+    })
+}
+
+export function genSpAuthLink(auth_manage_id: number) {
+    return request({
+        url: '/api/ad_manage/auth/gen_adauth/',
+        method: 'post',
+        data: {
+            auth_manage_id: auth_manage_id
+        }
+    })
 }

+ 146 - 143
src/views/authorization/crud.tsx

@@ -1,150 +1,153 @@
 import * as api from './api'
-import {dict, UserPageQuery, AddReq, DelReq, EditReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet} from '@fast-crud/fast-crud'
-import {inject, nextTick, ref} from 'vue'
-import {BaseColumn} from '/@/views/adManage/utils/commonTabColumn.js'
-import {useRouter} from 'vue-router'
+import { dict, UserPageQuery, AddReq, DelReq, EditReq, compute, CreateCrudOptionsProps, CreateCrudOptionsRet } from '@fast-crud/fast-crud'
+import { inject, nextTick, ref } from 'vue'
+import { useCompute } from '@fast-crud/fast-crud'
 
-export const createCrudOptions = function ({crudExpose, context}: CreateCrudOptionsProps): CreateCrudOptionsRet {
-	const pageRequest = async (query: UserPageQuery) => {
-		return await api.GetList(query)
-	}
-	const editRequest = async ({form, row}: EditReq) => {
-		form.id = row.id
-		return await api.UpdateObj(form)
-	}
-	const delRequest = async ({row}: DelReq) => {
-		return await api.DelObj(row.id)
-	}
-	const addRequest = async ({form}: AddReq) => {
-		return await api.AddObj(form)
-	}
+export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
+	const { showDialog } = context
 
-	//权限判定
-	const hasPermissions = inject('$hasPermissions')
+  const pageRequest = async (query: UserPageQuery) => {
+    return await api.GetList(query)
+  }
+  const editRequest = async ({ form, row }: EditReq) => {
+    form.id = row.id
+    return await api.UpdateObj(form)
+  }
+  const delRequest = async ({ row }: DelReq) => {
+    return await api.DelObj(row.id)
+  }
+  const addRequest = async ({ form }: AddReq) => {
+    return await api.AddObj(form)
+  }
 
-	// todo 点击新建广告活动进行路由跳转(还有问题)
-	const router = useRouter()
+  //权限判定
+  const hasPermissions = inject('$hasPermissions')
+  const { compute } = useCompute()
 
-	function goCreate() {
-		router.push('/createcampaigns')
-	}
-
-	return {
-		crudOptions: {
-			table: {
-				height: 800
-			},
-			container: {
-				fixedHeight: false
-			},
-			actionbar: {
-				show: true,
-				buttons: {
-					add: {
-						text: 'xxx',
-						show: false
-					},
-					create: {
-						text: '新建广告活动',
-						type: 'primary',
-						show: true,
-						click() {
-							goCreate()
-						}
-					}
-				}
-			},
-			search: {
-				show: false
-			},
-			toolbar: {
-				buttons: {
-					search: {
-						show: true
-					},
-					compact: {
-						show: false
-					}
-				}
-			},
-			request: {
-				pageRequest,
-				addRequest,
-				editRequest,
-				delRequest,
-			},
-			rowHandle: {
-				fixed: 'right',
-				width: 80,
-				buttons: {
-					view: {
-						show: false,
-					},
-					edit: {
-						iconRight: 'Edit',
-						type: 'text',
-						text: null
-						// show: hasPermissions('dictionary:Update'),
-					},
-					remove: {
-						iconRight: 'Delete',
-						type: 'text',
-						text: null
-						// show: hasPermissions('dictionary:Delete'),
-					},
-				},
-			},
-			columns: {
-				campaignName: {
-					title: '广告活动',
-					column: {
-						width: '150px'
-					},
-					search: {
-						show: true,
-						component: {
-							props: {
-								clearable: true
-							}
+  return {
+    crudOptions: {
+      table: {
+        height: 800,
+      },
+      container: {
+        fixedHeight: false,
+      },
+      actionbar: {
+        show: true,
+        buttons: {
+          add: {
+            text: 'xxx',
+            show: false,
+          },
+          create: {
+            text: '添加店铺',
+            type: 'primary',
+            show: true,
+            click() {
+							showDialog('ad')
+            }
+          },
+        },
+      },
+      search: {
+        show: false,
+      },
+      toolbar: {
+        buttons: {
+          search: {
+            show: true,
+          },
+          compact: {
+            show: false,
+          },
+        },
+      },
+      request: {
+        pageRequest,
+        addRequest,
+        editRequest,
+        delRequest,
+      },
+      rowHandle: {
+        fixed: 'right',
+        width: 80,
+        buttons: {
+          view: {
+            show: false,
+          },
+          edit: {
+            iconRight: 'Edit',
+            type: 'text',
+            text: null,
+            show: false,
+          },
+          remove: {
+            iconRight: 'Delete',
+            type: 'text',
+            text: null,
+            show: false,
+          },
+          custom: {
+            type: 'text',
+            text: 'SP授权',
+            disabled: compute((context: any) => {
+              return context.row.ad_auth === 1 && context.row.sp_auth === 1
+            }),
+						click(context: any) {
+							showDialog('sp', context.row)
 						}
-					},
-					form: {
-						rules: [{required: true, message: '必填项'}]
-					}
-				},
-				// targetingType: {
-				// 	title: '投放类型',
-				// 	type: 'dict-select',
-				// 	search: {
-				// 		show: true
-				// 	},
-				// 	dict: dict({
-				// 		data: [
-				// 			{ value: 'AUTO', label: '自动' },
-				// 			{ value: 'MANUAL', label: '手动' },
-				// 		]
-				// 	})
-				// },
-				state: {
-					title: '状态'
-				},
-				// state: {
-				//     title: '竞价'
-				// },
-				startDate: {
-					title: '开始日期'
-				},
-				endDate: {
-					title: '结束日期'
-				},
-				portfolio: {
-					title: '广告组合'
-				},
-				budget: {
-					title: '预算'
-				},
-				...BaseColumn
-			}
-		}
-	}
+          },
+        },
+      },
+      columns: {
+        custom_shop_name: {
+          title: '亚马逊店铺名称',
+        },
+        advertiser_id: {
+          title: '店铺ID',
+        },
+        region: {
+          title: '区域',
+          type: 'dict-select',
+          dict: dict({
+            data: [
+              { label: '北美洲', value: 1 },
+              { label: '欧洲', value: 2 },
+              { label: '亚洲', value: 3 },
+            ],
+          }),
+        },
+        country_code: {
+          title: '站点',
+        },
+        type: {
+          title: '店铺类型',
+        },
+        ad_auth: {
+          title: '广告API授权',
+          column: {
+            cellRender(scope) {
+              if (scope.value === 1) return <span style="color: green">已授权</span>
+              return <span style="color: red">未授权</span>
+            },
+          },
+        },
+        sp_auth: {
+          title: 'SP-API授权',
+          column: {
+            cellRender(scope) {
+              if (scope.value === 1) return <span style="color: green">已授权</span>
+              return <span style="color: red">未授权</span>
+            },
+          },
+        },
+        // creator: {
+        // 	title: '授权人'
+        // },
+        // email: {
+        // 	title: '授权人邮箱'
+        // }
+      },
+    },
+  }
 }

+ 80 - 18
src/views/authorization/index.vue

@@ -1,30 +1,92 @@
 <template>
-    <fs-page class="fs-page-custom">
-        <fs-crud ref="crudRef" v-bind="crudBinding">
-            <template #header-middle>
-
-            </template>
-        </fs-crud>
-    </fs-page>
+  <fs-page class="fs-page-custom">
+    <fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
+  </fs-page>
+  <el-dialog v-model="dialogVisible" :title="authType === 'ad' ? '广告授权' : 'SP授权'" width="45%" :destroy-on-close="true" center>
+    <el-form :model="formData" label-position="right" label-width="100px" :disabled="formDisabeld">
+      <el-form-item label="亚马逊店铺" prop="custom_shop_name" :rules="{ required: true, message: '必填项', trigger: 'blur' }">
+        <el-input v-model="formData.custom_shop_name"></el-input>
+      </el-form-item>
+      <el-form-item label="区域">
+        <el-select v-model="formData.region">
+          <el-option label="北美" :value="1"></el-option>
+          <el-option label="欧洲" :value="2"></el-option>
+          <el-option label="远东" :value="3"></el-option>
+        </el-select>
+      </el-form-item>
+    </el-form>
+    <el-button type="primary" @click="genAuthLink" :disabled="formData.custom_shop_name === ''">生成授权链接</el-button>
+    <div v-show="authLink">
+      <el-divider />
+      <p>请复制下面的授权链接到店铺常用登入浏览器去授权:</p>
+      <el-text truncated>{{ authLink }}</el-text>
+      <el-button style="display: block" @click="copyLink">复制链接</el-button>
+    </div>
+  </el-dialog>
 </template>
 
-<script setup>
+<script lang="ts" setup>
 import { ref, onMounted, inject, nextTick } from 'vue'
 import { useFs, FsPage } from '@fast-crud/fast-crud'
 import { createCrudOptions } from './crud'
-import BarLineChart from '/@/components/echartsComponents/BarLineChart.vue'
-import PieBarChart from '/@/components/echartsComponents/PieBarChart.vue'
-import ScatterChart from '/@/components/echartsComponents/ScatterChart.vue'
-import MetricsCards from "/@/components/MetricsCards/index.vue"
+import useClipboard from 'vue-clipboard3'
+import { genAdAuthLink, genSpAuthLink } from './api'
+import { ElMessage } from 'element-plus'
+
+const { toClipboard } = useClipboard()
+const dialogVisible = ref(false)
+const formData = ref({
+  region: 1,
+  custom_shop_name: '',
+})
+const formDisabeld = ref(false)
+const authLink = ref('')
+const authType = ref('ad')
+let rowData = { id: 0 }
+const showDialog = (type: string, row: any) => {
+  authType.value = type
+  if (type === 'sp') {
+    formData.value.custom_shop_name = row.custom_shop_name
+    formData.value.region = row.region
+    rowData = row
+    formDisabeld.value = true
+  } else {
+    formData.value.custom_shop_name = ''
+    formData.value.region = 1
+    formDisabeld.value = false
+  }
+  authLink.value = ''
+  dialogVisible.value = true
+}
 
-const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: {} })
+const genAuthLink = async () => {
+  if (authType.value === 'ad') {
+    // const resp = await genAdAuthLink(formData.value)
+    // authLink.value = resp.data    
+    authLink.value = '广告授权'
+  } else if (authType.value === 'sp') {
+    // const resp = await genSpAuthLink(rowData.id)
+    // authLink.value = resp.data
+    authLink.value = 'SP授权'
+  }
+}
+const copyLink = async () => {
+  try {
+    await toClipboard(authLink.value)
+    ElMessage({
+      message: '复制成功!',
+      type: 'success',
+    })
+  } catch (e) {
+    ElMessage.error(e)
+  }
+}
+
+const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions, context: { showDialog } })
 
 onMounted(() => {
-    crudExpose.doRefresh()
+  crudExpose.doRefresh()
 })
-
 </script>
 
-<style scoped>
-
-</style>
+<style scoped></style>

+ 6 - 2
src/views/components/ad-group-select/index.vue

@@ -6,6 +6,8 @@
     :remote-method="searchAdGroupName"
     :style="{ width }"
     clearable
+    collapse-tags
+    :multiple="multiple"
     @change="changeAdGroup"
     placeholder="请选择广告组">
     <el-option v-for="info in adGroupList" :key="info.adGroupId" :label="info.adGroupName" :value="info.adGroupId"></el-option>
@@ -17,16 +19,18 @@ import { ref, onMounted, watch } from 'vue'
 import { getAdGroupList } from './api'
 
 interface Props {
-  modelValue: string
+  modelValue: string | string[]
   query: {
     profileId: string
     campaignType: string
     campaignId: string
   }
-  width: string
+  width: string,
+  multiple: boolean
 }
 const props = withDefaults(defineProps<Props>(), {
   width: '',
+  multiple: false
 })
 const adGroupId = ref(props.modelValue)
 const adGroupList = ref([])

+ 1 - 1
src/views/components/auto/auto-campaigns/target-rule.vue

@@ -7,7 +7,7 @@
         <template #label>
           <span class="asj-h3">生效对象</span>
         </template>
-        <TargetSelect mode="auto" :data="formData.rule" :useTmpl="formData.useTmpl"></TargetSelect>
+        <TargetSelect mode="auto" :data="formData.rule" :useTmpl="formData.useTmpl" :campaign-id="data.campaignId"></TargetSelect>
       </el-form-item>
     </el-form>
     <TargetRuleSetting :rule="formData.rule" ref="ruleSettingRef" :disabled="formData.useTmpl"/>

+ 1 - 13
src/views/components/auto/auto-templates/search-term.vue

@@ -33,20 +33,8 @@ interface Props {
   mode: string
   data: AutoTemplate
   submitFormData: Function
-  candidateFields: any[]
 }
-const props = withDefaults(defineProps<Props>(), {
-  candidateFields: () => {
-    return [
-      { label: '曝光量', value: 'impressions' },
-      { label: '点击量', value: 'clicks' },
-      { label: '转化率', value: 'cr', suffix: '%' },
-      { label: '单次点击费用', value: 'cpc', prefix: '$' },
-      { label: '关键词', value: 'keyword', type: 'array', options: [{ label: '精确匹配', value: 'exect' }] },
-      { label: '否定词', value: 'neg_keyword', type: 'array' },
-    ]
-  },
-})
+const props = defineProps<Props>()
 const emits = defineEmits(['refresh'])
 const formRef = ref()
 const condiBuilderRef = ref()

+ 1 - 8
src/views/components/auto/auto-templates/switch-campaign.vue

@@ -30,7 +30,7 @@
       </el-checkbox-group>
     </el-form>
     <div v-show="formData.rule.action.state.includes('paused')">
-      <conditionBuilder :data="formData.rule.conditions" :candidate-fields="condidateFields" ref="condiBuilderRef" />
+      <conditionBuilder :data="formData.rule.conditions" ref="condiBuilderRef" />
     </div>
   </div>
 
@@ -43,7 +43,6 @@
     <el-button style="width: 200px" @click="cancel">取消</el-button>
     <el-button style="width: 200px" type="primary" @click="submitForm">提交</el-button>
   </div>
-  <p>{{ formData }}</p>
 </template>
 
 <script lang="ts" setup>
@@ -73,12 +72,6 @@ const addConditions = () => {
   }
 }
 
-const condidateFields = [
-  { label: '曝光量', value: 'impressions' },
-  { label: '点击量', value: 'clicks' },
-  { label: '转化率', value: 'cr', suffix: '%' },
-  { label: '单次点击费用', value: 'cpc', prefix: '$' },
-]
 const validateConditionsForm = async () => {
   const validList = await condiBuilderRef.value.validate()
   if (validList.includes(false)) {

+ 21 - 5
src/views/components/auto/target-rule-setting.vue

@@ -82,23 +82,39 @@ const props = defineProps<Props>()
 const candidateFields = [
   { label: '曝光量', value: 'impressions' },
   { label: '点击量', value: 'clicks' },
-  { label: '转化率', value: 'cr', suffix: '%' },
+  { label: '花费', value: 'spend', prefix: '$' },
+  { label: '点击率', value: 'ctr', suffix: '%' },
   { label: '单次点击费用', value: 'cpc', prefix: '$' },
-  { label: '关键词', value: 'keyword', type: 'array', options: [{ label: '精确匹配', value: 'exect' }] },
-  { label: '否定词', value: 'neg_keyword', type: 'array' },
+  { label: '转化率', value: 'cr', suffix: '%' },
+  { label: '广告订单数', value: 'order' },
+  { label: '广告销售额', value: 'sale', prefix: '$' },
+  { label: 'ACOS', value: 'acos', suffix: '%' },
+  {
+    label: '定向匹配方式',
+    value: 'matchType',
+    type: 'array',
+    options: [
+      { label: '关键词-精确', value: 'exect' },
+      { label: '关键词-广泛', value: 'broad' },
+      { label: '关键词-词组', value: 'phrase' },
+      { label: '商品-品类', value: 'category' },
+      { label: '商品-单个商品', value: 'asin' },
+    ],
+  },
+  { label: '关键词名称', value: 'keywords', type: 'array' }
 ]
 const { getSymbolOptions } = useSymbolOptions(candidateFields)
 const ruleFormRef = ref()
 const condiBuilderRef = ref()
 const checkFloat = (rule: any, value: any, callback: any) => {
-  if (value === '0.00' || value === '') {
+  if (XEUtils.toNumber(value) <= 0) {
     callback(new Error('请输入大于0的数值!'))
   } else {
     callback()
   }
 }
 const checkMinMax = (rule: any, value: any, callback: any) => {
-  if (value === '0.00') {
+  if (XEUtils.toNumber(value) <= 0) {
     callback(new Error('请输入大于0的数值!'))
   } else {
     callback()

+ 12 - 6
src/views/components/auto/target-select.vue

@@ -1,6 +1,6 @@
 <template>
-  <div style="display: flex; flex-direction: column; align-items: center">
-    <div style="margin: 5px auto">
+  <div style="display: flex; flex-direction: column; align-items: flex-start">
+    <div style="margin: 5px 0">
       <span>广告类型:</span>
       <el-select v-model="data.campaignType" :disabled="mode==='edit' || useTmpl">
         <el-option label="SP" value="sp"></el-option>
@@ -13,9 +13,13 @@
         <el-radio label="campaign">当前广告活动(所有定向)</el-radio>
         <div class="target-radio-group-item">
           <el-radio label="adGroup">当前广告活动的指定广告组(所有定向)</el-radio>
-          <el-select style="margin-left: 23px" v-show="mode === 'auto' && data.activeModel === 'adGroup'" v-model="data.campaignAd">
-            <el-option label="111"></el-option>
-          </el-select>
+          <AdGroupSelect
+            v-show="mode === 'auto' && data.activeModel === 'adGroup'"
+            v-model="data.campaignAd"
+            style="padding-left: 23px;width: 450px;"
+            :multiple="true"
+            :query="{ profileId: '3006125408623189', campaignType: data.campaignType, campaignId: campaignId }">
+          </AdGroupSelect>
         </div>
         <div class="target-radio-group-item">
           <el-radio label="specified">指定定向</el-radio>
@@ -28,11 +32,13 @@
 
 <script lang="ts" setup>
 import { ref, watch } from 'vue'
+import AdGroupSelect from '/@/views/components/ad-group-select/index.vue'
 
 interface Props {
   mode: string,
   data: AutoRule,
-  useTmpl?: boolean
+  useTmpl?: boolean,
+  campaignId: string
 }
 const props = defineProps<Props>()
 </script>

+ 45 - 2
src/views/demo/index.vue

@@ -1,7 +1,21 @@
 <template>
-  <fs-page>
+  <!-- <fs-page>
     <fs-crud ref="crudRef" v-bind="crudBinding" />
-  </fs-page>
+  </fs-page> -->
+  <el-upload
+    v-model:file-list="fileList"
+    action="#"
+    method="post"
+    :data="{profileId: 'xxxx'}"
+    multiple
+    :on-progress="onProgress"
+    :auto-upload="true"
+    :on-success="onSuccess"
+    :http-request="submit"
+    >
+    <el-button type="primary">Click to upload</el-button>
+  </el-upload>
+  <el-button @click="submit">上传</el-button>
 </template>
 
 <script lang="ts" setup>
@@ -9,6 +23,35 @@ import { ref, onMounted } from 'vue'
 import { useFs } from '@fast-crud/fast-crud'
 import { createCrudOptions } from './crud'
 
+import { request } from '/@/utils/service'
+
+import type { UploadProps, UploadUserFile, UploadFile, UploadFiles, UploadProgressEvent } from 'element-plus'
+
+const fileList = ref<UploadUserFile[]>([])
+const onProgress = (evt: UploadProgressEvent, uploadFile: UploadFile, uploadFiles: UploadFiles) => {
+  console.log(evt)
+  console.log(uploadFile)
+}
+const onSuccess = (response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) => {
+  console.log(response)
+  console.log(uploadFile)
+  console.log(uploadFiles)
+}
+
+const submit = () => {
+  const formData = new FormData();
+  formData.append('file', fileList.value[0].raw)
+  formData.append('profileId', 'xxxx')
+  return request({
+    url: 'http://127.0.0.1:8003/api/amazon/assets/upload/',
+    headers: {
+      'Content-Type': 'multipart/form-data'
+    },
+    method: 'post',
+    data: formData
+  })
+}
+
 const { crudBinding, crudRef, crudExpose } = useFs({ createCrudOptions })
 
 onMounted(async () => {