Ver Fonte

商品类目,商品信息

1018653686@qq.com há 1 ano atrás
pai
commit
828d2ea292

+ 5 - 0
src/api/XMHJC/product.js

@@ -0,0 +1,5 @@
+// const { proxy } = getCurrentInstance();
+
+export function category_list(data) {
+    return proxy.post("/productCategory/page", data)
+}

+ 289 - 0
src/views/XMHJC/product/category/index.vue

@@ -0,0 +1,289 @@
+<template>
+  <div class="productCategory">
+    <!-- <Banner /> -->
+    <div class="content">
+      <byTable
+        :source="sourceList.data"
+        :pagination="sourceList.pagination"
+        :config="config"
+        :loading="loading"
+        highlight-current-row
+        :action-list="[
+          {
+            text: '添加类目',
+            action: () => openModal('add'),
+          },
+        ]"
+        @get-list="getList">
+        <template #slotName="{ item }">
+          {{ item.createTime }}
+        </template>
+      </byTable>
+    </div>
+    <el-dialog :title="modalType == 'add' ? '新增' : '编辑'" v-model="dialogVisible" width="800" v-loading="loading">
+      <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="byform"> </byForm>
+      <template #footer>
+        <el-button @click="dialogVisible = false" size="large">取 消</el-button>
+        <el-button type="primary" v-no-double-click="submitForm" size="large" :loading="submitLoading">确 定</el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+/* eslint-disable vue/no-unused-components */
+import { ElMessage, ElMessageBox } from "element-plus";
+import byTable from "@/components/byTable/index.vue";
+import byForm from "@/components/byForm/index.vue";
+import { computed, ref } from "vue";
+import {getDictOneByXmhjc} from "@/api/XMHJC/common";
+const loading = ref(false);
+const submitLoading = ref(false);
+const enableStatus = ref([]);
+const sourceList = ref({
+  data: [],
+  pagination: {
+    total: 3,
+    pageNum: 1,
+    pageSize: 10,
+  },
+});
+let dialogVisible = ref(false);
+let modalType = ref("add");
+let rules = ref({
+  name: [{ required: true, message: "请输入名称" }],
+  status: [{ required: true, message: "请选择启用状态", trigger: "change" }],
+});
+const { proxy } = getCurrentInstance();
+const config = computed(() => {
+  return [
+    {
+        attrs: {
+            label: "序号",
+            prop: "id",
+        },
+    },
+    {
+      attrs: {
+        label: "名称",
+        prop: "name",
+      },
+    },
+    {
+      attrs: {
+        label: "编号",
+        prop: "code",
+      },
+    },
+    {
+      attrs: {
+        label: "排序",
+        prop: "sort",
+        align: "center",
+      },
+    },
+    {
+      attrs: {
+        label: "状态",
+        prop: "status",
+      },
+      render(type) {
+        return proxy.dictValueLabel(type, enableStatus.value);
+      },
+    },
+    {
+      attrs: {
+        label: "操作",
+        width: "200",
+        align: "right",
+      },
+      // 渲染 el-button,一般用在最后一列。
+      renderHTML(row) {
+        return [
+          {
+            attrs: {
+              label: row.status == 1 ? "禁用" : "启用",
+              type: "primary",
+              text: true,
+            },
+            el: "button",
+            click() {
+              changeStatus(row);
+            },
+          },
+          {
+            attrs: {
+              label: "编辑",
+              type: "primary",
+              text: true,
+            },
+            el: "button",
+            click() {
+              getDetail(row);
+            },
+          },
+          {
+            attrs: {
+              label: "删除",
+              type: "danger",
+              text: true,
+            },
+            el: "button",
+            click() {
+              del(row);
+            },
+          },
+        ];
+      },
+    },
+  ];
+});
+
+let formData = reactive({
+  data: {},
+  treeData: [],
+});
+const formOption = reactive({
+  inline: true,
+  labelWidth: 100,
+  itemWidth: 100,
+  rules: [],
+});
+const byform = ref(null);
+const formConfig = computed(() => {
+  return [
+    {
+      type: "input",
+      prop: "name",
+      label: "名称",
+      itemWidth: 100,
+      maxlength: 10,
+      itemType: "text",
+    },
+    {
+      type: "input",
+      prop: "code",
+      label: "编号",
+      maxlength: 10,
+    },
+    {
+      label: "启用状态",
+      prop: "status",
+      type: "select",
+      data: enableStatus.value,
+      required: true,
+    },
+    {
+      type: "input",
+      itemType: "number",
+      prop: "sort",
+      label: "排序",
+      style: {
+        width: "50%",
+      },
+    },
+  ];
+});
+const getList = async (req) => {
+  sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
+  loading.value = true;
+    proxy.post("/productCategory/page", sourceList.value.pagination).then((message) => {
+    console.log(message);
+    sourceList.value.data = message.rows;
+    sourceList.value.pagination.total = message.total;
+    setTimeout(() => {
+      loading.value = false;
+    }, 200);
+  });
+};
+const openModal = () => {
+  dialogVisible.value = true;
+  modalType.value = "add";
+  formData.data = {};
+};
+const submitForm = () => {
+  byform.value.handleSubmit((valid) => {
+    submitLoading.value = true;
+    proxy
+      .post("/productCategory/" + modalType.value, formData.data)
+      .then((res) => {
+        ElMessage({
+          message: modalType.value == "add" ? "添加成功" : "编辑成功",
+          type: "success",
+        });
+        dialogVisible.value = false;
+        submitLoading.value = false;
+        getList();
+      })
+      .catch((err) => {
+        submitLoading.value = false;
+      });
+  });
+};
+
+const changeStatus = (row) => {
+  modalType.value = "edit";
+  let status = row.status=='1' ? 0 : 1;
+  proxy.post("/productCategory/detail", { id: row.id }).then((res) => {
+    res.status = status;
+    formData.data = res;
+    ElMessageBox.confirm("你是否确认此操作?", "提示", {
+      confirmButtonText: "确定",
+      cancelButtonText: "取消",
+      type: "warning",
+    }).then(() => {
+      // 更新状态
+      proxy.post("/productCategory/" + modalType.value, formData.data).then((res) => {
+        ElMessage({
+          message: "操作成功",
+          type: "success",
+        });
+        getList();
+      });
+    });
+  });
+};
+
+//编辑详情
+const getDetail = (row) => {
+  modalType.value = "edit";
+  proxy.post("/productCategory/detail", { id: row.id }).then((res) => {
+    formData.data = res;
+    dialogVisible.value = true;
+  });
+};
+
+//删除
+const del = (row) => {
+  modalType.value = "edit";
+  ElMessageBox.confirm("你是否确认此操作?", "提示", {
+    confirmButtonText: "确定",
+    cancelButtonText: "取消",
+    type: "warning",
+  }).then(() => {
+    proxy.post("/productCategory/delete", { id: row.id }).then((res) => {
+        ElMessage({
+          message: "操作成功",
+          type: "success",
+        });
+        getList();
+      });
+  });
+};
+//获取字典
+const getDictlist = async () => {
+  const res = await getDictOneByXmhjc(["enable_status"]);
+  enableStatus.value = res["enable_status"].map((x) => ({
+    label: x.dictValue,
+    value: x.dictKey,
+  }));
+};
+getList();
+getDictlist();
+</script>
+
+<style lang="scss" scoped>
+.tenant {
+  padding: 20px;
+}
+</style>

+ 482 - 0
src/views/XMHJC/product/info/index.vue

@@ -0,0 +1,482 @@
+<template>
+    <div class="productInfo">
+        <!-- <Banner /> -->
+        <div class="content">
+            <byTable
+                    :source="sourceList.data"
+                    :pagination="sourceList.pagination"
+                    :config="config"
+                    :loading="loading"
+                    highlight-current-row
+                    :action-list="[
+          {
+            text: '添加商品',
+            action: () => openModal('add'),
+          },
+        ]"
+                    @get-list="getList">
+                <template #slotName="{ item }">
+                    {{ item.createTime }}
+                </template>
+            </byTable>
+        </div>
+        <el-dialog z-index="100"  :title="modalType == 'add' ? '新增' : '编辑'" v-model="dialogVisible" width="800" v-loading="loading">
+            <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="byform">
+                <template #coverUrl>
+                    <el-row style="width: 100%">
+                        <el-col :span="6">
+                            <el-form-item prop="coverUrl">
+                                <el-upload
+                                        class="avatar-uploader"
+                                        action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
+                                        :data="coverUrlOne"
+                                        :show-file-list="false"
+                                        accept=".gif, .jpeg, .jpg, .png"
+                                        :on-success="coverUrlSuccess"
+                                        :before-upload="uploadCoverUrl">
+                                    <el-image
+                                            v-if="formData.data.coverUrlList && formData.data.coverUrlList.length > 0"
+                                            :src="formData.data.coverUrlList[0].fileUrl"
+                                            fit="scale-down"
+                                            class="avatar" />
+                                    <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
+                                </el-upload>
+                                <el-button
+                                        class="delete-btn"
+                                        type="danger"
+                                        v-if="formData.data.coverUrlList && formData.data.coverUrlList.length > 0"
+                                        @click="formData.data.coverUrlList = []">
+                                    删除
+                                </el-button>
+                            </el-form-item>
+                        </el-col>
+                    </el-row>
+                </template>
+                <template #contentImg>
+                    <el-row style="width: 100%">
+                        <el-col :span="6">
+                            <el-form-item  prop="contentImg">
+                                <el-upload
+                                        class="avatar-uploader"
+                                        action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
+                                        :data="contentImgOne"
+                                        :show-file-list="false"
+                                        accept=".gif, .jpeg, .jpg, .png"
+                                        :on-success="contentImgSuccess"
+                                        :before-upload="uploadContentImg">
+                                    <el-image
+                                            v-if="formData.data.contentImgList && formData.data.contentImgList.length > 0"
+                                            :src="formData.data.contentImgList[0].fileUrl"
+                                            fit="scale-down"
+                                            class="avatar" />
+                                    <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
+                                </el-upload>
+                                <el-button
+                                        class="delete-btn"
+                                        type="danger"
+                                        v-if="formData.data.contentImgList && formData.data.contentImgList.length > 0"
+                                        @click="formData.data.contentImgList = []">
+                                    删除
+                                </el-button>
+                            </el-form-item>
+                        </el-col>
+                    </el-row>
+                </template>
+                <template #content>
+                    <div style="width: 100%" v-if="dialogVisible">
+                        <TinymceEditor
+                                :value="formData.data.content"
+                                @updateValue="updateContentValue"
+                                ref="contentEditor"
+                        />
+                    </div>
+                </template>
+            </byForm>
+            <template #footer>
+                <el-button @click="dialogVisible = false" size="large">取 消</el-button>
+                <el-button type="primary" v-no-double-click="submitForm" size="large" :loading="submitLoading">确 定</el-button>
+            </template>
+        </el-dialog>
+    </div>
+</template>
+
+<script setup>
+/* eslint-disable vue/no-unused-components */
+import { ElMessage, ElMessageBox } from "element-plus";
+import byTable from "@/components/byTable/index.vue";
+import byForm from "@/components/byForm/index.vue";
+import {getDictOneByXmhjc, getFileList, getFileStr} from "@/api/XMHJC/common";
+import { computed, ref } from "vue";
+import TinymceEditor from "@/components/Editor/TinymceEditor.vue";
+const loading = ref(false);
+const submitLoading = ref(false);
+const specDict = ref([]);
+const enableStatus = ref([]);
+const contentType = ref([]);
+const sourceList = ref({
+    data: [],
+    pagination: {
+        total: 3,
+        pageNum: 1,
+        pageSize: 10,
+    },
+});
+let dialogVisible = ref(false);
+let modalType = ref("add");
+let rules = ref({
+    title: [{ required: true, message: "请输入标题" }],
+    subheading: [{ required: true, message: "请输入副标题" }],
+    name: [{ required: true, message: "请上传封面图片" }],
+    specList: [{ required: true, message: "请选择产品规格" }],
+    status: [{ required: true, message: "请选择启用状态" }],
+    contentType: [{ required: true, message: "请选择详情类型" }],
+});
+const { proxy } = getCurrentInstance();
+const config = computed(() => {
+    return [
+        {
+            attrs: {
+                label: "序号",
+                prop: "id",
+            },
+        },
+        {
+            attrs: {
+                label: "商品名称",
+                prop: "title",
+            },
+        },
+        {
+            attrs: {
+                label: "副标题",
+                prop: "subheading",
+            },
+        },
+        {
+            attrs: {
+                label: "产品规格",
+                prop: "spec",
+            },
+        },
+        {
+            attrs: {
+                label: "排序",
+                prop: "sort",
+                align: "center",
+            },
+        },
+        {
+            attrs: {
+                label: "状态",
+                prop: "status",
+            },
+            render(type) {
+                return proxy.dictValueLabel(type, enableStatus.value);
+            },
+        },
+        {
+            attrs: {
+                label: "操作",
+                width: "200",
+                align: "right",
+            },
+            // 渲染 el-button,一般用在最后一列。
+            renderHTML(row) {
+                return [
+                    {
+                        attrs: {
+                            label: row.status == 1 ? "禁用" : "启用",
+                            type: "primary",
+                            text: true,
+                        },
+                        el: "button",
+                        click() {
+                            changeStatus(row);
+                        },
+                    },
+                    {
+                        attrs: {
+                            label: "编辑",
+                            type: "primary",
+                            text: true,
+                        },
+                        el: "button",
+                        click() {
+                            getDetail(row);
+                        },
+                    },
+                    {
+                        attrs: {
+                            label: "删除",
+                            type: "danger",
+                            text: true,
+                        },
+                        el: "button",
+                        click() {
+                            del(row);
+                        },
+                    },
+                ];
+            },
+        },
+    ];
+});
+
+let formData = reactive({
+    data: {
+        "contentImgList": [],
+        "coverUrlList": [],
+    },
+});
+const formOption = reactive({
+    inline: true,
+    labelWidth: 100,
+    itemWidth: 100,
+    rules: [],
+});
+const byform = ref(null);
+const formConfig = computed(() => {
+    return [
+        {
+            type: "input",
+            prop: "title",
+            label: "标题",
+            itemWidth: 100,
+            maxlength: 30,
+            itemType: "text",
+        },
+        {
+            type: "input",
+            prop: "subheading",
+            label: "副标题",
+            maxlength: 50,
+        },
+        {
+            type: "slot",
+            slotName: "coverUrl",
+            prop: "coverUrl",
+            label: "封面图片",
+        },
+        {
+            type: "select",
+            prop: "specList",
+            label: "产品规格",
+            itemWidth: 100,
+            multiple: true,
+            data: specDict.value,
+            style: {
+                width: "50%",
+            },
+            disabled: false,
+        },
+        {
+            label: "启用状态",
+            prop: "status",
+            type: "select",
+            data: enableStatus.value,
+        },
+        {
+            type: "input",
+            itemType: "number",
+            prop: "sort",
+            label: "排序",
+            style: {
+                width: "50%",
+            },
+        },
+        {
+            type: "select",
+            prop: "contentType",
+            label: "详情类型",
+            data: contentType.value,
+            required: true,
+        },
+        {
+            type: "slot",
+            prop: "contentImgList",
+            slotName: "contentImg",
+            label: "详情图片",
+            isShow: formData.data.contentType == "1"
+        },
+        {
+            type: "slot",
+            prop: "content",
+            slotName: "content",
+            label: "详情内容",
+            isShow: formData.data.contentType == "2"
+        },
+    ];
+});
+const getList = async (req) => {
+    sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
+    loading.value = true;
+    proxy.post("/productInfo/page", sourceList.value.pagination).then((message) => {
+        console.log(message);
+        sourceList.value.data = message.rows;
+        sourceList.value.pagination.total = message.total;
+        setTimeout(() => {
+            loading.value = false;
+        }, 200);
+    });
+};
+const openModal = () => {
+    dialogVisible.value = true;
+    modalType.value = "add";
+    formData.data = {};
+};
+const submitForm = () => {
+    byform.value.handleSubmit((valid) => {
+        submitLoading.value = true;
+        proxy
+            .post("/productInfo/" + modalType.value, formData.data)
+            .then((res) => {
+                ElMessage({
+                    message: modalType.value == "add" ? "添加成功" : "编辑成功",
+                    type: "success",
+                });
+                dialogVisible.value = false;
+                submitLoading.value = false;
+                getList();
+            })
+            .catch((err) => {
+                submitLoading.value = false;
+            });
+    });
+};
+
+const changeStatus = (row) => {
+    modalType.value = "edit";
+    let status = row.status=='1' ? 0 : 1;
+    proxy.post("/productInfo/detail", { id: row.id }).then((res) => {
+        res.status = status;
+        formData.data = res;
+        ElMessageBox.confirm("你是否确认此操作?", "提示", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning",
+        }).then(() => {
+            // 删除
+            proxy.post("/productInfo/" + modalType.value, formData.data).then((res) => {
+                ElMessage({
+                    message: "操作成功",
+                    type: "success",
+                });
+                getList();
+            });
+        });
+    });
+};
+
+//编辑详情
+const getDetail = (row) => {
+    modalType.value = "edit";
+    proxy.post("/productInfo/detail", { id: row.id }).then((res) => {
+        formData.data = res;
+        getFileList({businessIdList: [res.id], fileType: 1}).then((resFile1) => {
+            formData.data.coverUrlList = resFile1.data[res.id];
+            dialogVisible.value = true;
+        });
+    });
+};
+
+//删除
+const del = (row) => {
+    modalType.value = "edit";
+    ElMessageBox.confirm("你是否确认此操作?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+    }).then(() => {
+        proxy.post("/productInfo/delete", { id: row.id }).then((res) => {
+            ElMessage({
+                message: "操作成功",
+                type: "success",
+            });
+            getList();
+        });
+    });
+};
+
+
+//获取字典
+const getDictlist = async () => {
+    const res = await getDictOneByXmhjc(["enable_status", "product_spec", "content_type"]);
+    enableStatus.value = res["enable_status"].map((x) => ({
+        label: x.dictValue,
+        value: x.dictKey,
+    }));
+    specDict.value = res["product_spec"].map((x) => ({
+        label: x.dictValue,
+        value: x.dictKey,
+    }));
+    contentType.value = res["content_type"].map((x) => ({
+        label: x.dictValue,
+        value: x.dictKey,
+    }));
+};
+
+
+//富文本相关
+const updateContentValue = (val) => {
+    formData.data.content = val;
+};
+
+
+//图片上传相关
+const contentImgOne = ref({});
+const uploadContentImg = async (file) => {
+    const res = await getFileStr({ fileName: file.name });
+    contentImgOne.value = res.data.uploadBody;
+    file.id = res.data.id;
+    file.fileName = res.data.fileName;
+    file.fileUrl = res.data.fileUrl;
+    return true;
+};
+
+const contentImgSuccess = (response, uploadFile) => {
+    formData.data.contentImgList = [
+        {
+            id: uploadFile.raw.id,
+            fileName: uploadFile.raw.fileName,
+            fileUrl: uploadFile.raw.fileUrl,
+        },
+    ];
+};
+
+const coverUrlOne = ref({});
+const uploadCoverUrl = async (file) => {
+    const res = await getFileStr({ fileName: file.name });
+    coverUrlOne.value = res.data.uploadBody;
+    file.id = res.data.id;
+    file.fileName = res.data.fileName;
+    file.fileUrl = res.data.fileUrl;
+    return true;
+};
+
+const coverUrlSuccess = (response, uploadFile) => {
+    formData.data.coverUrlList = [
+        {
+            id: uploadFile.raw.id,
+            fileName: uploadFile.raw.fileName,
+            fileUrl: uploadFile.raw.fileUrl,
+        },
+    ];
+};
+
+getDictlist();
+getList();
+</script>
+
+<style lang="scss" scoped>
+.tenant {
+  padding: 20px;
+}
+.el-icon.avatar-uploader-icon {
+  font-size: 28px;
+  color: #8c939d;
+  width: 110px;
+  height: 110px;
+  text-align: center;
+  border: 1px dashed var(--el-border-color);
+}
+</style>