Ver código fonte

Merge branch 'cheney' into dev

# Conflicts:
#	src/views/sku-manage/Columns.ts
WanGxC 6 meses atrás
pai
commit
9ba90d51f1

+ 0 - 1
src/views/product-manage/historical-detail/component/PriceChart.vue

@@ -125,7 +125,6 @@ async function fetchChartData() {
   const res = await useResponse(api.getChartData, { asin, country_code: country }, loading);
   if (res.code === 2000 && res.data) {
     chartData.value = res.data;
-    console.log("(PriceChart.vue: 126)=> chartData", chartData);
     updateChart();
   }
 }

+ 18 - 6
src/views/product-manage/product-list/component/DataTableSlot.vue

@@ -6,7 +6,7 @@
  */
 
 import { useCountryInfoStore } from '/@/stores/countryInfo';
-import { DocumentCopy, Message, Operation } from '@element-plus/icons-vue';
+import { DocumentCopy, Message, MessageBox, Operation } from '@element-plus/icons-vue';
 import { getTagType } from '/@/utils/useTagColor';
 import PermissionButton from '/@/components/PermissionButton/index.vue';
 import ProductInfo from '/@/views/product-manage/component/ProductInfo.vue';
@@ -118,11 +118,14 @@ function handleMonitor() {
             <Operation />
           </el-icon>
         </PermissionButton>
-        <PermissionButton circle plain type="info" @click="handleNotice">
-          <el-icon>
-            <Message />
-          </el-icon>
-        </PermissionButton>
+        <el-tooltip :enterable="false" :show-arrow="false" content="变更通知" hide-after="0"
+                    placement="top" popper-class="custom-btn-tooltip-info">
+          <PermissionButton circle plain type="info" @click="handleNotice">
+            <el-icon>
+              <Message />
+            </el-icon>
+          </PermissionButton>
+        </el-tooltip>
       </div>
     </div>
     <div v-else>
@@ -134,3 +137,12 @@ function handleMonitor() {
 <style scoped>
 
 </style>
+
+<style lang="scss">
+.custom-btn-tooltip-info {
+  background-color: #F4F4F5 !important;
+  color: #606266 !important;
+  border: 1px solid #C8C9CC !important;
+  font-size: 14px;
+}
+</style>

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

@@ -118,7 +118,7 @@ function mappingShopId(val: any) {
           </el-select>
         </el-form-item>
         <el-form-item class="font-medium" label="分 组:" prop="tag">
-          <el-select v-model="ruleForm.tag">
+          <el-select v-model="ruleForm.tag" filterable>
             <el-option v-for="item in groupOptions" :label="item.tag" :value="item.tag" />
           </el-select>
         </el-form-item>

+ 11 - 1
src/views/sku-manage/Columns.ts

@@ -57,7 +57,7 @@ export const ProductCategoryColumns = [
   },
   { field: 'create_datetime', title: '创建时间',  align: 'center', slots: { default: 'create_datetime' } },
   {
-    field: 'operate', title: '操 作', width: 100, align: 'center', fixed: 'right',
+    field: 'operate', title: '操 作', width: 130, align: 'center', fixed: 'right',
     slots: { default: 'operate' }
   }
 ];
@@ -101,3 +101,13 @@ export const EnumColumns = [
   {field:'operate',title: '操作',align: 'center',slots: { default: 'operate' }}
 ]
 
+
+export const AttributeManageColumns = [
+  { type: 'seq', title: 'No.', width: 70, align: 'center', fixed: 'left' },
+  { field: 'placement', title: '位 置',  align: 'center', slots: { default: 'placement' } },
+  { field: 'attribute', title: '属 性',  align: 'center', slots: { default: 'attribute' } },
+  { field: 'order', title: '顺 序',  align: 'center', slots: { default: 'order' } },
+  { field: 'update_datetime', title: '更新时间', width: 170, align: 'center', slots: { default: 'update_datetime' } },
+  { field: 'create_datetime', title: '创建时间', width: 170, align: 'center', slots: { default: 'create_datetime' } },
+  { field: 'operate', title: '操 作', width: 175, align: 'center', fixed: 'right', slots: { default: 'operate' } }
+]

+ 55 - 1
src/views/sku-manage/product-category/api.ts

@@ -15,7 +15,6 @@ export function deleteRow(query: any) {
   return request({
     url: apiPrefix + query.id + '/',
     method: 'DELETE',
-    params: query
   });
 }
 
@@ -35,3 +34,58 @@ export function create(data:any) {
   })
 }
 
+
+export function getAttributeManageData(query: any) {
+  return request({
+    url: '/api/cms/sku_kind_attr/',
+    method: 'GET',
+    params: query
+  });
+}
+
+export function getAttributeOptions(query: any) {
+  return request({
+    url: '/api/cms/sku_attr/',
+    method: 'GET',
+    params: query
+  });
+}
+
+export function updateAttributeRow(query: any) {
+  return request({
+    url: '/api/cms/sku_kind_attr/' + query.id + '/',
+    method: 'PUT',
+    data: query
+  });
+}
+
+export function createProductAttr(body: any) {
+  return request({
+    url: 'api/cms/sku_kind_attr/',
+    method: 'POST',
+    data: body
+  });
+}
+
+export function deleteProductAttr(id: any) {
+  return request({
+    url: `api/cms/sku_kind_attr/${id}/`,
+    method: 'DELETE',
+  });
+}
+
+export function release(query: any) {
+  return request({
+    url: `/api/cms/sku_kind/${query.id}/?partial=${query.partial}`,
+    method: 'PUT',
+    data: { status: query.status }
+  });
+}
+
+export function updateOrder(query: any) {
+  return request({
+    url: `/api/cms/sku_kind_attr/${query.id}/`,
+    method: 'PUT',
+    data: query
+  });
+}

+ 302 - 0
src/views/sku-manage/product-category/component/AttributeManage.vue

@@ -0,0 +1,302 @@
+<script lang="ts" setup>
+/**
+ * @Name: AttributeManage.vue
+ * @Description: 属性管理
+ * @Author: Cheney
+ */
+
+import { usePagination } from '/@/utils/usePagination';
+import { useTableData } from '/@/utils/useTableData';
+import * as api from '../api';
+import { AttributeManageColumns } from '/@/views/sku-manage/Columns';
+import { Delete, InfoFilled, Operation, Plus, Position, Refresh } from '@element-plus/icons-vue';
+import { getTagType } from '/@/utils/useTagColor';
+import PermissionButton from '/@/components/PermissionButton/index.vue';
+import AttributeManageEdit from '/@/views/sku-manage/product-category/component/AttributeManageEdit.vue';
+import { useResponse } from '/@/utils/useResponse';
+import { ElMessage } from 'element-plus';
+import AttributeManageCreate from '/@/views/sku-manage/product-category/component/AttributeManageCreate.vue';
+
+
+const visible = defineModel({ default: false });
+
+const props: any = defineProps({
+  rowData: Object
+});
+const { rowData } = props;
+
+const emit = defineEmits([ 'refresh' ]);
+
+const editDrawer = <Ref>useTemplateRef('editDrawer');
+
+const { tableOptions, handlePageChange } = usePagination(fetchList);
+
+const gridRef = ref();
+const gridOptions: any = reactive({
+  id: 'product-attribute-table',
+  keepSource: true,
+  size: 'small',
+  border: false,
+  round: true,
+  stripe: true,
+  currentRowHighLight: true,
+  height: '100%',
+  customConfig: {
+    storage: true
+  },
+  toolbarConfig: {
+    size: 'large',
+    custom: true,
+    slots: {
+      buttons: 'toolbar_buttons',
+      tools: 'toolbar_tools'
+    }
+  },
+  rowConfig: {
+    isHover: true
+  },
+  columnConfig: {
+    resizable: true
+  },
+  pagerConfig: {
+    total: tableOptions.value.total,
+    page: tableOptions.value.page,
+    limit: tableOptions.value.limit
+  },
+  loading: false,
+  loadingConfig: {
+    icon: 'vxe-icon-indicator roll',
+    text: '正在拼命加载中...'
+  },
+  columns: '',
+  data: ''
+});
+
+const editOpen = ref(false);
+const createOpen = ref(false);
+const editRow = ref({});
+
+onBeforeMount(() => {
+  fetchList();
+});
+
+async function fetchList(isQuery = false) {
+  if (isQuery) {
+    gridOptions.pagerConfig.page = 1;
+  }
+
+  gridOptions.data = [];
+  gridOptions.columns = [];
+
+  const query = {
+    kind: rowData.id
+  };
+
+  await useTableData(api.getAttributeManageData, query, gridOptions);
+  await gridRef.value.loadColumn(AttributeManageColumns);
+  gridOptions.showHeader = Boolean(gridOptions.data?.length);
+}
+
+function handleRefresh() {
+  fetchList();
+}
+
+function handleEdit(row: any) {
+  editOpen.value = true;
+  editRow.value = row;
+}
+
+async function onConfirm(row: any) {
+  const res = await useResponse(api.deleteProductAttr, row.id);
+  if (res.code === 2000) {
+    ElMessage.success({ message: '删除成功', plain: true });
+    handleRefresh();
+  }
+}
+
+async function handleCreate() {
+  createOpen.value = true;
+}
+
+async function handleRelease() {
+  const query = {
+    id: rowData.id,
+    partial: 1,
+    status: 3
+  };
+
+  const res = await useResponse(api.release, query);
+  if (res.code === 2000) {
+    ElMessage.success({ message: '发布成功', plain: true });
+    closeDrawer();
+    emit('refresh');
+  }
+}
+
+async function handleUpdate(row: any) {
+  console.log("(AttributeManage.vue: 137)=> row", row);
+  const query = {
+    id: row.id,
+    attr: row.attr.id,
+    order: row.order,
+    kind: row.kind.id,
+    section: row.section,
+    status: row.status
+  };
+
+  const res = await useResponse(api.updateOrder, query);
+  if (res.code === 2000) {
+    ElMessage.success({ message: '修改成功', plain: true });
+    handleRefresh();
+  }
+}
+
+function closeDrawer() {
+  editDrawer.value.handleClose();
+}
+
+function refreshOuter() {
+  closeDrawer();
+  emit('refresh');
+}
+
+const gridEvents = {
+  custom({ type }: any) {
+    if (type == 'confirm') {
+      fetchList();
+    }
+  }
+};
+
+</script>
+
+<template>
+  <div class="drawer-container">
+    <el-drawer ref="editDrawer"
+               v-model="visible"
+               :close-on-click-modal="false"
+               :close-on-press-escape="false"
+               direction="btt"
+               size="80%"
+    >
+      <template #title>
+        <div class="font-medium text-xl">
+          产品属性管理:
+          <span class="italic">
+            {{ rowData.name }}
+          </span>
+        </div>
+      </template>
+      <div class="h-full p-3">
+        <vxe-grid ref="gridRef"
+                  v-bind="gridOptions"
+                  v-on="gridEvents">
+          <template #toolbar_buttons>
+            <div class="flex gap-3">
+              <PermissionButton :icon="Plus" plain round type="primary" @click="handleCreate">
+                新 增
+              </PermissionButton>
+              <el-popconfirm :icon="InfoFilled" icon-color="#626AEF" title="发布后将无法更改, 是否继续?"
+                             width="230" @confirm="handleRelease">
+                <template #reference>
+                  <PermissionButton :color="'#6466F1'" :icon="Position" plain round>
+                    发 布
+                  </PermissionButton>
+                </template>
+                <template #actions="{ confirm, cancel }">
+                  <el-button size="small" @click="cancel">No!</el-button>
+                  <el-button :color="'#6466F1'" size="small" @click="confirm">Yes?</el-button>
+                </template>
+              </el-popconfirm>
+            </div>
+          </template>
+          <template #toolbar_tools>
+            <el-button circle class="toolbar-btn mr-3" @click="handleRefresh">
+              <el-icon>
+                <Refresh />
+              </el-icon>
+            </el-button>
+          </template>
+          <template #pager>
+            <vxe-pager
+                v-model:currentPage="gridOptions.pagerConfig.page"
+                v-model:pageSize="gridOptions.pagerConfig.limit"
+                :total="gridOptions.pagerConfig.total"
+                class="mt-1.5"
+                @page-change="handlePageChange"
+            />
+          </template>
+          <template #empty>
+            <el-empty description="暂无数据" />
+          </template>
+          <template #placement="{ row }">
+            <el-tag :type=getTagType(row.section) effect="plain" round>
+              第{{ row.section }}部分
+            </el-tag>
+          </template>
+          <template #attribute="{ row }">
+            <el-tag :type=getTagType(row.attr.name)>
+              {{ row.attr.name }}
+            </el-tag>
+          </template>
+          <template #order="{ row }">
+            <el-input-number v-model="row.order" :max="100" :min="1" size="small" @change="handleUpdate(row)" />
+          </template>
+          <template #update_datetime="{ row }">
+            {{ row.update_datetime }}
+          </template>
+          <template #create_datetime="{ row }">
+            {{ row.create_datetime }}
+          </template>
+          <template #operate="{ row }">
+            <div class="flex justify-center gap-2">
+              <PermissionButton :disabled="row.is_competitors" circle plain type="warning" @click="handleEdit(row)">
+                <el-icon>
+                  <Operation />
+                </el-icon>
+              </PermissionButton>
+              <el-popconfirm
+                  :icon="InfoFilled"
+                  icon-color="#626AEF"
+                  title="你确定要删除此项吗?"
+                  width="220"
+                  @confirm="onConfirm(row)"
+              >
+                <template #reference>
+                  <PermissionButton circle plain type="danger">
+                    <el-icon>
+                      <Delete />
+                    </el-icon>
+                  </PermissionButton>
+                </template>
+                <template #actions="{ confirm, cancel }">
+                  <el-button size="small" @click="cancel">No!</el-button>
+                  <el-button
+                      size="small"
+                      type="danger"
+                      @click="confirm"
+                  >
+                    Yes?
+                  </el-button>
+                </template>
+              </el-popconfirm>
+            </div>
+          </template>
+        </vxe-grid>
+      </div>
+    </el-drawer>
+    <AttributeManageEdit v-if="editOpen" v-model="editOpen" :row-data="editRow" @refresh="handleRefresh" />
+    <AttributeManageCreate v-if="createOpen" v-model="createOpen" :row-data="rowData" @refresh="refreshOuter" />
+  </div>
+</template>
+
+<style scoped>
+.drawer-container :deep(.el-drawer__header) {
+  border-bottom: none;
+  font-weight: 500;
+}
+
+.drawer-container :deep(.el-drawer__title) {
+  font-size: 18px;
+}
+</style>

+ 136 - 0
src/views/sku-manage/product-category/component/AttributeManageCreate.vue

@@ -0,0 +1,136 @@
+<script lang="ts" setup>
+/**
+ * @Name: AttributeManageCreate.vue
+ * @Description:
+ * @Author: Cheney
+ */
+
+import { Close, Finished } from '@element-plus/icons-vue';
+import { ElMessage, FormInstance, FormRules } from 'element-plus';
+import { useResponse } from '/@/utils/useResponse';
+import * as api from '../api';
+
+
+const props: any = defineProps({
+  rowData: Object
+});
+const { rowData } = props;
+console.log('(AttributeManageCreate.vue: 19)=> rowData', rowData);
+
+const emit = defineEmits([ 'refresh' ]);
+
+const loading = ref(false);
+const createDialog = <Ref>useTemplateRef('createDialog');
+const createOpen = defineModel({ default: false });
+const btnLoading = ref(false);
+
+interface RuleForm {
+  kind: any;
+  attr: any;
+  section: any;
+  order: any;
+}
+
+const ruleFormRef = ref<FormInstance>();
+const ruleForm = reactive<RuleForm>({
+  kind: '',
+  attr: '',
+  order: '',
+  section: ''
+});
+
+const rules = reactive<FormRules<RuleForm>>({
+  attr: [ { required: true, message: '必填项', trigger: 'blur' } ],
+  section: [ { required: true, message: '必填项', trigger: 'blur' } ]
+});
+
+const submitForm = async (formEl: FormInstance | undefined) => {
+  if (!formEl) return;
+  await formEl.validate(async (valid, fields) => {
+    if (valid) {
+      const body = {
+        kind: rowData.id,
+        attr: ruleForm.attr,
+        order: ruleForm.order,
+        section: Number(ruleForm.section)
+      };
+      const res = await useResponse(api.createProductAttr, body, loading);
+      if (res.code === 2000) {
+        ElMessage.success('创建成功');
+        createDialog.value.visible = false;
+        emit('refresh');
+      }
+    } else {
+      ElMessage.error('创建失败,请检查表单');
+    }
+  });
+};
+
+const resetForm = (formEl: FormInstance | undefined) => {
+  if (!formEl) return;
+  formEl.resetFields();
+};
+
+const attributeOptions: any = ref([]);
+
+onBeforeMount(() => {
+  fetchAttributeOptions();
+});
+
+async function fetchAttributeOptions() {
+  const res = await useResponse(api.getAttributeOptions, { limit: 100 });
+  attributeOptions.value = res.data;
+}
+
+function cancelDialog() {
+  resetForm(ruleFormRef.value);
+  createDialog.value.visible = false;
+}
+
+</script>
+
+<template>
+  <el-dialog ref="createDialog"
+             v-model="createOpen" :close-on-click-modal="false" :close-on-press-escape="false" class="create-dialog"
+             style="width: 35%" title="创 建">
+    <el-form
+        ref="ruleFormRef"
+        :model="ruleForm"
+        :rules="rules"
+        class="mx-2.5 mt-7"
+        label-position="left"
+        label-width="auto"
+        status-icon>
+      <el-form-item class="font-medium" label="位 置" prop="section">
+        <el-select v-model="ruleForm.section">
+          <el-option label="第1部分" value="1" />
+          <el-option label="第2部分" value="2" />
+          <el-option label="第3部分" value="3" />
+        </el-select>
+      </el-form-item>
+      <el-form-item class="font-medium" label="属 性" prop="attr">
+        <el-select v-model="ruleForm.attr">
+          <el-option v-for="item in attributeOptions" :key="item.id" :label="item.name" :value="item.id" />
+        </el-select>
+      </el-form-item>
+      <el-form-item class="font-medium" label="顺 序" prop="order">
+        <el-input-number v-model="ruleForm.order" />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-divider />
+      <div class="flex flex-1 justify-end">
+        <el-button :icon="Close" @click="cancelDialog">取 消</el-button>
+        <el-button :icon="Finished" :loading="btnLoading" type="primary" @click="submitForm(ruleFormRef)">
+          确 定
+        </el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<style scoped>
+:deep(.create-dialog .el-dialog__footer) {
+  padding-top: 0;
+}
+</style>

+ 143 - 0
src/views/sku-manage/product-category/component/AttributeManageEdit.vue

@@ -0,0 +1,143 @@
+<script lang="ts" setup>
+/**
+ * @Name: AttributeManageEdit.vue
+ * @Description:
+ * @Author: Cheney
+ */
+
+import { Close, Finished } from '@element-plus/icons-vue';
+import { ElMessage, FormInstance, FormRules } from 'element-plus';
+import { useResponse } from '/@/utils/useResponse';
+import * as api from '../api';
+
+
+const btnLoading = ref(false);
+
+const editOpen = defineModel({ default: false });
+
+const editDrawer = <Ref>useTemplateRef('editDrawer');
+
+const props: any = defineProps({
+  rowData: Object
+});
+const { rowData } = props;
+
+const emit = defineEmits([ 'refresh' ]);
+
+interface RuleForm {
+  section: any;
+  name: any;
+  order: any;
+}
+
+const ruleFormRef = ref<FormInstance>();
+const ruleForm = reactive<RuleForm>({
+  section: rowData?.section.toString(),
+  name: rowData?.attr.id,
+  order: rowData?.order
+});
+
+const rules = reactive<FormRules<RuleForm>>({
+  section: [ { required: true, trigger: 'blur' } ],
+  name: [ { required: true, trigger: 'blur' } ]
+});
+
+const submitForm = async (formEl: FormInstance | undefined) => {
+  if (!formEl) return;
+  await formEl.validate(async (valid, fields) => {
+    if (valid) {
+      const query = {
+        attr: ruleForm.name,
+        id: rowData.id,
+        kind: rowData.kind.id,
+        order: ruleForm.order,
+        section: Number(ruleForm.section),
+        status: rowData.status
+      };
+      try {
+        const res = await useResponse(api.updateAttributeRow, query, btnLoading);
+        if (res && res.code == 2000) {
+          editOpen.value = false;
+          ElMessage.success('编辑成功');
+          emit('refresh');
+        }
+      } catch (error) {
+        console.error('Error==>', error);
+      }
+    } else {
+      console.log('error submit!', fields);
+    }
+  });
+};
+
+const attributeOptions: any = ref([]);
+
+onBeforeMount(() => {
+  fetchAttributeOptions();
+});
+
+function closeDrawer() {
+  editDrawer.value.handleClose();
+}
+
+async function fetchAttributeOptions() {
+  const res = await useResponse(api.getAttributeOptions, { limit: 100 });
+  attributeOptions.value = res.data;
+}
+</script>
+
+<template>
+  <div class="drawer-container">
+    <el-drawer ref="editDrawer"
+               v-model="editOpen"
+               :close-on-click-modal="false"
+               :close-on-press-escape="false"
+               :title="`产品种类- 编辑 `"
+               size="25%">
+      <el-form
+          ref="ruleFormRef"
+          :model="ruleForm"
+          :rules="rules"
+          class="mx-2.5 mt-7"
+          label-position="top"
+          label-width="auto"
+          status-icon>
+        <el-form-item class="font-medium" label="位 置" prop="section">
+          <el-select v-model="ruleForm.section">
+            <el-option label="第1部分" value="1" />
+            <el-option label="第2部分" value="2" />
+            <el-option label="第3部分" value="3" />
+          </el-select>
+        </el-form-item>
+        <el-form-item class="font-medium" label="属 性" prop="name">
+          <el-select v-model="ruleForm.name">
+            <el-option v-for="item in attributeOptions" :key="item.id" :label="item.name" :value="item.id" />
+          </el-select>
+        </el-form-item>
+        <el-form-item class="font-medium" label="顺 序" prop="order">
+          <el-input-number v-model="ruleForm.order" />
+        </el-form-item>
+        <el-form-item>
+          <el-divider />
+          <div class="flex flex-1 justify-end">
+            <el-button :icon="Close" @click="closeDrawer">取 消</el-button>
+            <el-button :icon="Finished" :loading="btnLoading" type="primary" @click="submitForm(ruleFormRef)">
+              确 定
+            </el-button>
+          </div>
+        </el-form-item>
+      </el-form>
+    </el-drawer>
+  </div>
+</template>
+
+<style scoped>
+.drawer-container :deep(.el-drawer__header) {
+  border-bottom: none;
+  font-weight: 500;
+}
+
+.drawer-container :deep(.el-drawer__title) {
+  font-size: 18px;
+}
+</style>

+ 11 - 1
src/views/sku-manage/product-category/component/DataTable.vue

@@ -17,6 +17,7 @@ import EditDrawer from './EditDrawer.vue';
 import NoticeDialog from '/src/views/product-manage/product-list/component/NoticeDialog.vue';
 import * as api from '../api';
 import CreateDialog from '/@/views/sku-manage/product-category/component/CreateDialog.vue';
+import AttributeManage from '/@/views/sku-manage/product-category/component/AttributeManage.vue';
 
 
 interface Parameter {
@@ -74,6 +75,8 @@ const rowData = ref({});
 
 const dialogVisible = ref(false);
 
+const visible = ref(false);
+
 onBeforeMount(() => {
   gridOptions.pagerConfig.limit = 20;
 });
@@ -109,6 +112,11 @@ function handleEdit(row: any) {
   rowData.value = row;
 }
 
+function handleAttribute(row: any) {
+  visible.value = true;
+  rowData.value = row;
+}
+
 function handleCreate() {
   createOpen.value = true;
 }
@@ -160,12 +168,14 @@ defineExpose({ fetchList });
     </template>
     <!-- 自定义列插槽 -->
     <template v-for="col in ProductCategoryColumns" #[`${col.field}`]="{ row }">
-      <DataTableSlot :key="row.id" :field="col.field" :row="row" @edit-row="handleEdit" @handle-delete="singleDelete" />
+      <DataTableSlot :key="row.id" :field="col.field" :row="row" @edit-row="handleEdit" @handle-delete="singleDelete" 
+                     @handle-attribute="handleAttribute" />
     </template>
   </vxe-grid>
   <EditDrawer v-if="editOpen" v-model="editOpen" :row-data="rowData" @refresh="handleRefresh" />
   <NoticeDialog v-if="dialogVisible" v-model="dialogVisible" :row-data="rowData" />
   <CreateDialog v-if="createOpen" v-model="createOpen" @refresh="fetchList" />
+  <AttributeManage v-if="visible" v-model="visible" :row-data="rowData" @refresh="handleRefresh"  />
 </template>
 
 <style scoped>

+ 15 - 3
src/views/sku-manage/product-category/component/DataTableSlot.vue

@@ -5,7 +5,7 @@
  * @Author: Cheney
  */
 
-import { Delete, InfoFilled, Operation } from '@element-plus/icons-vue';
+import { Delete, InfoFilled, MessageBox, Operation, Timer } from '@element-plus/icons-vue';
 import PermissionButton from '/@/components/PermissionButton/index.vue';
 import MainAttr from '/@/views/sku-manage/product-category/component/MainAttr.vue';
 
@@ -16,12 +16,16 @@ const props = defineProps<{
 }>();
 const { row, field } = props;
 
-const emit = defineEmits([ 'edit-row', 'handle-delete' ]);
+const emit = defineEmits([ 'edit-row', 'handle-delete', 'handle-attribute' ]);
 
 function handleEdit() {
   emit('edit-row', row);
 }
 
+function handleAttribute() {
+  emit('handle-attribute', row);
+}
+
 function onConfirm() {
   emit('handle-delete', row);
 }
@@ -61,10 +65,18 @@ function onConfirm() {
             </el-button>
           </template>
         </el-popconfirm>
+        <el-tooltip :disabled="row.status == '3'" :enterable="false" :show-arrow="false" content="属性管理" hide-after="0"
+                    placement="top" popper-class="custom-btn-tooltip-2">
+          <PermissionButton :color="'#6466F1'" :disabled="row.status == '3'" circle plain @click="handleAttribute">
+            <el-icon>
+              <MessageBox />
+            </el-icon>
+          </PermissionButton>
+        </el-tooltip>
       </div>
     </div>
     <div v-else-if="field === 'main'">
-     <MainAttr :attrs="row.RelatedAttrs" />
+      <MainAttr :attrs="row.RelatedAttrs" />
     </div>
     <div v-else-if="field === 'status'">
       <el-tag :type="row.status === 3 ? 'primary' : row.status === 1 ? 'warning' : row.status === 2 ? 'info' : ''">

+ 1 - 1
src/views/sku-manage/product-category/component/MainAttr.vue

@@ -51,7 +51,7 @@ const groupedAttrs = computed(() => {
         </el-tag>
         <!--</el-tooltip>-->
       </div>
-      <span class="line-separator ml-1">——</span>
+      <span class="line-separator ml-1">--></span>
     </template>
   </div>