Browse Source

refactor(product-manage): 重构商品管理模块

- 优化了产品列表和监控页面的表格组件
- 新增 DataTableSlot 组件用于自定义表格列
-改进了数据请求和处理逻辑- 统一了样式和布局
WanGxC 7 months ago
parent
commit
8bf11cc006

+ 24 - 127
src/views/product-manage/product-list/ColumnsTsx.tsx

@@ -1,20 +1,9 @@
-import { useCountryInfoStore } from '/@/stores/countryInfo';
-import { getTagType } from '/@/utils/useTagColor';
-
-
-const countryInfoStore = useCountryInfoStore();
-
-export const productColumns = (handleMonitor: Function) => [
+export const productColumns = [
   { type: 'checkbox', width: 50, align: 'center', fixed: 'left' },
   { type: 'seq', title: 'No.', width: 60, align: 'center' },
   {
     field: 'is_monitor', title: '监控管理', width: 90, align: 'center',
-    slots: {
-      default({ row }: any) {
-        return <el-switch v-model={ row.is_monitor }
-                          onChange={ (newVal: any) => handleMonitor({ id: row.id, isMonitor: newVal }) } />;
-      }
-    }
+    slots: { default: 'is_monitor' }
   },
   {
     field: 'product_info', title: '商品信息', minWidth: 'auto', align: 'center',
@@ -22,155 +11,63 @@ export const productColumns = (handleMonitor: Function) => [
   },
   {
     field: 'sku', title: 'SKU', minWidth: 'auto', align: 'center',
-    slots: {
-      default({ row }: any) {
-        return <span class={ 'font-medium' }>{ row.sku ? row.sku : '--' }</span>;
-      }
-    }
+    slots: { default: 'sku' }
   },
   {
     field: 'country_code', title: '国 家', minWidth: 'auto', align: 'center',
-    slots: {
-      default({ row }: any) {
-        const country = countryInfoStore.countries.find(c => c.code === row.country_code);
-        const color = country ? country.color : '#3875F6';
-        return (
-            <el-tag effect="plain" round
-                    style={ { color: color, borderColor: color } }>{ country ? country.name : '--' }
-            </el-tag>
-        );
-      }
-    }
+    slots: { default: 'country_code' }
+  },
+  {
+    field: 'brand', title: '品 牌', minWidth: 'auto', align: 'center',
+    slots: { default: 'brand' }
   },
   {
     field: 'platform_number', title: '平台编号', minWidth: 'auto', align: 'center',
-    slots: {
-      default({ row }: any) {
-        return <span class={ 'font-medium' }>{ row.platform_number ? row.platform_number : '--' }</span>;
-      }
-    }
+    slots: { default: 'platform_number' }
   },
   {
     field: 'shop_name', title: '店 铺', minWidth: 'auto', align: 'center',
-    slots: {
-      default({ row }: any) {
-        return (
-            <el-tag type={ getTagType.value(row.shop_name) }>
-              { row.shop_name ? row.shop_name : '--' }
-            </el-tag>
-        );
-      }
-    }
-  },
-  {
-    field: 'tag', title: '分 组',  minWidth: 'auto', align: 'center',
-    slots: {
-      default({ row }: any) {
-        return (
-            <el-tag type={ getTagType.value(row.tag) }>
-              { row.tag ? row.tag : '--' }
-            </el-tag>
-        );
-      }
-    }
+    slots: { default: 'shop_name' }
   },
   {
-    field: 'brand', title: '品 牌', minWidth: 'auto', align: 'center',
-    slots: {
-      default({ row }: any) {
-        return (
-            <el-tag type={ getTagType.value(row.brand) } effect="plain" round>
-              { row.brand ? row.brand : '--' }
-            </el-tag>
-        );
-      }
-    }
-  },
-  {
-    field: 'price_info', title: '价 格', minWidth: 'auto', align: 'center',
-    slots: {
-      default({ row }: any) {
-        return (
-            <div v-if={ row.price > 0 } class={ `font-medium text-left` }>
-              <p>现 价:{ row.currency_code + '‎' + row.price }</p>
-              <p>折 扣:{ row.discount > 0 ? row.discount + '%' : '-' }</p>
-              <p>优惠劵:{ !row || row.coupon <= 0 ? '-' : row.currency_code + '‎' + row.coupon }</p>
-            </div>
-        );
-      }
-    }
+    field: 'tag', title: '分 组', minWidth: 'auto', align: 'center',
+    slots: { default: 'tag' }
+  },
+  {
+    field: 'price_info', title: '价 格', minWidth: 'auto', headerAlign: 'center', align: 'left',
+    slots: { default: 'price_info' }
   },
   {
     field: 'show_price', title: '展示价格', minWidth: 'auto', align: 'center',
-    slots: {
-      default({ row }: any) {
-        return <div class={ 'font-medium' }>{ row.show_price ? row.currency_code + row.show_price : '--' }</div>;
-      }
-    }
+    slots: { default: 'show_price' }
   },
   {
     field: 'activity_price', title: '平时活动售价', minWidth: 'auto', align: 'center',
-    slots: {
-      default({ row }: any) {
-        return <div
-            class={ 'font-medium' }>{ row.activity_price ? row.currency_code + row.activity_price : '--' }</div>;
-      }
-    }
+    slots: { default: 'activity_price' }
   },
   {
     field: 'minimum_price', title: '最低活动售价', minWidth: 'auto', align: 'center',
-    slots: {
-      default({ row }: any) {
-        return <div class={ 'font-medium' }>{ row.minimum_price ? row.currency_code + row.minimum_price : '--' }</div>;
-      }
-    }
+    slots: { default: 'minimum_price' }
   },
   {
     field: 'launch_date', title: '上架日期', minWidth: 'auto', align: 'center', sortable: true,
-    slots: {
-      default({ row }: any) {
-        return <div class={ 'font-medium' }>{ row.launch_date ? row.launch_date : '--' }</div>;
-      }
-    }
+    slots: { default: 'launch_date' }
   },
   {
     field: 'category', title: '类 目', minWidth: 'auto', align: 'center',
-    slots: {
-      default({ row }: any) {
-        return <div class={ 'font-medium' }>{ row.category ? row.category : '--' }</div>;
-      }
-    }
+    slots: { default: 'category' }
   },
   {
     field: 'status', title: '状 态', minWidth: 'auto', align: 'center',
-    slots: {
-      default({ row }: any) {
-        const statusText = row.status === 1 ? '在售' : '停售';
-        const statusType = row.status === 1 ? 'success' : 'info';
-
-        return (
-            <el-tag type={ statusType }>
-              { statusText }
-            </el-tag>
-        );
-      }
-    }
+    slots: { default: 'status' }
   },
   {
     field: 'update_datetime', title: '更新时间', minWidth: 'auto', align: 'center',
-    slots: {
-      default({ row }: any) {
-        return <div class={ 'font-medium' }>{ row.update_datetime ? row.update_datetime : '--' }</div>;
-      }
-    }
+    slots: { default: 'update_datetime' }
   },
   {
     field: 'create_datetime', title: '创建时间', minWidth: 'auto', align: 'center',
-    slots: {
-      default({ row }: any) {
-        return <div class={ 'font-medium' }>{ row.create_datetime ? row.create_datetime : '--' }</div>;
-      }
-    }
+    slots: { default: 'create_datetime' }
   },
   {
     field: 'operate', title: '操 作', width: 100, align: 'center', fixed: 'right',

+ 6 - 6
src/views/product-manage/product-list/api.ts

@@ -7,30 +7,30 @@ export function getTableData(query: any) {
   return request({
     url: apiPrefix,
     method: 'GET',
-    params: query,
+    params: query
   });
 }
 
 export function getGroupOptions() {
   return request({
     url: apiPrefix + 'tags/',
-    method: 'GET',
+    method: 'GET'
   });
 }
 
 export function getBrandsOptions(query: any) {
   return request({
-    url:  apiPrefix + 'brands/',
+    url: apiPrefix + 'brands/',
     method: 'GET',
-    params: query,
+    params: query
   });
 }
 
 export function updateShopDetail(body: any) {
   return request({
-    url: apiPrefix + `${body.id}/`,
+    url: apiPrefix + `${ body.id }/`,
     method: 'POST',
     params: { partial: body.partial },
-    data: body.formData,
+    data: body.formData
   });
 }

+ 10 - 23
src/views/product-manage/product-list/component/DataTable.vue

@@ -14,7 +14,7 @@ import ImportButton from '/src/components/ImportButton/index.vue';
 import VerticalDivider from '/src/components/VerticalDivider/index.vue';
 import { productColumns } from '../ColumnsTsx';
 import { downloadFile } from '/@/utils/service';
-import ProductInfo from '/@/views/product-manage/product-list/component/ProductInfo.vue';
+import DataTableSlot from './DataTableSlot.vue';
 
 
 interface Parameter {
@@ -60,7 +60,7 @@ const gridOptions: any = reactive({
     icon: 'vxe-icon-indicator roll',
     text: '正在拼命加载中...'
   },
-  columns: productColumns(handleMonitor),
+  columns: '',
   data: ''
 });
 
@@ -73,11 +73,13 @@ const dialogVisible = ref(false);
 
 const templateType = ref('notice');
 
-onBeforeMount(() => {
+onMounted(() => {
   fetchList();
 });
 
 async function fetchList() {
+  gridOptions.data = [];
+  
   const query = {
     country_code: queryParameter?.country,
     brand: queryParameter?.brand,
@@ -87,7 +89,10 @@ async function fetchList() {
     sku: queryParameter?.sku,
     shop_id: queryParameter?.shop
   };
+
   await useTableData(api.getTableData, query, gridOptions);
+  await gridRef.value.loadColumn(productColumns);
+  gridOptions.showHeader = Boolean(gridOptions.data?.length);
 }
 
 function handleRefresh() {
@@ -151,10 +156,6 @@ function downloadTemplate() {
   }
 }
 
-function handleMonitor(val: any) {
-  console.log('(DataTable.vue: 157)=> val', val);
-}
-
 defineExpose({ fetchList });
 </script>
 
@@ -223,22 +224,8 @@ defineExpose({ fetchList });
       />
     </template>
     <!-- 自定义列插槽 -->
-    <template #product_info="{ row }">
-      <ProductInfo :item="row" :img-width="50"></ProductInfo>
-    </template>
-    <template #operate="{ row }">
-      <div class="flex justify-center gap-2">
-        <PermissionButton circle plain type="warning" @click="handleEdit(row)">
-          <el-icon>
-            <Operation />
-          </el-icon>
-        </PermissionButton>
-        <PermissionButton circle plain type="info" @click="handleNotice(row)">
-          <el-icon>
-            <Message />
-          </el-icon>
-        </PermissionButton>
-      </div>
+    <template v-for="col in productColumns" #[`${col.field}`]="{ row }">
+      <DataTableSlot :key="row.id" :field="col.field" :row="row" @edit-row="handleEdit" @handle-notice="handleNotice" />
     </template>
   </vxe-grid>
   <EditDrawer v-if="editOpen" v-model="editOpen" :row-data="rowData" />

+ 116 - 0
src/views/product-manage/product-list/component/DataTableSlot.vue

@@ -0,0 +1,116 @@
+<script lang="ts" setup>
+/**
+ * @Name: DataTableSlot.vue
+ * @Description: 商品列表-单元格插槽
+ * @Author: Cheney
+ */
+
+import { useCountryInfoStore } from '/@/stores/countryInfo';
+import { Operation, Delete, Message } from '@element-plus/icons-vue';
+import PermissionButton from '/@/components/PermissionButton/index.vue';
+import ProductInfo from '/@/views/product-manage/product-list/component/ProductInfo.vue';
+import { getTagType } from '/@/utils/useTagColor';
+
+
+const props = defineProps<{
+  row: any,
+  field: any
+}>();
+const { row, field } = props;
+
+const emit = defineEmits([ 'edit-row', 'handle-notice' ]);
+
+const countryInfoStore = useCountryInfoStore();
+const country = countryInfoStore.countries.find(c => c.code == row.country_code);
+const color = country ? country.color : '#3875F6';
+
+const statusText = row.status === 1 ? '在售' : '停售';
+const statusType = row.status === 1 ? 'success' : 'info';
+
+function handleEdit(row: any) {
+  emit('edit-row', row);
+}
+
+function handleNotice(row: any) {
+  emit('handle-notice', row);
+}
+</script>
+
+<template>
+  <div class="font-medium">
+    <div v-if="field === 'is_monitor'">
+      <el-switch v-model=row.is_monitor />
+    </div>
+    <div v-else-if="field === 'product_info'">
+      <ProductInfo :img-width="50" :item="row" style="min-width: 230px" />
+    </div>
+    <div v-else-if="field === 'country_code'">
+      <el-tag :disable-transitions="true" :style="{ color: color, borderColor: color }" effect="plain" round>
+        {{ country ? country.name : '--' }}
+      </el-tag>
+    </div>
+    <div v-else-if="field === 'shop_name'">
+      <el-tag :disable-transitions="true" :type=getTagType(row.shop_name)>
+        {{ row.shop_name ?? '--' }}
+      </el-tag>
+    </div>
+    <div v-else-if="field === 'tag'">
+      <el-tag :disable-transitions="true" :type=getTagType(row.tag)>
+        {{  row.tag ??  '--'  }}
+      </el-tag>
+    </div>
+    <div v-else-if="field === 'brand'">
+      <el-tag :disable-transitions="true" :type=getTagType(row.brand) effect="plain" round>
+        {{ row.brand ?? '--' }}
+      </el-tag>
+    </div>
+    <div v-else-if="field === 'price_info'">
+      <div v-if="row.price > 0" class="font-medium">
+        <p>现 价:{{ row.currency_code + '‎' + row.price }}</p>
+        <p>折 扣:{{ row.discount > 0 ? row.discount + '%' : '-' }}</p>
+        <p>优惠劵:{{ !row || row.coupon <= 0 ? '-' : row.currency_code + '‎' + row.coupon }}</p>
+      </div>
+    </div>
+    <div v-else-if="field === 'show_price'">
+      <div class="font-medium">
+        {{ row.show_price ? row.currency_code + row.show_price : '--' }}
+      </div>
+    </div>
+    <div v-else-if="field === 'activity_price'">
+      <div class="font-medium">
+        {{ row.activity_price ? row.currency_code + row.activity_price : '--' }}
+      </div>
+    </div>
+    <div v-else-if="field === 'minimum_price'">
+      <div class="font-medium">
+        {{ row.minimum_price ? row.currency_code + row.minimum_price : '--' }}
+      </div>
+    </div>
+    <div v-else-if="field === 'status'">
+      <el-tag :disable-transitions="true" :type=statusType>
+        {{ statusText }}
+      </el-tag>
+    </div>
+    <div v-else-if="field === 'operate'">
+      <div class="flex justify-center gap-2">
+        <PermissionButton circle plain type="warning" @click="handleEdit(row)">
+          <el-icon>
+            <Operation />
+          </el-icon>
+        </PermissionButton>
+        <PermissionButton circle plain type="info" @click="handleNotice(row)">
+          <el-icon>
+            <Message />
+          </el-icon>
+        </PermissionButton>
+      </div>
+    </div>
+    <div v-else>
+      {{ row[field] }}
+    </div>
+  </div>
+</template>
+
+<style scoped>
+
+</style>

+ 1 - 1
src/views/product-manage/product-list/component/EditDrawer.vue

@@ -1,7 +1,7 @@
 <script lang="ts" setup>
 /**
  * @Name: EditDrawer.vue
- * @Description: 店铺编辑
+ * @Description: 商品列表-行编辑
  * @Author: Cheney
  */
 

+ 2 - 2
src/views/product-manage/product-list/component/NoticeDialog.vue

@@ -1,6 +1,6 @@
 <script lang="ts" setup>/**
  * @Name: NoticeDialog.vue
- * @Description:
+ * @Description: 变更通知弹窗
  * @Author: Cheney
  */
 import { ElMessage } from 'element-plus';
@@ -9,7 +9,7 @@ import { ElMessage } from 'element-plus';
 const { rowData } = defineProps<{
   rowData: object;
 }>();
-// console.log('rowData=> ', rowData);
+
 const dialogVisible = defineModel({ default: false });
 
 const staffSelect = ref('');

+ 1 - 1
src/views/product-manage/product-list/component/ProductInfo.vue

@@ -49,7 +49,7 @@ const props = defineProps({
       </div>
     </el-image>
     <div class="text-left">
-      <el-tooltip :content="item.title" :disabled="showTitleTooltip" :show-after="300" effect="dark" 
+      <el-tooltip :content="item.title" :disabled="showTitleTooltip" :show-after="300" effect="dark"
                   placement="top-start">
         <el-link :href=item.url :underline="false" target="_blank" type="primary">
           <span class="line-clamp-2 text-ellipsis whitespace-normal">{{ item.title ?? '--' }}</span>

+ 17 - 17
src/views/product-manage/product-list/index.vue

@@ -15,43 +15,43 @@ import * as api from './api';
 import { useTemplateRef } from 'vue';
 
 
-const { data: staticData } = DictionaryStore()
+const { data: staticData } = DictionaryStore();
 
 const titleContainer: Ref<HTMLElement | null> = useTemplateRef('titleContainer');
 const queryContainer: Ref<HTMLElement | null> = useTemplateRef('queryContainer');
 const { tableHeight } = useTableHeight(titleContainer, queryContainer);
 
-const tableRef: Ref<any> = useTemplateRef('table')
+const tableRef: Ref<any> = useTemplateRef('table');
 
 const btnLoading = ref(false);
 
 const formInline = reactive({
-  country: '',
-  brand: '',
+  country: 'US',
+  brand: 'ZOSI',
   group: '',
   status: '',
   asin: '',
   sku: '',
-  shop: '',
+  shop: ''
 });
-provide('query-parameter', formInline)
+provide('query-parameter', formInline);
 
-const groupOptions:any = ref([])
-const brandsOptions:any = ref([])
+const groupOptions: any = ref([]);
+const brandsOptions: any = ref([]);
 
 onBeforeMount(() => {
-  fetchGroupOptions()
-  fetchBrandsOptions()
-})
+  fetchGroupOptions();
+  fetchBrandsOptions();
+});
 
 async function fetchGroupOptions() {
-  const res = await useResponse(api.getGroupOptions)
-  groupOptions.value = res.data
+  const res = await useResponse(api.getGroupOptions);
+  groupOptions.value = res.data;
 }
 
 async function fetchBrandsOptions() {
-  const res = await useResponse(api.getBrandsOptions)
-  brandsOptions.value = res.data
+  const res = await useResponse(api.getBrandsOptions);
+  brandsOptions.value = res.data;
 }
 
 async function handleQuery() {
@@ -74,7 +74,7 @@ async function handleQuery() {
                 <div class="flex items-center">
                   <span class="mr-2">国 家</span>
                   <el-select v-model="formInline.country" clearable placeholder="请选择国家">
-                    <el-option v-for="item in staticData.country_code" :key="item.value" :label="item.label" 
+                    <el-option v-for="item in staticData.country_code" :key="item.value" :label="item.label"
                                :value="item.value" />
                   </el-select>
                 </div>
@@ -99,7 +99,7 @@ async function handleQuery() {
                 <div class="flex items-center">
                   <span class="mr-2">状 态</span>
                   <el-select v-model="formInline.status" clearable placeholder="请选择状态">
-                    <el-option v-for="item in staticData.goods_status" :key="item.value" :label="item.label" 
+                    <el-option v-for="item in staticData.goods_status" :key="item.value" :label="item.label"
                                :value="item.value" />
                   </el-select>
                 </div>

+ 8 - 8
src/views/product-manage/product-monitor/ColumnsTsx.tsx

@@ -1,18 +1,22 @@
 export const productColumns = [
-  { type: 'checkbox', minWidth: 50, align: 'center', fixed: 'left' },
-  { type: 'seq', title: 'No.', minWidth: 60, align: 'center', fixed: 'left' },
+  { type: 'checkbox', width: 50, align: 'center', fixed: 'left' },
+  { type: 'seq', title: 'No.', width: 60, align: 'center', fixed: 'left' },
   {
     field: 'product_info', title: '商品信息', minWidth: 'auto', align: 'center', fixed: 'left',
     slots: { default: 'product_info' }
   },
   {
     field: 'sku', title: 'SKU', minWidth: 'auto', align: 'center',
-    slots: {default: 'sku' }
+    slots: { default: 'sku' }
   },
   {
     field: 'country_code', title: '国 家', minWidth: 'auto', align: 'center',
     slots: { default: 'country_code' }
   },
+  {
+    field: 'brand', title: '品 牌', minWidth: 'auto', align: 'center',
+    slots: { default: 'brand' }
+  },
   {
     field: 'platform_number', title: '平台编号', minWidth: 'auto', align: 'center',
     slots: { default: 'platform_number' }
@@ -22,13 +26,9 @@ export const productColumns = [
     slots: { default: 'shop_name' }
   },
   {
-    field: 'tag', title: '分 组',  minWidth: 'auto', align: 'center',
+    field: 'tag', title: '分 组', minWidth: 'auto', align: 'center',
     slots: { default: 'tag' }
   },
-  {
-    field: 'brand', title: '品 牌', minWidth: 'auto', align: 'center',
-    slots: { default: 'brand' }
-  },
   {
     field: 'price_info', title: '价 格', minWidth: 'auto', headerAlign: 'center', align: 'left',
     slots: { default: 'price_info' }

+ 10 - 9
src/views/product-manage/product-monitor/api.ts

@@ -7,38 +7,39 @@ export function getTableData(query: any) {
   return request({
     url: apiPrefix + 'reviews_monitor/',
     method: 'GET',
-    params: query,
+    params: query
   });
 }
 
 export function getGroupOptions(query: any) {
   return request({
-    url:  apiPrefix + 'goods/tags/',
+    url: apiPrefix + 'goods/tags/',
     method: 'GET',
-    params: query,
+    params: query
   });
 }
 
 export function getBrandsOptions(query: any) {
   return request({
-    url:  apiPrefix + 'goods/brands/',
+    url: apiPrefix + 'goods/brands/',
     method: 'GET',
-    params: query,
+    params: query
   });
 }
+
 export function getShopsOptions(query: any) {
   return request({
-    url:  apiPrefix + 'marketplace_shops/select/',
+    url: apiPrefix + 'marketplace_shops/select/',
     method: 'GET',
-    params: query,
+    params: query
   });
 }
 
 export function updateShopDetail(body: any) {
   return request({
-    url: apiPrefix + `${body.id}/`,
+    url: apiPrefix + `${ body.id }/`,
     method: 'POST',
     params: { partial: body.partial },
-    data: body.formData,
+    data: body.formData
   });
 }

+ 3 - 3
src/views/product-manage/product-monitor/component/DataTable.vue

@@ -1,7 +1,7 @@
 <script lang="ts" setup>
 /**
  * @Name: Table.vue
- * @Description: 商品列表表格
+ * @Description: 商品监控表格
  * @Author: Cheney
  */
 
@@ -96,7 +96,7 @@ async function fetchList() {
     goods__all_reviews: queryParameter?.commentNumber,
     goods__all_score: queryParameter?.displayScore
   };
-  
+
   await useTableData(api.getTableData, query, gridOptions);
   await gridRef.value.loadColumn(productColumns);
   gridOptions.showHeader = Boolean(gridOptions.data?.length);
@@ -212,7 +212,7 @@ defineExpose({ fetchList });
     </template>
     <!-- 自定义列插槽 -->
     <template v-for="col in productColumns" #[`${col.field}`]="{ row }">
-      <DataTableSlot :key="row.id" :field="col.field" :row="row" @edit-row="handleEdit" @handle-notice="singleDelete" />
+      <DataTableSlot :key="row.id" :field="col.field" :row="row" @edit-row="handleEdit" @handle-delete="singleDelete" />
     </template>
   </vxe-grid>
   <EditDrawer v-if="editOpen" v-model="editOpen" :row-data="rowData" />

+ 24 - 23
src/views/product-manage/product-monitor/component/DataTableSlot.vue

@@ -1,15 +1,15 @@
 <script lang="ts" setup>
 /**
  * @Name: DataTableSlot.vue
- * @Description:
+ * @Description: 商品监控-表格插槽
  * @Author: Cheney
  */
 
-
 import { useCountryInfoStore } from '/@/stores/countryInfo';
-import { Operation, Delete, Message } from '@element-plus/icons-vue';
-import PermissionButton from '/@/components/PermissionButton/index.vue'
+import { Operation, Delete } from '@element-plus/icons-vue';
+import PermissionButton from '/@/components/PermissionButton/index.vue';
 import ProductInfo from '/@/views/product-manage/product-list/component/ProductInfo.vue';
+import { getTagType } from '/@/utils/useTagColor';
 
 
 const props = defineProps<{
@@ -18,7 +18,7 @@ const props = defineProps<{
 }>();
 const { row, field } = props;
 
-const emit = defineEmits([ 'edit-row', 'handle-notice' ]);
+const emit = defineEmits([ 'edit-row', 'handle-delete' ]);
 
 const countryInfoStore = useCountryInfoStore();
 const country = countryInfoStore.countries.find(c => c.code == row.country_code);
@@ -31,32 +31,33 @@ function handleEdit(row: any) {
   emit('edit-row', row);
 }
 
-function handleNotice(row: any) {
-  emit('handle-notice', row);
+function handleDelete(row: any) {
+  emit('handle-delete', row);
 }
 </script>
 
 <template>
   <div class="font-medium">
-    <div v-if="field === 'country_code'">
+    <div v-if="field === 'product_info'">
+      <ProductInfo :img-width="50" :item="row.goods" style="min-width: 230px" />
+    </div>
+    <div v-else-if="field === 'country_code'">
       <el-tag :disable-transitions="true" :style="{ color: color, borderColor: color }" effect="plain" round>
         {{ country ? country.name : '--' }}
       </el-tag>
     </div>
-    <div v-else-if="field === 'product_info'">
-      <ProductInfo :item="row.goods" :img-width="50" />
-    </div>
-    <div v-else-if="field === 'sku'">
-      {{ row.goods.sku ?? '--' }}
-    </div>
-    <div v-else-if="field === 'platform_number'">
-      {{ row.goods.platform_number ?? '--' }}
-    </div>
     <div v-else-if="field === 'shop_name'">
-      <el-tag :disable-transitions="true" type="primary" effect="plain">{{ row.shop_name ?? '--' }}</el-tag>
+      <el-tag :disable-transitions="true" :type=getTagType(row.shop_name)>
+        {{ row.shop_name ?? '--' }}
+      </el-tag>
+    </div>
+    <div v-else-if="field === 'tag'">
+      <el-tag :disable-transitions="true" :type=getTagType(row.goods.tag)>
+        {{  row.goods.tag ??  '--'  }}
+      </el-tag>
     </div>
     <div v-else-if="field === 'brand'">
-      <el-tag :disable-transitions="true" :style="{ color: '#F88B8A', borderColor: '#FBC4C4'}"  effect="plain">
+      <el-tag :disable-transitions="true" :type=getTagType(row.goods.brand) effect="plain" round>
         {{ row.goods.brand ?? '--' }}
       </el-tag>
     </div>
@@ -70,7 +71,7 @@ function handleNotice(row: any) {
     <div v-else-if="field === 'show_price'">
       <div class="font-medium">
         {{ row.goods.show_price ? row.goods.currency_code + row.goods.show_price : '--' }}
-    </div>
+      </div>
     </div>
     <div v-else-if="field === 'activity_price'">
       <div class="font-medium">
@@ -84,7 +85,7 @@ function handleNotice(row: any) {
     </div>
     <div v-else-if="field === 'status'">
       <el-tag :disable-transitions="true" :type=statusType>
-      {{ statusText }}
+        {{ statusText }}
       </el-tag>
     </div>
     <div v-else-if="field === 'operate'">
@@ -94,9 +95,9 @@ function handleNotice(row: any) {
             <Operation />
           </el-icon>
         </PermissionButton>
-        <PermissionButton circle plain type="info" @click="handleNotice(row)">
+        <PermissionButton circle plain type="danger" @click="handleDelete(row)">
           <el-icon>
-            <Message />
+            <Delete />
           </el-icon>
         </PermissionButton>
       </div>

+ 9 - 11
src/views/product-manage/product-monitor/component/EditDrawer.vue

@@ -1,13 +1,11 @@
 <script lang="ts" setup>
 /**
  * @Name: EditDrawer.vue
- * @Description: 店铺编辑
+ * @Description: 商品监控-行编辑
  * @Author: Cheney
  */
 
 import { ElMessage, FormInstance, FormRules } from 'element-plus';
-import { useResponse } from '/src/utils/useResponse';
-import * as api from '/src/views/shop-information/api';
 
 
 const loading = ref(false);
@@ -40,7 +38,7 @@ const ruleForm = reactive<RuleForm>({
   shop: '',
   group: '',
   status: '',
-  frequency: '',
+  frequency: ''
 });
 
 const rules = reactive<FormRules<RuleForm>>({
@@ -49,7 +47,7 @@ const rules = reactive<FormRules<RuleForm>>({
   country: [ { required: true, message: '请选择国家', trigger: 'change' } ],
   shop: [ { required: true, message: '请输入店铺', trigger: 'blur' } ],
   group: [ { required: true, message: '请输入分组', trigger: 'blur' } ],
-  status: [ {  message: '请选择状态', trigger: 'blur' } ],
+  status: [ { message: '请选择状态', trigger: 'blur' } ],
   frequency: [ { message: '请选择更新频率', trigger: 'blur' } ]
 
 });
@@ -98,19 +96,19 @@ const resetForm = (formEl: FormInstance | undefined) => {
         label-width="auto"
         status-icon>
       <el-form-item label="ASIN" prop="asin">
-        <el-input v-model="ruleForm.asin"/>
+        <el-input v-model="ruleForm.asin" />
       </el-form-item>
       <el-form-item label="SKU" prop="sku">
-        <el-input v-model="ruleForm.sku"/>
+        <el-input v-model="ruleForm.sku" />
       </el-form-item>
       <el-form-item label="店 铺" prop="shop">
-        <el-input v-model="ruleForm.shop"/>
+        <el-input v-model="ruleForm.shop" />
       </el-form-item>
       <el-form-item label="分 组" prop="group">
-        <el-input v-model="ruleForm.group"/>
+        <el-input v-model="ruleForm.group" />
       </el-form-item>
       <el-form-item label="状 态" prop="status">
-        <el-select v-model="ruleForm.status"/>
+        <el-select v-model="ruleForm.status" />
       </el-form-item>
       <el-form-item label="国 家" prop="country">
         <el-select v-model="ruleForm.country" placeholder="请选择国家">
@@ -123,7 +121,7 @@ const resetForm = (formEl: FormInstance | undefined) => {
         </el-select>
       </el-form-item>
       <el-form-item label="更新频率" prop="frequency">
-        <el-input-number v-model="ruleForm.frequency"/>
+        <el-input-number v-model="ruleForm.frequency" />
       </el-form-item>
       <el-form-item>
         <el-divider />

+ 0 - 135
src/views/product-manage/product-monitor/component/NoticeDialog.vue

@@ -1,135 +0,0 @@
-<script lang="ts" setup>/**
- * @Name: NoticeDialog.vue
- * @Description:
- * @Author: Cheney
- */
-import { ElMessage } from 'element-plus';
-
-
-const { rowData } = defineProps<{
-  rowData: object;
-}>();
-// console.log('rowData=> ', rowData);
-const dialogVisible = defineModel({ default: false });
-
-const staffSelect = ref('');
-const staffOptions: any = ref([]);
-const staffTags: any = ref([]);
-const staffLoading = ref(false);
-const currentRow: any = ref(null);
-
-function handleClose(done: any) {
-  staffSelect.value = '';
-  staffTags.value = [];
-  done();
-}
-
-function addStaffChange() {
-  const selectedOption: any = staffOptions.value.find((option: any) => option.id === staffSelect.value);
-  if (selectedOption && !staffTags.value.some((tag: any) => tag.id === selectedOption.id)) {
-    // 如果选中的项不在 staffTags 中,则添加到 staffTags
-    staffTags.value.push({
-      id: selectedOption.id,
-      username: selectedOption.username
-    });
-  }
-}
-
-function isOptionDisabled(id: any) {
-  return staffTags.value.some((tag: any) => tag.id === id);
-}
-
-function removeTag(tag: any) {
-  staffTags.value = staffTags.value.filter((t: any) => t.id !== tag.id);
-}
-
-async function fetchExistingStaff(row: any) {
-  const query = {
-    id: row.value.id ? row.value.id : row.value.rowid
-  };
-  // const resp = await api.getExistingStaffs(query);
-  // staffTags.value = resp.data;
-}
-
-async function addStaffs() {
-  staffLoading.value = true;
-  const body = {
-    id: currentRow.id,
-    user_ids: staffTags.map((tag: any) => tag.id)
-  };
-  try {
-    // const resp = await api.postStaffs(body);
-    // if (resp.code === 2000) {
-    //   ElMessage.error('编辑成功!');
-    //   await fetchExistingStaff(currentRow);
-    // }
-  } catch (error) {
-    ElMessage.error('编辑失败!');
-  } finally {
-    staffSelect.value = '';
-    staffLoading.value = false;
-  }
-}
-
-function cancelDialog() {
-  handleClose(() => {
-    dialogVisible.value = false;
-  });
-}
-</script>
-
-<template>
-  <div>
-    <el-dialog
-        v-model="dialogVisible"
-        :before-close="handleClose"
-        :close-on-click-modal="false"
-        :close-on-press-escape="false"
-        title="变更通知"
-        width="35%"
-    >
-      <el-row class="mb-2">
-        <el-col>
-          <span class="mr-2">人员选择</span>
-          <el-select v-model="staffSelect" filterable placeholder="输入搜索" style="width: 200px;"
-                     @change="addStaffChange">
-            <el-option
-                v-for="item in staffOptions"
-                :key="item.id"
-                :disabled="isOptionDisabled(item.id)"
-                :label="item.username"
-                :value="item.id">
-            </el-option>
-          </el-select>
-        </el-col>
-      </el-row>
-      <el-row :gutter="20">
-        <el-col :span="2">
-
-        </el-col>
-        <el-col :span="20" class="ml-2.5">
-          <i class="bi bi-info-circle"></i>
-          <span class="ml-1" style="color: #909399">仅可添加已绑定邮箱的用户</span>
-        </el-col>
-      </el-row>
-      <el-divider style="margin: 12px 0 20px 0"></el-divider>
-      <div class="flex flex-wrap gap-1.5">
-        <el-tag
-            v-for="tag in staffTags"
-            :key="tag.id"
-            closable
-            @close="removeTag(tag)">
-          {{ tag.username }}
-        </el-tag>
-      </div>
-      <span slot="footer" class="dialog-footer">
-        <el-button @click="cancelDialog">取 消</el-button>
-        <el-button :loading="staffLoading" type="primary" @click="addStaffs">确 定</el-button>
-      </span>
-    </el-dialog>
-  </div>
-</template>
-
-<style scoped>
-
-</style>

+ 3 - 4
src/views/product-manage/product-monitor/index.vue

@@ -1,7 +1,7 @@
 <script lang="ts" setup>
 /**
  * @Name: index.vue
- * @Description:
+ * @Description: 商品监控
  * @Author: Cheney
  */
 
@@ -13,7 +13,6 @@ import { useResponse } from '/@/utils/useResponse';
 import * as api from './api';
 import { useTemplateRef } from 'vue';
 import { DictionaryStore } from '/@/stores/dictionary';
-import { getShopsOptions } from './api';
 
 
 const { data: staticData } = DictionaryStore();
@@ -25,8 +24,8 @@ const { tableHeight } = useTableHeight(titleContainer, queryContainer);
 const tableRef: Ref<any> = useTemplateRef('table');
 
 const formInline = reactive({
-  country: '',
-  brand: '',
+  country: 'US',
+  brand: 'ZOSI',
   group: '',
   status: '',
   shop: '',