Преглед изворни кода

✨ feat: 新增商品中心--商品列表页面

WanGxC пре 1 година
родитељ
комит
e09ea73bd5

+ 11 - 4
package-lock.json

@@ -7611,12 +7611,19 @@
 			}
 		},
 		"vxe-table": {
-			"version": "4.5.12",
-			"resolved": "https://registry.npmmirror.com/vxe-table/-/vxe-table-4.5.12.tgz",
-			"integrity": "sha512-eFLzujF+PcpKmd8LpuKOvmyZfVIKKB8q5w/9P1/D392D7NMuCFDDY+HRIYIo889sZMQzUjEb8oNkYvFjHqEFDw==",
+			"version": "4.5.20",
+			"resolved": "https://registry.npmmirror.com/vxe-table/-/vxe-table-4.5.20.tgz",
+			"integrity": "sha512-UC+z1ED3QE6Be/UN0390hSXMAseXg+com3fkX9q3tjfsCGFx7CjN9tLstuNtecn+ElkPGHqzRGtA3N5FTSv5Vw==",
 			"requires": {
 				"dom-zindex": "^1.0.1",
-				"xe-utils": "^3.5.13"
+				"xe-utils": "^3.5.20"
+			},
+			"dependencies": {
+				"xe-utils": {
+					"version": "3.5.20",
+					"resolved": "https://registry.npmmirror.com/xe-utils/-/xe-utils-3.5.20.tgz",
+					"integrity": "sha512-dZewCp04O0xQ4JnUxlvRfxsBlV1vxrA9LCazGAFFeRWoTj0DU70OpqUNd8is1GnJXUL4ineZ4nywrEq/3Mbybg=="
+				}
 			}
 		},
 		"webpack-sources": {

+ 1 - 1
package.json

@@ -52,7 +52,7 @@
 		"vue-grid-layout": "^3.0.0-beta1",
 		"vue-i18n": "^9.2.2",
 		"vue-router": "^4.1.6",
-		"vxe-table": "^4.4.1",
+		"vxe-table": "^4.5.20",
 		"xe-utils": "^3.5.7"
 	},
 	"devDependencies": {

+ 33 - 7
src/views/demo/index.vue

@@ -6,16 +6,37 @@
     v-model:file-list="fileList"
     action="#"
     method="post"
-    :data="{profileId: 'xxxx'}"
+    :data="{ profileId: 'xxxx' }"
     multiple
     :on-progress="onProgress"
     :auto-upload="true"
     :on-success="onSuccess"
-    :http-request="submit"
-    >
+    :http-request="submit">
     <el-button type="primary">Click to upload</el-button>
   </el-upload>
   <el-button @click="submit">上传</el-button>
+
+  <div style="padding: 0 12px">
+    <div style="display: inline-block; width: 10%">
+      <el-card shadow="never"> qweqweqwe </el-card>
+    </div>
+    <div style="display: inline-block; width: 90%">
+      <div style="display: flex; justify-content: flex-end; align-items: center">
+        <el-button>确定</el-button>
+        <el-button>确定</el-button>
+        <el-button>确定</el-button>
+        <el-button>确定</el-button>
+      </div>
+      <div>
+        <vxe-table round :data="tableData">
+          <vxe-column resizable type="seq" width="60"></vxe-column>
+          <vxe-column resizable field="name" title="Name"></vxe-column>
+          <vxe-column resizable field="sex" title="Sex"></vxe-column>
+          <vxe-column resizable field="age" title="Age"></vxe-column>
+        </vxe-table>
+      </div>
+    </div>
+  </div>
 </template>
 
 <script lang="ts" setup>
@@ -26,7 +47,12 @@ import { createCrudOptions } from './crud'
 import { request } from '/@/utils/service'
 
 import type { UploadProps, UploadUserFile, UploadFile, UploadFiles, UploadProgressEvent } from 'element-plus'
-
+const tableData = ref([
+  { id: 10001, name: 'Test1', role: 'Develop', sex: 'Man', age: 28, address: 'test abc' },
+  { id: 10002, name: 'Test2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
+  { id: 10003, name: 'Test3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' },
+  { id: 10004, name: 'Test4', role: 'Designer', sex: 'Women', age: 24, address: 'Shanghai' },
+])
 const fileList = ref<UploadUserFile[]>([])
 const onProgress = (evt: UploadProgressEvent, uploadFile: UploadFile, uploadFiles: UploadFiles) => {
   console.log(evt)
@@ -39,16 +65,16 @@ const onSuccess = (response: any, uploadFile: UploadFile, uploadFiles: UploadFil
 }
 
 const submit = () => {
-  const formData = new FormData();
+  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'
+      'Content-Type': 'multipart/form-data',
     },
     method: 'post',
-    data: formData
+    data: formData,
   })
 }
 

+ 0 - 0
src/views/productCenter/productAnalyze/index.vue


+ 37 - 0
src/views/productCenter/productList/api.ts

@@ -0,0 +1,37 @@
+import { request } from '/@/utils/service'
+import { UserPageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud'
+
+export const apiPrefix = '/api/ad_manage/sbcampaigns/'
+export function getCardData(query: UserPageQuery) {
+  return request({
+    url: apiPrefix + 'total/',
+    method: 'GET',
+    params: query,
+  })
+}
+export function getLineData(query: UserPageQuery) {
+  query['dateRangeType'] = 'D'
+  return request({
+    url: apiPrefix + 'daily/',
+    method: 'GET',
+    params: query,
+  })
+}
+
+export function getLineWeekData(query: UserPageQuery) {
+  query['dateRangeType'] = 'W'
+  return request({
+    url: apiPrefix + 'daily/',
+    method: 'GET',
+    params: query,
+  })
+}
+
+export function getLineMonthData(query: UserPageQuery) {
+  query['dateRangeType'] = 'M'
+  return request({
+    url: apiPrefix + 'daily/',
+    method: 'GET',
+    params: query,
+  })
+}

+ 241 - 0
src/views/productCenter/productList/crud.tsx

@@ -0,0 +1,241 @@
+import * as api from './api'
+import {AddReq, CreateCrudOptionsProps, CreateCrudOptionsRet, DelReq, dict, EditReq, UserPageQuery} from '@fast-crud/fast-crud'
+import {inject} from 'vue'
+import {SbBaseColumn} from '/@/views/adManage/utils/commonTabColumn.js'
+import {parseQueryParams} from '/@/views/adManage/utils/tools.js'
+import XEUtils from 'xe-utils'
+import { useRouter } from 'vue-router'
+
+export const createCrudOptions = function ({crudExpose, context}: CreateCrudOptionsProps): CreateCrudOptionsRet {
+  const pageRequest = async (query: UserPageQuery) => {
+    const params = parseQueryParams(context.value)
+    XEUtils.assign(query, params)
+    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)
+  }
+
+  const router = useRouter()
+
+  //权限判定
+  const hasPermissions = inject('$hasPermissions')
+
+  return {
+    crudOptions: {
+      table: {
+        height: 800,
+        headerCellStyle: {
+          backgroundColor: '#f6f7fa', // 直接设置背景颜色
+          height: '20px',
+          borderRight: 'none'
+        },
+        cellStyle: {
+          border: 'none',
+          borderBottom: '0.5px solid #ddd',
+        },
+        stripe: false,
+        showSummary: true,
+      },
+      container: {
+        fixedHeight: false
+      },
+      // actionbar: {
+      //   show: true,
+      //   color: "#626aef",
+      //   buttons: {
+      //     add: {
+      //       show: false
+      //     },
+      //     create: {
+      //       text: '新建广告活动',
+      //       // type: 'primary',
+      //       color: "#626aef",
+      //       plain: true,
+      //       show: true,
+      //       click() {
+
+      //       }
+      //     },
+      //   }
+      // },
+      actionbar: {
+        show: true,
+        buttons: {
+          add: {
+            show: false,
+          },
+          create: {
+            text: '新建广告活动',
+            type: 'primary',
+            show: true,
+            color: "#626aef",
+            plain: true,
+            click() {
+              router.push({
+                name: 'SbCreateCampaigns',
+                query: { campaignId: 123, tagsViewName: '新建广告活动' },
+              })
+            
+            },
+          },
+        },
+      },
+      search: {
+        show: false
+      },
+      toolbar: {
+        buttons: {
+          search: {
+            show: true
+          },
+          compact: {
+            show: false
+          }
+        }
+      },
+      request: {
+        pageRequest,
+        addRequest,
+        editRequest,
+        delRequest,
+      },
+      rowHandle: {
+        fixed: 'right',
+        width: 100,
+        align: 'center',
+        buttons: {
+          view: {
+            show: false,
+          },
+          edit: {
+            iconRight: 'Edit',
+            type: 'text',
+            text: null
+            // show: hasPermissions('dictionary:Update'),
+          },
+          remove: {
+            show: false
+            // iconRight: 'Delete',
+            // type: 'text',
+            // text: null
+            // show: hasPermissions('dictionary:Delete'),
+          },
+        },
+      },
+      columns: {
+        id: {
+          title: 'ID',
+          column: {
+            show: false
+          },
+          form: {
+            show: false
+          }
+        },
+        campaignName: {
+          title: '广告活动名称',
+          sortable: true,
+          column: {
+            fixed: 'left',
+            width: 180,
+            // showOverflowTooltip: true,
+          },
+        },
+        state: {
+          title: '状态',
+          sortable: true,
+          column: {
+            width: '90px',
+            align: 'center'
+          },
+          type: 'dict-select',
+          search: {
+            show: true
+          },
+          dict: dict({
+            data: [
+              {value: 'PAUSED', label: '已暂停', color: 'warning'},
+              {value: 'ENABLED', label: '投放中', color: 'success'},
+            ]
+          })
+        },
+        bidOptimization: {
+          title: '竞价',
+          form: {
+            show: false,
+          },
+          column: {
+            width: '100px',
+            sortable: true,
+            align: 'center',
+            formatter: (row) => {
+              switch (row.value) {
+                case 1:
+                  return '自动竞价'
+                case 0:
+                  return '自定义竞价'
+                default:
+                  return '-'
+              }
+            }
+          },
+        },
+        startDate: {
+          title: '开始日期',
+          column: {
+            width: '120px',
+            align: 'center',
+            sortable: true,
+          },
+        },
+        endDate: {
+          title: '结束日期',
+          column: {
+            width: '120px',
+            align: 'center',
+            sortable: true,
+            formatter: (row) => {
+              if (row.value !== null) {
+                return row.value
+              } else {
+                return '--'
+              }
+            }
+          },
+        },
+        portfolioName: {
+          title: '广告组合',
+          type: 'text',
+          column: {
+            width: '120px',
+            align: 'center',
+            formatter: (row) => {
+              if (row.value !== null) {
+                return row.value
+              } else {
+                return '--'
+              }
+            }
+          }
+        },
+        dailyBudget: {
+          title: '预算',
+          column: {
+            sortable: true,
+            width: '120px',
+            align: 'right',
+          }
+        },
+        ...SbBaseColumn
+      }
+    }
+  }
+}

+ 131 - 0
src/views/productCenter/productList/index.vue

@@ -0,0 +1,131 @@
+<template>
+  <div class="outer-container">
+    <div class="filters">
+      <el-input placeholder="ASIN/父ASIN/标题/SKU"></el-input>
+      <el-select style="width: 300px"></el-select>
+      <DateRangePicker v-model="dateRange"></DateRangePicker>
+    </div>
+    <div class="table-tips">
+      <el-icon><Warning /></el-icon>
+      <p style="margin-left: 3px">商品中心广告数据统计不包含SB广告</p>
+    </div>
+    <el-card>
+      <DataTendencyChart
+        :query="queryParams"
+        :fetchCard="getCardData"
+        :fetchLine="getLineData"
+        :fetch-line-month="getLineMonthData"
+        :fetch-line-week="getLineWeekData">
+      </DataTendencyChart>
+    </el-card>
+  </div>
+
+  <div style="width: 100%; padding: 12px">
+    <el-scrollbar>
+      <div class="scrollbar-flex-content">
+        <el-card v-for="item in 50" :key="item" class="scrollbar-demo-item">
+          {{ item }}
+        </el-card>
+      </div>
+    </el-scrollbar>
+  </div>
+
+  <div class="pl-and-asin-tables">
+    <div class="asin-table-container">
+      <div class="xp-radio-group-wrapper">
+        <el-button-group>
+          <el-button bg pain>产品线</el-button>
+          <el-button bg pain>父ASIN</el-button>
+          <el-button bg pain>ASIN</el-button>
+          <el-button bg pain>SKU</el-button>
+        </el-button-group>
+      </div>
+      <div style="width: auto">
+        <el-table :data="tableData">
+          <el-table-column prop="date" label="Date" />
+          <el-table-column prop="name" label="Name" />
+          <el-table-column prop="address" label="Address" />
+        </el-table>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { storeToRefs } from 'pinia'
+import { usePublicData } from '/@/stores/publicData'
+import DateRangePicker from '/@/components/DateRangePicker/index.vue'
+import DataTendencyChart from '/@/views/adManage/sb/chartComponents/dataTendency.vue'
+import { useShopInfo } from '/@/stores/shopInfo'
+import { getCardData, getLineData, getLineMonthData, getLineWeekData } from './api'
+import { ref } from 'vue'
+
+const publicData = usePublicData()
+const { dateRange } = storeToRefs(publicData)
+const shopInfo = useShopInfo()
+const { profile } = storeToRefs(shopInfo)
+const queryParams = ref({
+  profileId: profile.value.profile_id,
+  dateRange,
+})
+
+const tableData = ref([
+  { id: 10001, name: 'Test1', role: 'Develop', sex: 'Man', age: 28, address: 'test abc' },
+  { id: 10002, name: 'Test2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
+  { id: 10003, name: 'Test3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' },
+  { id: 10004, name: 'Test4', role: 'Designer', sex: 'Women', age: 24, address: 'Shanghai' },
+])
+</script>
+
+<style scoped>
+.outer-container {
+  padding: 5px 10px 0 10px;
+}
+.filters {
+  display: flex;
+  justify-content: space-between;
+  gap: 10px;
+}
+.table-tips {
+  color: #8d9095;
+  display: flex;
+  align-items: center;
+  margin: 8px 0;
+}
+.pl-and-asin-tables {
+  padding: 10px 12px 0 12px;
+}
+.product-lines {
+  display: flex;
+}
+.asin-table-container {
+  width: 100%;
+  padding: 8px;
+  color: #4e5969;
+  background-color: #fff;
+  border-radius: 4px;
+  box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.06);
+}
+.xp-radio-group-wrapper {
+  display: flex;
+  justify-content: flex-end;
+  margin-bottom: 12px;
+  align-items: center;
+}
+.scrollbar-flex-content {
+  display: flex;
+}
+.scrollbar-demo-item {
+  flex-shrink: 0;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 100px;
+  height: 50px;
+  margin: 10px;
+  text-align: center;
+  border-radius: 4px;
+  background: var(--el-color-danger-light-9);
+  color: var(--el-color-danger);
+}
+</style>