123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452 |
- <template>
- <div prop="commodity" style="width: 100%" v-loading="productLoading">
- <div style="width: 100%; height: 620px; display: flex; border: 1px solid #e5e7ec; border-radius: 6px">
- <div style="width: 50%; border-right: 1px solid #e5e7ec">
- <el-tabs v-model="productTabs" class="demo-tabs">
- <el-tab-pane label="搜索" name="first">
- <div style="margin-bottom: 10px">
- <el-input v-model="searchInp" placeholder="Please input" class="input-with-select" @change="inpChange" clearable>
- <template #prepend>
- <el-select v-model="leftSelect" style="width: 100px" @change="selChange">
- <el-option label="名称" value="name" />
- <el-option label="ASIN" value="asin" />
- <el-option label="SKU" value="sku" />
- </el-select>
- </template>
- <template #append>
- <el-select v-model="rightSelect" style="width: 100px">
- <el-option label="最新优先" value="latest" />
- <el-option label="最早优先" value="earliest" />
- <el-option label="优选广告" value="optimal" />
- </el-select>
- </template>
- </el-input>
- </div>
- <el-table
- height="490"
- style="width: 100%"
- v-loading="loading"
- :data="productTableData"
- :header-cell-style="headerCellStyle"
- @selection-change="handleSelectionChange">
- <el-table-column type="selection" width="50" />
- <el-table-column prop="asin" label="商品">
- <template #default="scope">
- <div style="display: flex; align-items: center">
- <div style="margin-right: 8px; line-height: normal">
- <el-image class="img-box" :src="scope.row.image_link" />
- </div>
- <div>
- <el-tooltip class="box-item" effect="dark" :content="scope.row.title" placement="top">
- <div class="single-line">{{ scope.row.title ? scope.row.title : '--' }}</div>
- </el-tooltip>
- <div class="data-color">
- <span style="font-weight: 500; color: rgb(30, 33, 41)">${{ scope.row.price ? scope.row.price : '--' }}</span>
- <span style="margin: 0 5px; color: #cacdd4">|</span>
- <span style="color: #6d7784">{{ scope.row.quantity }}</span>
- </div>
- <span>
- ASIN: <span class="data-color" style="margin-right: 8px">{{ scope.row.asin ? scope.row.asin : '--' }}</span>
- </span>
- <span>
- SKU: <span class="data-color">{{ scope.row.sku ? scope.row.sku : '--' }}</span>
- </span>
- </div>
- </div>
- </template>
- </el-table-column>
- <el-table-column prop="name" label="Name" width="120" align="right">
- <template #header>
- <el-button type="primary" size="normal" link :disabled="addedTableData.length >= 1" @click="handleGoodsAdd">添加已选中</el-button>
- </template>
- <template #default="scope">
- <el-button type="primary" size="small" :disabled="addedTableData.length >= 1" @click="addSingleGoods(scope)" text>添加</el-button>
- </template>
- </el-table-column>
- </el-table>
- <el-pagination
- @current-change="handleCurrentChange"
- @size-change="handleSizeChange"
- :current-page="currentPage"
- :page-size="pageSize"
- :total="totalItems"
- layout="prev, pager, next" />
- </el-tab-pane>
- <el-tab-pane label="输入" name="second">
- <el-input
- style="padding: 10px"
- v-model="productTextarea"
- :rows="20"
- type="textarea"
- placeholder="请输入ASIN,多个ASIN使用逗号、空格或换行符分隔。(未完成)"
- maxlength="11000" />
- <div style="display: flex; flex-direction: row-reverse; margin-top: 10px">
- <el-button v-for="button in buttons" :key="button.text" :type="button.type" link @click="addGods">{{ button.text }}</el-button>
- </div>
- </el-tab-pane>
- </el-tabs>
- </div>
- <div style="width: 50%">
- <el-card class="box-card" shadow="never" style="border: 0">
- <template #header>
- <div class="card-header">
- <span style="font-weight: 550; font-size: 15px; color: #1f2128">已添加: {{ addedTableData.length }}</span>
- <el-text type="warning" truncated>最多添加一个产品</el-text>
- <el-button class="button" type="danger" text bg @click="delAllGoods">全部删除</el-button>
- </div>
- </template>
- <div class="card-body"></div>
- </el-card>
- <div style="padding: 0 10px 0 10px; margin-top: -12px">
- <el-table
- :data="addedTableData"
- height="475"
- style="width: 100%"
- :header-cell-style="headerCellStyle"
- @selection-change="handleAddedGoodsChange">
- <el-table-column type="selection" width="50" />
- <el-table-column prop="asin" label="ASIN">
- <template #default="scope">
- <div style="display: flex; align-items: center">
- <div style="margin-right: 8px; line-height: normal">
- <el-image class="img-box" :src="scope.row.image_link" />
- </div>
- <div>
- <el-tooltip class="box-item" effect="dark" :content="scope.row.title" placement="top">
- <div class="single-line">{{ scope.row.title ? scope.row.title : '--' }}</div>
- </el-tooltip>
- <div class="data-color">
- <span style="font-weight: 500; color: rgb(30, 33, 41)">${{ scope.row.price ? scope.row.price : '--' }}</span>
- <span style="margin: 0 5px; color: #cacdd4">|</span>
- <span style="color: #6d7784">{{ scope.row.quantity }}</span>
- </div>
- <span
- >ASIN:
- <span class="data-color" style="margin-right: 8px">{{ scope.row.asin ? scope.row.asin : '--' }}</span>
- </span>
- <span
- >SKU:
- <span class="data-color">{{ scope.row.sku ? scope.row.sku : '--' }}</span>
- </span>
- </div>
- </div>
- </template>
- </el-table-column>
- <el-table-column prop="name" label="Name" width="120" align="right">
- <template #header>
- <el-button type="danger" size="normal" link @click="delSelectedGoods">删除已选中</el-button>
- </template>
- <template #default="scope">
- <el-button type="primary" size="small" @click="delSingleGoods(scope)" text>删除</el-button>
- </template>
- </el-table-column>
- </el-table>
- </div>
- <!-- <div style="display: flex; justify-content: space-around; padding-top: 5px">
- <el-button type="primary" plain :disabled="productSave" @click="submitProductForm">保存</el-button>
- </div> -->
- </div>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { inject, onMounted, ref, watch, provide, onUnmounted } from 'vue'
- import type { Ref } from 'vue'
- import type { TabsPaneContext } from 'element-plus'
- import { ElMessage } from 'element-plus'
- import { storeToRefs } from 'pinia'
- import { useShopInfo } from '/@/stores/shopInfo'
- import { request } from '/@/utils/service'
- const shopInfo = useShopInfo()
- const { profile } = storeToRefs(shopInfo)
- const productTextarea = ref('')
- const productLoading = ref(false)
- let addedAdsTableItems = ref([])
- const currentPage = ref() // 当前页
- const pageSize = ref(20) // 每页显示条目数
- const totalItems = ref() // 数据总量
- const productTableData = ref([]) // 左侧表格数据
- const loading = ref(false)
- let addedTableData = ref([])
- let selections = []
- let addedSels = []
- const searchInp = ref('')
- const leftSelect = ref('name')
- let productSave = ref(true)
- const buttons = [{ type: 'primary', text: '添加' }] as const
- const productTabs = ref('first')
- const rightSelect = ref('latest')
- const respCampaignId = inject<Ref>('respCampaignId')
- const respAdGroupId = inject<Ref>('respAdGroupId')
- function setTableData(asin = '', sku = '') {
- return request({
- url: '/api/sellers/listings/our/',
- method: 'GET',
- params: {
- page: currentPage.value,
- limit: pageSize.value,
- profile_id: profile.value.profile_id,
- asin,
- sku,
- },
- })
- .then((resp) => {
- productTableData.value = resp.data
- totalItems.value = resp.total
- currentPage.value = resp.page
- loading.value = false
- })
- .catch((error) => {
- console.error('Error fetching data:', error)
- loading.value = false
- })
- }
- function addSingleGoods(scope) {
- // console.log('scope', scope.row)
- const isAlreadyAdded = addedTableData.value.some((item) => item.sku === scope.row.sku)
- if (!isAlreadyAdded) {
- addedTableData.value.push(scope.row)
- } else {
- console.log('Item is already added.')
- }
- }
- function addGods() {
- const inputData = productTextarea.value
- const asins = inputData.split(/[\n,]+/)
- asins.forEach((asin) => {
- if (asin.trim()) {
- setTableData(asin.trim())
- .then((response) => {
- console.log(`Data for ASIN ${asin}:`, response) // 更新这里来正确地访问数据
- })
- .catch((error) => {
- console.error(`Error fetching data for ASIN ${asin}:`, error)
- })
- }
- })
- }
- function delSingleGoods(scope) {
- const index = addedTableData.value.findIndex((item) => item.sku === scope.row.sku)
- if (index !== -1) {
- addedTableData.value.splice(index, 1)
- console.log('Item removed successfully.')
- } else {
- console.log('Item not found.')
- }
- }
- function delAllGoods() {
- addedTableData.value = []
- // addedTableData.value.splice(0, addedTableData.value.length)
- }
- // 删除第二个table中已经选中的项
- function delSelectedGoods() {
- addedTableData.value = addedTableData.value.filter((item) => !addedSels.includes(item))
- addedSels = []
- }
- function inpChange(e) {
- const value = e
- if (leftSelect.value === 'asin') {
- loading.value = true
- setTableData(value)
- } else if (leftSelect.value === 'sku') {
- loading.value = true
- setTableData('', value)
- }
- }
- function selChange(e) {
- console.log('e', e)
- const value = e
- if (leftSelect.value === 'asin' && searchInp.value) {
- loading.value = true
- setTableData(value)
- } else if (leftSelect.value === 'sku' && searchInp.value) {
- loading.value = true
- setTableData('', value)
- }
- }
- // 点击表格选项触发事件
- function handleSelectionChange(selection) {
- selections = selection
- }
- // 获取addedTable中已选中的项
- function handleAddedGoodsChange(selection) {
- addedSels = selection
- }
- // 添加已选中的项
- function handleGoodsAdd() {
- // 过滤掉已经存在于addedData.value中的项
- const newSelections = selections.filter(
- (sel) => !addedTableData.value.some((added) => added.sku === sel.sku) // 使用sku作为唯一标识
- )
- // 如果有新的不重复项,加入到addedData.value中
- if (newSelections.length > 0) {
- addedTableData.value.push(...newSelections)
- }
- }
- // 点击Tab
- const handleGoodsTabs = (tab: TabsPaneContext, event: Event) => {
- console.log(tab, event)
- }
- function isItemInList(item, list) {
- return list.some((listItem) => listItem.sku === item.sku && listItem.asin === item.asin)
- }
- // 监听商品右侧表格已添加的数据并转化数据格式
- watch(
- addedTableData,
- (newValue, oldValue) => {
- newValue.forEach((item) => {
- if (!isItemInList(item, addedAdsTableItems.value)) {
- addedAdsTableItems.value.push({ sku: item.sku, asin: item.asin })
- }
- })
- if (addedTableData.value.length !== 0) {
- productSave.value = false
- } else {
- productSave.value = true
- }
- },
- { deep: true }
- )
- async function createAds() {
- try {
- const requestData = {
- profile_id: profile.value.profile_id,
- campaignId: respCampaignId.value,
- adGroupId: respAdGroupId.value,
- asinsku: addedAdsTableItems.value,
- state: 'PAUSED',
- }
- const filteredRequestData = Object.fromEntries(Object.entries(requestData).filter(([_, v]) => v != null))
- const resp = await request({
- url: '/api/ad_manage/spads/create/',
- method: 'POST',
- data: filteredRequestData,
- })
- console.log('🚀 ~ createAds ~ resp-->>', resp)
- productLoading.value = false
- if (resp.data.success.length > 0) {
- productSave.value = false
- addedTableData.value = []
- ElMessage({
- message: '商品创建成功',
- type: 'success',
- })
- } else {
- ElMessage.error('商品创建失败!')
- }
- } catch (error) {
- console.error('请求失败:', error)
- }
- }
- function submitProductForm() {
- productLoading.value = true
- createAds()
- }
- // 处理分页器当前页变化
- function handleCurrentChange(newPage) {
- currentPage.value = newPage
- loading.value = true
- setTableData()
- }
- // 处理分页器每页显示条目数变化
- function handleSizeChange(newSize) {
- pageSize.value = newSize
- currentPage.value = 1 // 重置到第一页
- }
- const headerCellStyle = (args) => {
- if (args.rowIndex === 0) {
- return {
- backgroundColor: 'rgba(245, 245, 245, 0.9)',
- }
- }
- }
- const emit = defineEmits(['update-added-data']);
- // 当数据发生变化时,触发事件
- watch(addedTableData, (newValue) => {
- emit('update-added-data', newValue);
- }, {deep: true});
- onMounted(() => {
- setTableData()
- })
- </script>
- <style lang="scss" scoped>
- ::v-deep(.el-form--default.el-form--label-top .el-form-item .el-form-item__label) {
- font-weight: 500;
- }
- .demo-tabs > .el-tabs__content {
- padding: 52px;
- color: #6b778c;
- font-size: 32px;
- font-weight: 600;
- }
- /* 广告组商品Tab栏 */
- ::v-deep(.el-tabs__nav-scroll) {
- overflow: hidden;
- margin-left: 20px;
- }
- ::v-deep(.el-table__inner-wrapper::before) {
- background-color: white;
- }
- // 表格内容边距
- div {
- & #pane-first,
- & #pane-second {
- margin: 10px;
- }
- }
- .card-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- }
- .box-card {
- width: 100%;
- margin-right: 10px;
- }
- .single-line {
- color: rgb(30, 33, 41);
- overflow: hidden;
- display: -webkit-box;
- -webkit-box-orient: vertical;
- -webkit-line-clamp: 1;
- white-space: pre-wrap;
- word-break: break-word;
- }
- .data-color {
- color: rgb(30, 33, 41);
- }
- .img-box {
- width: 60px;
- height: 60px;
- margin-top: 5px;
- border: 1px solid rgb(194, 199, 207);
- border-radius: 4px;
- }
- /* 商品定向Tab栏 */
- ::v-deep(.goods-orientation-tabs #tab-1) {
- border-right: 0;
- }
- </style>
|