فهرست منبع

✨ feat: 更改UI布局,接口调用

WanGxC 1 سال پیش
والد
کامیت
4165998f46
1فایلهای تغییر یافته به همراه434 افزوده شده و 166 حذف شده
  1. 434 166
      src/views/adManage/sp/campaigns/CreateCampaigns/index.vue

+ 434 - 166
src/views/adManage/sp/campaigns/CreateCampaigns/index.vue

@@ -3,65 +3,80 @@
     <el-card>
       <div style="padding-left: 5px">
         <!-- 广告活动 -->
-        <div style="font-size: 20px; font-weight: bold">广告活动</div>
-        <hr />
-        <br />
         <el-form
           :label-position="labelPosition"
-          ref="ruleFormRef"
-          :model="ruleForm"
-          :rules="rules"
+          ref="campaignFormRef"
+          :model="campaignRuleForm"
+          :rules="campaignRules"
           label-width="120px"
           class="demo-ruleForm"
           :size="formSize"
           status-icon>
+          <el-card shadow="never" body-style="padding-bottom: 0 !important;" v-loading="campaignLoading">
+            <div style="font-size: 24px; font-weight: bold;">广告活动</div>
+            <hr>
+            <br>
           <el-form-item label="广告活动名称" prop="name" style="width: 350px">
-            <el-input v-model="ruleForm.name" />
+            <el-input v-model="campaignRuleForm.name" />
           </el-form-item>
           <el-form-item label="广告组合" prop="adMix">
-            <el-select v-model="ruleForm.adMix" placeholder="请选择">
+            <el-select v-model="campaignRuleForm.adMix" placeholder="请选择">
               <el-option label="Zone one" value="shanghai" />
               <el-option label="Zone two" value="beijing" />
             </el-select>
           </el-form-item>
-          <el-form-item prop="date1" label="开始日期" style="width: 350px">
-            <el-date-picker v-model="ruleForm.date1" type="date" label="开始日期" placeholder="开始日期" style="width: 100%" />
+          <el-form-item prop="startDate" label="开始日期" style="width: 350px">
+            <el-date-picker
+              v-model="campaignRuleForm.startDate"
+              type="date"
+              format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD"
+              label="开始日期"
+              placeholder="开始日期"
+              style="width: 100%"/>
           </el-form-item>
           <el-form-item prop="date2" label="结束日期" style="width: 350px">
-            <el-date-picker v-model="ruleForm.date2" label="结束日期" placeholder="结束日期" style="width: 100%" />
+            <el-date-picker
+              v-model="campaignRuleForm.date2"
+              type="date"
+              format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD"
+              label="结束日期"
+              placeholder="结束日期"
+              style="width: 100%"/>
           </el-form-item>
           <el-form-item prop="budget" label="每日预算" style="width: 350px">
-            <el-input v-model="ruleForm.budget" maxlength="7" oninput="value=value.indexOf('.') > -1?value.slice(0, value.indexOf('.') + 3):value" />
+            <el-input v-model="campaignRuleForm.budget" maxlength="7" oninput="value=value.indexOf('.') > -1?value.slice(0, value.indexOf('.') + 3):value" />
           </el-form-item>
           <el-form-item label="投放类型" prop="type" class="column-item">
-            <el-radio-group v-model="ruleForm.type" @click="changeType">
+            <el-radio-group v-model="campaignRuleForm.type" @click="changeType">
               <div>
-                <el-radio label="auto">自动</el-radio>
+                <el-radio label="AUTO">自动</el-radio>
                 <div class="radio-description">定向与您推广商品相似的关键词和商品</div>
               </div>
               <div>
-                <el-radio label="manual">手动</el-radio>
+                <el-radio label="MANUAL">手动</el-radio>
                 <div class="radio-description">选择关键词或商品以定向购物者搜索并设置自定义出价</div>
               </div>
             </el-radio-group>
           </el-form-item>
           <el-form-item label="竞价策略" prop="bidStrategy" class="column-item column-margin-bottom">
-            <el-radio-group v-model="ruleForm.bidStrategy">
+            <el-radio-group v-model="campaignRuleForm.bidStrategy">
               <div>
-                <el-radio label="dynamicBid_Low" border>
+                <el-radio label="LEGACY_FOR_SALES" border>
                   动态竞价-仅降低
                   <div class="radio-description-2">当您的广告不太可能带来销售时,我们将实时降低您的竞价</div>
                 </el-radio>
               </div>
               <div>
-                <el-radio label="dynamicBid_HighAndLow" border>
+                <el-radio label="AUTO_FOR_SALES" border>
                   动态竞价-提高和降低
                   <div class="radio-description-2">
                     当您的广告很有可能带来销售时,我们将实时提高您的竞价(最高可达 100%),并在您的广告不太可能带来销售时降低您的竞价
                   </div>
                 </el-radio>
               </div>
-              <el-radio label="staticBid" border>
+              <el-radio label="MANUAL" border>
                 固定竞价
                 <div class="radio-description-2">我们将使用您的确切竞价和您设置的任何手动调整,而不会根据售出可能性对您的竞价进行更改</div>
               </el-radio>
@@ -71,33 +86,55 @@
             <p style="color: #8e9196">除了出价策略外,您还可以将出价提高多达900%</p>
             <div class="gap-items">
               <div class="gap-item">搜索结果顶部(首页)</div>
-              <el-input v-model="ruleForm.placeBid" class="gap-item">
+              <el-input v-model="campaignRuleForm.placeBid" class="gap-item">
                 <template #append>%</template>
               </el-input>
             </div>
             <div class="gap-items">
               <div class="gap-item">商品首页</div>
-              <el-input v-model="ruleForm.firstPage" class="gap-item">
+              <el-input v-model="campaignRuleForm.firstPage" class="gap-item">
                 <template #append>%</template>
               </el-input>
             </div>
-            <div class="gap-items">
+            <div class="gap-items" style="margin-bottom: 0">
               <div class="gap-item">搜索结果的其余位置</div>
-              <el-input v-model="ruleForm.other" class="gap-item">
+              <el-input v-model="campaignRuleForm.other" class="gap-item">
                 <template #append>%</template>
               </el-input>
             </div>
           </el-form-item>
-          <!-- 广告组 -->
-          <div style="font-size: 20px; font-weight: bold; margin-top: 30px">广告组</div>
-          <hr />
-          <el-form-item label="广告组名称" prop="adGroupName" style="width: 350px; margin-top: 20px">
-            <el-input v-model="ruleForm.adGroupName" />
+          <el-form-item style="margin-left: 48%;">
+            <el-button type="primary" plain @click="submitCampaignForm(campaignFormRef)">保存</el-button>
           </el-form-item>
-          <!-- 广告组商品表格 -->
-          <el-form-item label="商品" prop="commodity" style="width: 100%; margin-top: 20px">
-            <div style="width: 100%; height: 620px; display: flex; border: 1px solid #c2c7cf; border-radius: 6px">
-              <div style="width: 50%; border-right: 1px solid #c2c7cf">
+        </el-card>
+        <br>
+          <!-- 广告组 -->
+          <el-card shadow="never" body-style="padding-bottom: 0 !important;">
+            <div style="font-size: 20px; font-weight: bold;">广告组</div>
+            <hr>
+            <br>
+            <el-form ref="adGroupRuleFormRef" :model="adGroupRuleForm" :rules="adGroupRules">
+              <el-form-item required label="广告组名称" prop="adGroupName" style="width: 350px; margin-top: 20px">
+                <el-input v-model="adGroupRuleForm.adGroupName" />
+              </el-form-item>
+              <el-form-item required label="默认竞价" prop="defaultBidInp">
+                <el-input v-model="adGroupRuleForm.defaultBidInp" style="width: 200px">
+                  <template #prepend>$</template>
+                </el-input>
+              </el-form-item>
+              <el-form-item style="margin-left: 48%;">
+                <el-button type="primary" plain @click="submitGroupsForm(adGroupRuleFormRef)" :disabled="campaignSave">保存</el-button>
+              </el-form-item>
+            </el-form>
+          </el-card>
+
+          <!-- 商品表格 -->
+          <div style=" margin-top:20px; font-size: 24px; font-weight: bold;">商品</div>
+          <hr>
+          <br>
+          <el-form-item prop="commodity" style="width: 100%;">
+            <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="activeName" class="demo-tabs">
                   <el-tab-pane label="搜索" name="first">
                     <div style="margin-bottom: 10px">
@@ -201,7 +238,7 @@
                 </el-tabs>
               </div>
               <div style="width: 50%">
-                <el-card class="box-card" shadow="never">
+                <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">已添加: {{ addedData.length }}</span>
@@ -260,25 +297,12 @@
               </div>
             </div>
           </el-form-item>
-          <!-- 自动定向 -->
-          <div class="column-item" v-if="ruleForm.type == 'auto'">
-            <p style="color: #606266; font-weight: 450"><span style="color: #e47470">*</span> 自动定向</p>
-            <el-radio-group v-model="ruleForm.autoRedirect" @change="changeBid">
-              <div style="display: flex">
-                <el-radio label="defaultBid">设置默认出价</el-radio>
-                <el-form-item prop="defaultBidInp">
-                  <el-input v-model="ruleForm.defaultBidInp" label="ruleForm.defaultBidInp" style="width: 200px">
-                    <template #prepend>$</template>
-                  </el-input>
-                </el-form-item>
-              </div>
-              <div>
-                <el-radio label="targetBid">按目标组设置出价</el-radio>
-              </div>
-            </el-radio-group>
-          </div>
-          <!-- 自动定向---按目标组设置出价 -->
-          <el-card v-if="showCard && ruleForm.type == 'auto'" class="box-card">
+          <!-- 按目标组设置出价 -->
+          <div class="column-item" v-if="campaignRuleForm.type == 'AUTO'">
+            <div style=" margin-top:20px; font-size: 24px; font-weight: bold;">按目标组设置出价</div>
+            <hr>
+            <br>
+          <el-card shadow="never" v-if="campaignRuleForm.type == 'AUTO'" class="box-card">
             <div>
               <div style="color: #8e9095">
                 <span>目标群体</span>
@@ -337,9 +361,12 @@
               </div>
             </div>
           </el-card>
+            
+          </div>
+          
 
           <!-- 投放类型 -->
-          <div class="column-item" v-if="ruleForm.type == 'manual'">
+          <div class="column-item" v-if="campaignRuleForm.type == 'MANUAL'">
             <p style="color: #606266; font-weight: 450"><span style="color: #e47470">*</span> 投放类型</p>
             <el-radio-group v-model="ruleForm.targetType" @change="changeTargetType">
               <div style="display: flex">
@@ -357,11 +384,11 @@
             </el-radio-group>
           </div>
           <!-- 关键词定向 -->
-          <div style="font-size: 20px; font-weight: bold; margin-top: 30px" v-if="ruleForm.targetType == 'keyWords' && ruleForm.type == 'manual'">
+          <div style="font-size: 20px; font-weight: bold; margin-top: 30px" v-if="ruleForm.targetType == 'keyWords' && campaignRuleForm.type == 'MANUAL'">
             关键词定向
           </div>
-          <hr v-if="ruleForm.targetType == 'keyWords' && ruleForm.type == 'manual'" />
-          <el-form-item style="width: 100%; margin-top: 20px" v-if="ruleForm.targetType == 'keyWords' && ruleForm.type == 'manual'">
+          <hr v-if="ruleForm.targetType == 'keyWords' && campaignRuleForm.type == 'MANUAL'" />
+          <el-form-item style="width: 100%; margin-top: 20px" v-if="ruleForm.targetType == 'keyWords' && campaignRuleForm.type == 'MANUAL'">
             <div style="width: 100%; height: 520px; display: flex; border: 1px solid #c2c7cf; border-radius: 6px">
               <div style="width: 50%; border-right: 1px solid #c2c7cf">
                 <el-tabs v-model="keyWordsTabs" class="demo-tabs" @tab-click="handleGoodsTabs">
@@ -429,16 +456,16 @@
 
           <div
             style="font-size: 20px; font-weight: bold; margin-top: 30px"
-            v-if="ruleForm.type === 'auto' || (ruleForm.targetType === 'keyWords' && ruleForm.type === 'manual')">
+            v-if="campaignRuleForm.type === 'AUTO' || (ruleForm.targetType === 'keyWords' && campaignRuleForm.type === 'MANUAL')">
             否定词
           </div>
-          <hr v-if="ruleForm.type === 'auto' || (ruleForm.targetType === 'keyWords' && ruleForm.type === 'manual')" />
+          <hr v-if="campaignRuleForm.type === 'AUTO' || (ruleForm.targetType === 'keyWords' && campaignRuleForm.type === 'MANUAL')" />
           <!-- 否定词表格 -->
           <el-form-item
             style="width: 100%; margin-top: 20px"
-            v-if="ruleForm.type === 'auto' || (ruleForm.targetType === 'keyWords' && ruleForm.type === 'manual')">
-            <div style="width: 100%; height: 520px; display: flex; border: 1px solid #c2c7cf; border-radius: 6px">
-              <div style="width: 50%; border-right: 1px solid #c2c7cf">
+            v-if="campaignRuleForm.type === 'AUTO' || (ruleForm.targetType === 'keyWords' && campaignRuleForm.type === 'MANUAL')">
+            <div style="width: 100%; height: 520px; display: flex; border: 1px solid #e5e7ec; border-radius: 6px">
+              <div style="width: 50%; border-right: 1px solid #e5e7ec">
                 <div style="margin: 10px 0">
                   <span style="margin-left: 25px; color: #e47470">*</span>
                   <span style="color: #666666; margin-right: 10px">匹配类型: </span>
@@ -457,7 +484,7 @@
                 </div>
               </div>
               <div style="width: 50%">
-                <el-card class="box-card" shadow="never">
+                <el-card class="box-card" shadow="never" style="border: none">
                   <template #header>
                     <div class="card-header">
                       <span style="font-weight: 550; font-size: 15px; color: #1f2128">已添加: {{ addedData.length }}</span>
@@ -487,7 +514,11 @@
               style="width: 100%; height: 520px; display: flex; border: 1px solid #c2c7cf; border-radius: 6px"
               v-loading="productOrientationLoading">
               <div style="width: 50%; border-right: 1px solid #c2c7cf">
-                <el-tabs type="border-card" stretch class="goods-orientation-tabs" style="border-bottom-left-radius: 6px">
+                <el-tabs
+                  type="border-card"
+                  stretch
+                  class="goods-orientation-tabs"
+                  style="border: 0; border-right: 0; border-bottom-left-radius: 6px; border-top-left-radius: 5px; overflow: hidden">
                   <el-tab-pane label="品类" style="border-top-left-radius: 6px">
                     <div style="display: flex; align-items: center">
                       <span style="width: 40px">竞价:</span>
@@ -529,42 +560,45 @@
                             </template>
                           </el-tree>
                         </el-scrollbar>
-                        <el-dialog v-model="visible" :title="`细化分类: ${dialogTitle}`" >
-                          <div style="display: flex; justify-content: space-between;">
+                        <el-dialog v-model="visible" :title="`细化分类: ${dialogTitle}`" @close="dialogClose" destroy-on-close>
+                          <div style="display: flex; justify-content: space-between">
                             <span>根据特定品牌、价格范围、星级和Prime配送资格,细化分类</span>
                             <span>
-                              <el-checkbox v-model="dialogForm.isCount" label="显示商品数量" />
+                              <el-checkbox v-model="dialogForm.isCount" label="显示商品数量" @change="isCountChanged" />
                             </span>
                           </div>
-                          <el-form :model="dialogForm" :rules="dialogRules" ref="dialogFormRef" style="margin-top:20px">
-                            <el-form-item style="padding-left: 140px;">
-                              <span style="margin-right: 10px; color:#616266; font-weight: 500;">品牌</span>
-                              <el-select v-model="dialogForm.dialogselectValue" placeholder="请选择">
+                          <el-form :model="dialogForm" :rules="dialogRules" ref="dialogFormRef" style="margin-top: 20px">
+                            <el-form-item style="padding-left: 140px">
+                              <span style="margin-right: 10px; color: #616266; font-weight: 500">品牌</span>
+                              <el-select v-model="dialogForm.dialogselectValue" placeholder="请选择" v-loading="dialogSelectLoading">
                                 <el-option v-for="item in dialogForm.dialogOptions" :key="item.value" :label="item.label" :value="item.value" />
                               </el-select>
                             </el-form-item>
-                            <el-form-item prop="prices" style="padding-left: 112px; margin-top: 10px;">
-                              <span style="margin-right: 10px; color:#616266; font-weight: 500;">价格范围</span>
+                            <el-form-item prop="prices" style="padding-left: 112px; margin-top: 10px">
+                              <span style="margin-right: 10px; color: #616266; font-weight: 500">价格范围</span>
                               <el-input-number v-model="dialogForm.prices.lowest" :min="1" :controls="false" placeholder="无最低商品价格" />
                               --
                               <el-input-number v-model="dialogForm.prices.highest" :min="1" :controls="false" placeholder="无最高商品价格" />
                             </el-form-item>
-                            <el-form-item prop="starRating" style="padding-left: 85px; margin-top: 10px;">
-                              <span style="margin-right: 15px; color:#616266; font-weight: 500;">查看星级评定</span>
-                              <el-slider v-model="dialogForm.starRating" range show-stops :max="5" :marks="marks" style="width: 70%;"/>
+                            <el-form-item prop="starRating" style="padding-left: 85px; margin-top: 10px">
+                              <span style="margin-right: 15px; color: #616266; font-weight: 500">查看星级评定</span>
+                              <el-slider v-model="dialogForm.starRating" range show-stops :max="5" :marks="marks" style="width: 70%" />
                             </el-form-item>
-                            <el-form-item prop="delivery" style="padding-left: 140px; margin-top: 30px;">
-                              <span style="margin-right: 10px; color:#616266; font-weight: 500;">配送</span>
+                            <el-form-item prop="delivery" style="padding-left: 140px; margin-top: 30px">
+                              <span style="margin-right: 10px; color: #616266; font-weight: 500">配送</span>
                               <el-radio-group v-model="dialogForm.delivery">
-                                <el-radio label="all" style="font-weight: 400;">具备</el-radio>
-                                <el-radio label="eligible" style="font-weight: 400;">具备Prime资格</el-radio>
-                                <el-radio label="diseligible" style="font-weight: 400;">不具备Prime资格</el-radio>
+                                <el-radio label="all" style="font-weight: 400">具备</el-radio>
+                                <el-radio label="eligible" style="font-weight: 400">具备Prime资格</el-radio>
+                                <el-radio label="diseligible" style="font-weight: 400">不具备Prime资格</el-radio>
                               </el-radio-group>
                             </el-form-item>
                           </el-form>
                           <template #footer>
-                            <div style="display: flex; justify-content: space-between;">
-                              <span v-loading="countLoadig">定位到的商品数量: {{ commodityCount[0]?.min }} - {{ commodityCount[0]?.max }}</span>
+                            <div style="display: flex; justify-content: space-between">
+                              <span v-loading="countLoadig"
+                                >定位到的商品数量:
+                                <span v-if="dialogForm.isCount == true">{{ commodityCount[0]?.min }} - {{ commodityCount[0]?.max }}</span></span
+                              >
                               <span class="dialog-footer">
                                 <el-button @click="visible = false">取消</el-button>
                                 <el-button type="primary" @click="dialogFormSubmit">确定</el-button>
@@ -578,15 +612,19 @@
                   <el-tab-pane label="单个商品">
                     <div style="display: flex; align-items: center">
                       <span style="width: 40px">竞价:</span>
-                      <el-select v-model="categoryBiddingType" class="m-2" placeholder="Select">
-                        <el-option v-for="item in categoryBiddingTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
+                      <el-select class="m-2" v-model="singleGoodsBidSelect" @change="singleGoodsBidSelectChanged">
+                        <el-option v-for="item in singleGoodsBidTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
                       </el-select>
-                      <el-input v-model="categoryBidInput" placeholder="Please input" style="width: 200px">
+                      <el-input
+                        v-model="singleGoodsBidInput"
+                        :disabled="singleGoodsBidSelect == 'defaultBid'"
+                        placeholder="Please input"
+                        style="width: 200px">
                         <template #prepend>$</template>
                       </el-input>
                       <div style="margin-left: 20px">
                         <span style="margin-right: 10px">类型:</span>
-                        <el-checkbox v-model="expand" label="展" />
+                        <el-checkbox v-model="expand" label="展" />
                         <el-checkbox v-model="accurate" label="精准" />
                       </div>
                     </div>
@@ -600,7 +638,7 @@
                       </el-tab-pane>
                       <el-tab-pane label="搜索" name="second">
                         <el-input placeholder="按ASIN搜索"></el-input>
-                        <el-table :data="proposalTableData" style="width: 100%" height="342">
+                        <el-table :data="proposalTableData" style="width: 100%" height="309">
                           <el-table-column prop="proposal" label="商品" width="520" />
                           <el-table-column prop="address" label="类型" />
                           <el-table-column prop="operational" label="操作" />
@@ -616,20 +654,34 @@
                 <el-card class="box-card" shadow="never">
                   <template #header>
                     <div class="card-header">
-                      <span style="font-weight: 550; font-size: 15px; color: #1f2128">已添加: {{ addedData.length }}</span>
-                      <el-button class="button" text bg @click="delAllKeyWords">全部删除</el-button>
+                      <span style="font-weight: 550; font-size: 15px; color: #1f2128">已添加: {{ productOrientationTableData.length }}</span>
+                      <el-button class="button" text bg @click="delAllCna">全部删除</el-button>
                     </div>
                   </template>
                   <div class="card-body">
                     <el-table
-                      :data="addedKeyWordsTableData"
+                      :data="productOrientationTableData"
                       style="width: 100%"
                       :header-row-style="changeKeyWordsTableHeader"
                       :header-cell-style="headerCellStyle">
-                      <el-table-column prop="keyword" label="关键词" width="auto" />
-                      <el-table-column prop="bid" label="出价" />
-                      <el-table-column prop="suggestBid" label="建议出价" />
-                      <el-table-column prop="operate" label="操作" width="60" align="right" />
+                      <el-table-column prop="cna" label="分类 & 商品" width="300">
+                        <template #default="scope"> 分类: {{ scope.row.cna }} </template>
+                      </el-table-column>
+                      <el-table-column prop="type" label="类型">
+                        <template #default="scope">
+                          {{ scope.row.type ? 'scope.row.type' : '--' }}
+                        </template>
+                      </el-table-column>
+                      <el-table-column prop="bid" label="竞价">
+                        <template #default="scope">
+                          <el-input-number v-model="scope.row.bid" :min="0" :max="1000000" :controls="false" size="small" />
+                        </template>
+                      </el-table-column>
+                      <el-table-column prop="operate" label="操作" width="60" align="right">
+                        <template #default="scope">
+                          <el-button text size="small" @click="delCna(scope.$index)">删除</el-button>
+                        </template>
+                      </el-table-column>
                     </el-table>
                   </div>
                 </el-card>
@@ -640,17 +692,17 @@
 
           <div
             style="font-size: 20px; font-weight: bold; margin-top: 30px"
-            v-if="ruleForm.type == 'auto' || (ruleForm.targetType == 'Goods' && ruleForm.type === 'manual')">
+            v-if="campaignRuleForm.type == 'AUTO' || (ruleForm.targetType == 'Goods' && campaignRuleForm.type === 'manual')">
             否定商品
           </div>
-          <hr v-if="ruleForm.type == 'auto' || (ruleForm.targetType == 'Goods' && ruleForm.type === 'manual')" />
+          <hr v-if="campaignRuleForm.type == 'AUTO' || (ruleForm.targetType == 'Goods' && campaignRuleForm.type === 'MANUAL')" />
           <!-- 否定商品表格 -->
           <el-form-item
             prop="matchType"
             style="width: 100%; margin-top: 20px"
-            v-if="ruleForm.type == 'auto' || (ruleForm.targetType == 'Goods' && ruleForm.type === 'manual')">
-            <div style="width: 100%; height: 520px; display: flex; border: 1px solid #c2c7cf; border-radius: 6px">
-              <div style="width: 50%; border-right: 1px solid #c2c7cf">
+            v-if="campaignRuleForm.type == 'AUTO' || (ruleForm.targetType == 'Goods' && campaignRuleForm.type === 'MANUAL')">
+            <div style="width: 100%; height: 520px; display: flex; border: 1px solid #e5e7ec; border-radius: 6px">
+              <div style="width: 50%; border-right: 1px solid #e5e7ec">
                 <el-tabs v-model="negativeTabs" class="demo-tabs" @tab-click="handleNegGoodsTabs">
                   <el-tab-pane label="搜索" name="first">
                     <div style="margin-bottom: 10px">
@@ -703,7 +755,7 @@
                 </el-tabs>
               </div>
               <div style="width: 50%">
-                <el-card class="box-card" shadow="never">
+                <el-card class="box-card" shadow="never" style="border: none">
                   <template #header>
                     <div class="card-header">
                       <span style="font-weight: 550; font-size: 15px; color: #1f2128">已添加: {{ addedNegetiveTableData.length }}</span>
@@ -750,8 +802,8 @@
 
           <br />
           <el-form-item>
-            <el-button type="negativeGoods" @click="submitForm(ruleFormRef)">Create</el-button>
-            <el-button @click="resetForm(ruleFormRef)">Reset</el-button>
+            <el-button size="large" @click="resetForm(ruleFormRef)">取消</el-button>
+            <el-button size="large" type="primary" plain @click="submitForm(ruleFormRef)">保存</el-button>
           </el-form-item>
         </el-form>
       </div>
@@ -764,11 +816,14 @@ import { onMounted, reactive, ref, computed, watch } from 'vue'
 import type { CSSProperties } from 'vue'
 import { useRoute } from 'vue-router'
 import type { FormInstance, FormRules, TabsPaneContext } from 'element-plus'
+import { ElMessage } from 'element-plus'
 import { useShopInfo } from '/@/stores/shopInfo'
 import { usePublicData } from '/@/stores/publicData'
 import { storeToRefs } from 'pinia'
 import { useRouter } from 'vue-router'
 import { request } from '/@/utils/service'
+import { number } from 'echarts'
+
 
 const negativeTableData = ref([])
 const addedNegetiveTableData = ref([])
@@ -801,14 +856,15 @@ let phraseType = ref(true)
 let exactType = ref(true)
 
 // 表单相关数据
+const campaignLoading = ref(false)
 const formSize = ref('default')
 const labelPosition = ref('top')
-const ruleFormRef = ref<FormInstance>()
-interface RuleForm {
+const campaignFormRef = ref<FormInstance>()
+interface CampaignForm {
   name: string
   adMix: string
   count: string
-  date1: string
+  startDate: string
   date2: string
   budget: string
   delivery: boolean
@@ -817,9 +873,79 @@ interface RuleForm {
   placeBid: string
   firstPage: string
   other: string
+}
+const campaignRuleForm = reactive<CampaignForm>({
+  name: 'aitest02campaign_wxc',
+  adMix: '',
+  count: '',
+  startDate: '',
+  date2: '',
+  budget: '',
+  delivery: false,
+  type: 'AUTO',
+  bidStrategy: 'LEGACY_FOR_SALES',
+  placeBid: '',
+  firstPage: '',
+  other: ''
+})
+const campaignRules = computed(() => ({
+  name: [{ required: true, message: 'Please input Activity name', trigger: 'blur' }],
+  adMix: [{ required: false, message: 'Please select Activity zone', trigger: 'change' }],
+  count: [{ required: true, message: 'Please select Activity count', trigger: 'change' }],
+  startDate: [{ required: true, type: 'date', message: 'Please pick a date', trigger: 'change' }],
+  date2: [{ required: false, type: 'date', message: 'Please pick a time', trigger: 'change' }],
+  budget: [
+    { required: true, message: '请输入预算', trigger: 'blur' },
+    { pattern: /^(?:[1-9]\d{0,5}|1000000)(?:\.\d{1,2})?$/, message: '预算必须是1到1000000之间的数字,小数点后最多两位', trigger: 'blur' },
+  ],
+  type: [{ required: false, trigger: 'change' }],
+  bidStrategy: [{ required: true, message: 'Please select activity resource', trigger: 'change' }],
+  placeBid: [{ required: false, pattern: /^[0-9]{1,3}$/, message: '必须是0~900之间的整数百分比', trigger: 'change' }],
+  firstPage: [{ required: false, pattern: /^[0-9]{1,3}$/, message: '必须是0~900之间的整数百分比', trigger: 'change' }],
+  other: [{ required: false, pattern: /^[0-9]{1,3}$/, message: '必须是0~900之间的整数百分比', trigger: 'change' }],
+}))
+
+const adGroupRuleFormRef = ref<FormInstance>()
+interface AdGroupForm {
   adGroupName: string
-  autoRedirect: string
   defaultBidInp: string
+}
+const adGroupRuleForm = reactive<AdGroupForm>({
+  adGroupName: '',
+  defaultBidInp: '',
+})
+const adGroupRules = computed(() => ({
+  adGroupName: [{ required: true, message: '请输入广告组名称', trigger: 'blur' }],
+  defaultBidInp: [
+    { required: true, message: '请输入默认出价', trigger: 'blur' },
+    { validator: validateDefaultBidInp, trigger: 'blur' },
+  ],
+}))
+
+function validateDefaultBidInp(rule, value, callback) {
+  if (value === '') {
+    callback(new Error('请输入默认出价'))
+  } else if (!/^(0\.0[2-9]|0\.[1-9]\d|1?\d{1,2}(\.\d{1,2})?|1000(\.0{1,2})?)$/.test(value)) {
+    callback(new Error('最小不低于0.02,最大不超过1000,并且只能有两位小数'))
+  } else {
+    const numericValue = parseFloat(value)
+    const numericBudget = parseFloat(campaignRuleForm.budget)
+    if (numericValue > numericBudget) {
+      callback(new Error('默认出价不能大于当前预算'))
+    } else {
+      callback()
+    }
+  }
+}
+
+
+
+
+const ruleFormRef = ref<FormInstance>()
+interface RuleForm {
+
+  autoRedirect: string
+
   closeMatch: boolean
   broadMatch: boolean
   similarProducts: boolean
@@ -835,21 +961,7 @@ interface RuleForm {
   targetType: string
 }
 const ruleForm = reactive<RuleForm>({
-  name: 'Hello',
-  adMix: '',
-  count: '',
-  date1: '',
-  date2: '',
-  budget: '',
-  delivery: false,
-  type: 'auto',
-  bidStrategy: 'dynamicBid_Low',
-  placeBid: '',
-  firstPage: '',
-  other: '',
-  adGroupName: '',
   autoRedirect: 'defaultBid',
-  defaultBidInp: '',
   closeMatch: true,
   broadMatch: true,
   similarProducts: true,
@@ -865,23 +977,7 @@ const ruleForm = reactive<RuleForm>({
   targetType: 'keyWords',
 })
 const rules = computed(() => ({
-  name: [{ required: true, message: 'Please input Activity name', trigger: 'blur' }],
-  adMix: [{ required: false, message: 'Please select Activity zone', trigger: 'change' }],
-  count: [{ required: true, message: 'Please select Activity count', trigger: 'change' }],
-  date1: [{ required: true, type: 'date', message: 'Please pick a date', trigger: 'change' }],
-  date2: [{ required: false, type: 'date', message: 'Please pick a time', trigger: 'change' }],
-  budget: [
-    { required: true, message: '请输入预算', trigger: 'blur' },
-    { pattern: /^(?:[1-9]\d{0,5}|1000000)(?:\.\d{1,2})?$/, message: '预算必须是1到1000000之间的数字,小数点后最多两位', trigger: 'blur' },
-  ],
-  type: [{ required: false, trigger: 'change' }],
-  bidStrategy: [{ required: true, message: 'Please select activity resource', trigger: 'change' }],
-  placeBid: [{ required: false, pattern: /^[0-9]{1,3}$/, message: '必须是0~900之间的整数百分比', trigger: 'change' }],
-  firstPage: [{ required: false, pattern: /^[0-9]{1,3}$/, message: '必须是0~900之间的整数百分比', trigger: 'change' }],
-  other: [{ required: false, pattern: /^[0-9]{1,3}$/, message: '必须是0~900之间的整数百分比', trigger: 'change' }],
-  adGroupName: [{ required: true, message: 'Please input Activity name', trigger: 'blur' }],
   autoRedirect: [{ required: true, trigger: 'change' }],
-  defaultBidInp: getValidationRules('defaultBidInp'),
   relatedProductsInp: getValidationRules('relatedProductsInp'),
   similarProductsInp: getValidationRules('similarProductsInp'),
   broadMatchInp: getValidationRules('broadMatchInp'),
@@ -933,11 +1029,24 @@ const categoryBiddingTypeOptions = [
   },
 ]
 const categoryBidInput = ref('0.75')
+const singleGoodsBidSelect = ref('customBid')
+const singleGoodsBidTypeOptions = [
+  {
+    value: 'defaultBid',
+    label: '默认竞价',
+  },
+  {
+    value: 'customBid',
+    label: '自定义竞价',
+  },
+]
+const singleGoodsBidInput = ref('0.75')
 const expand = ref(true)
 const accurate = ref(false)
 const proposalTableData = ref([])
 const searchClassifyTableData = ref([])
 const productOrientationLoading = ref(false)
+const dialogSelectLoading = ref(false)
 const defaultProps = {
   children: 'ch',
   label: 'cna',
@@ -950,19 +1059,17 @@ const dialogselectValue = ref('')
 let dialogOptions: any = ref([])
 const dialogForm: any = reactive({
   prices: {
-      lowest: undefined,
-      highest: undefined
+    lowest: undefined,
+    highest: undefined,
   },
-  starRating: [0,5],
+  starRating: [0, 5],
   dialogselectValue: [],
   delivery: 'all',
   isCount: false,
 })
 const dialogFormRef = ref()
 const dialogRules = reactive({
-  prices: [
-      { validator: validatePrices, trigger: 'blur' }
-    ]
+  prices: [{ validator: validatePrices, trigger: 'blur' }],
 })
 
 interface Mark {
@@ -979,7 +1086,8 @@ const marks = reactive<Marks>({
   5: '5',
 })
 let commodityCount = ref([])
-
+let currentDialogIndex = ref(0)
+let productOrientationTableData = ref([])
 
 async function validatePrices(rule, value) {
   if (value.highest !== '' && value.lowest !== '' && value.highest <= value.lowest) {
@@ -999,7 +1107,6 @@ function dialogFormSubmit() {
   })
 }
 
-
 async function setProductOrientationData() {
   try {
     const resp = await request({
@@ -1027,20 +1134,19 @@ async function setDialogOption() {
       },
     })
     const options = resp.data
-    dialogForm.dialogOptions = options.brands.map(brand => {
+    dialogForm.dialogOptions = options.brands.map((brand) => {
       return {
         label: brand.name,
-        value: brand.id
+        value: brand.id,
       }
     })
-    console.log('🚀 ~ setDialogOption ~ dialogOptions-->>', dialogOptions)
+    dialogSelectLoading.value = false
   } catch (error) {
     console.error('请求失败:', error)
   }
 }
 
-
-async function getCount() {
+async function getCount(instanceId) {
   try {
     const resp = await request({
       url: '/api/ad_manage/products/count/',
@@ -1050,32 +1156,78 @@ async function getCount() {
         category_id: categoryId.value,
       },
     })
-    commodityCount.value = resp.data.AsinCounts
-    countLoadig.value = false
-  } catch(error) {
+    if (instanceId === currentDialogIndex.value) {
+      commodityCount.value = resp.data.AsinCounts
+    }
+  } catch (error) {
     console.error('请求失败:', error)
+  } finally {
+    if (instanceId === currentDialogIndex.value) {
+      countLoadig.value = false
+    }
+  }
+}
+
+function dialogClose() {
+  currentDialogIndex.value++
+  resetDialogForm()
+  dialogForm.isCount = false
+  commodityCount.value = []
+  countLoadig.value = false
+}
+
+function resetDialogForm() {
+  dialogForm.prices.lowest = undefined
+  dialogForm.prices.highest = undefined
+  dialogForm.starRating = [0, 5]
+  dialogForm.dialogselectValue = []
+  dialogForm.delivery = 'all'
+  dialogForm.isCount = false
+}
+
+function isCountChanged() {
+  if (dialogForm.isCount) {
+    const instanceId = currentDialogIndex.value
+    countLoadig.value = true
+    getCount(instanceId)
+  } else {
+    countLoadig.value = false
+    commodityCount.value = []
+  }
+}
+
+function delCna(index) {
+  productOrientationTableData.value.splice(index, 1)
+}
+
+function delAllCna() {
+  productOrientationTableData.value = []
+}
+
+function singleGoodsBidSelectChanged() {
+  if (singleGoodsBidSelect.value === 'defaultBid') {
+    singleGoodsBidInput.value = ''
   }
 }
 
 function refine(data) {
   console.log('🚀 ~ refine ~ data-->>', data)
+  commodityCount.value = []
   dialogTitle.value = data.cna
   categoryId.value = data.cid
   visible.value = true
+  dialogSelectLoading.value = true
   setDialogOption()
 }
 
 function orientate(node, data) {
-}
+  console.log('🚀 ~ orientate ~ data-->>', data)
+  const exists = productOrientationTableData.value.some((item) => item.cid === data.cid)
 
-watch(() => dialogForm.isCount, (newValue, oldValue) => {
-    if (newValue === true) {
-      countLoadig.value = true
-      getCount()
-    } else {
-      commodityCount.value = []
-    }
-  })
+  if (!exists) {
+    productOrientationTableData.value.push(data)
+  }
+}
 
 // ------------------------------------------关键词定向模块------------------------------------------
 const bidType = ref('customBid')
@@ -1373,7 +1525,7 @@ function handleNegGoodsTabs(tab: TabsPaneContext, event: Event) {
 // ------------------------------------------自定义校验模块------------------------------------------
 function checkBid(value, callback, bidField) {
   const bid = parseFloat(value)
-  const budget = parseFloat(ruleForm.budget)
+  const budget = parseFloat(campaignRuleForm.budget)
   // 检查值是否为最多两位小数的普通数字格式
   const isNormalNumberWithTwoDecimals = /^-?\d+(\.\d{1,2})?$/.test(value)
 
@@ -1451,12 +1603,13 @@ watch(
   }
 )
 
-// 表单提交
+// ------------------------------------------表单提交------------------------------------------
 async function submitForm(formEl: FormInstance | undefined) {
   if (!formEl) return
   await formEl.validate((valid, fields) => {
     if (valid) {
       console.log('submit!')
+      createCampaigns()
     } else {
       console.log('error submit!', fields)
     }
@@ -1468,6 +1621,118 @@ function resetForm(formEl: FormInstance | undefined) {
   formEl.resetFields()
 }
 
+
+let respCampaignId = ref('')
+let campaignSave = ref(true)
+async function createCampaigns() {
+  try {
+    // 必需字段列表
+    const requiredFields = [
+      { key: 'profile_id', value: profile.value.profile_id },
+      { key: 'name', value: campaignRuleForm.name },
+      { key: 'startDate', value: campaignRuleForm.startDate },
+      { key: 'targetingType', value: campaignRuleForm.type },
+      { key: 'strategy', value: campaignRuleForm.bidStrategy },
+      { key: 'budget', value: campaignRuleForm.budget },
+    ]
+
+    // 检查每个必需字段
+    requiredFields.forEach((field) => {
+      if (!field.value) {
+        throw new Error(`缺少必需的字段: ${field.key}`)
+      }
+    })
+
+    // 构建请求数据
+    const requestData = {
+      profile_id: profile.value.profile_id,
+      name: campaignRuleForm.name,
+      startDate: campaignRuleForm.startDate,
+      budget: campaignRuleForm.budget,
+      targetingType: campaignRuleForm.type,
+      strategy: campaignRuleForm.bidStrategy,
+      state: 'PAUSED',
+      // 可选字段
+      endDate: campaignRuleForm.date2,
+      t_percentage: campaignRuleForm.placeBid,
+      p_percentage: campaignRuleForm.firstPage,
+      r_percentage: campaignRuleForm.other,
+    }
+
+    // 过滤掉 undefined 或空的可选字段
+    const filteredRequestData = Object.fromEntries(Object.entries(requestData).filter(([_, v]) => v != null))
+
+    const resp = await request({
+      url: '/api/ad_manage/spcampaigns/create/',
+      method: 'POST',
+      data: filteredRequestData,
+    })
+    console.log('🚀 ~ createCampaigns ~ resp-->>', resp)
+    respCampaignId.value = resp.data.campaignId
+    if (respCampaignId.value) {
+      campaignSave.value = false
+      campaignLoading.value = false
+    } else {
+      campaignLoading.value = false
+      ElMessage.error('广告活动创建失败!')
+    }
+  } catch (error) {
+    console.error('请求失败:', error)
+  }
+}
+
+async function submitCampaignForm(formEl: FormInstance | undefined) {
+  if (!formEl) return
+  await formEl.validate((valid, fields) => {
+    if (valid) {
+      console.log('submit!')
+      campaignLoading.value = true
+      createCampaigns()
+    } else {
+      console.log('error submit!', fields)
+    }
+  })
+}
+
+async function createGroups() {
+  try {
+    // 构建请求数据
+    const requestData = {
+      profile_id: profile.value.profile_id,
+      campaignId: respCampaignId,
+      name: adGroupRuleForm.adGroupName,
+      defaultBid: adGroupRuleForm.defaultBidInp,
+      state: 'PAUSED',
+    }
+
+    // 过滤掉 undefined 或空的可选字段
+    const filteredRequestData = Object.fromEntries(Object.entries(requestData).filter(([_, v]) => v != null))
+
+    const resp = await request({
+      url: '/api/ad_manage/spgroups/create/',
+      method: 'POST',
+      data: filteredRequestData,
+    })
+    console.log('🚀 ~ createCampaigns ~ resp-->>', resp)
+
+  } catch (error) {
+    console.error('请求失败:', error)
+  }
+}
+
+async function submitGroupsForm(formEl: FormInstance | undefined) {
+  if (!formEl) return
+  await formEl.validate((valid, fields) => {
+    if (valid) {
+      console.log('submit!')
+      createGroups()
+    } else {
+      console.log('error submit!', fields)
+    }
+  })
+}
+
+
 // 修改表头样式
 const headerCellStyle = (args) => {
   if (args.rowIndex === 0) {
@@ -1585,7 +1850,6 @@ div {
   width: 100%;
   // margin: 10px 0 10px 10px;
   margin-right: 10px;
-  border: none;
 }
 .single-line {
   color: rgb(30, 33, 41);
@@ -1624,8 +1888,12 @@ div {
 ::v-deep(.category-tabs .el-tabs__nav) {
   margin-left: 20px;
 }
-// el-tree自定义样式
+::v-deep(.goods-orientation-tabs #tab-1) {
+  /* 商品定向Tab栏 */
+  border-right: 0;
+}
 .custom-tree-node {
+  /* el-tree自定义样式 */
   flex: 1;
   display: flex;
   align-items: center;
@@ -1633,8 +1901,8 @@ div {
   font-size: 14px;
   padding-right: 8px;
 }
-/* 弹窗样式 */
 .dialog-head {
+  /* 弹窗样式 */
   display: flex;
   flex-direction: row;
   justify-content: space-between;