ソースを参照

feat: prodList & prodInfo

furffico 1 年間 前
コミット
25974ddd96

+ 1 - 0
.gitignore

@@ -1,3 +1,4 @@
+tmp.*
 .DS_Store
 node_modules
 /dist

+ 14 - 33
src/crud/prod/prodList.js → src/avue/crud/prodList.js

@@ -5,11 +5,8 @@ export const tableOption = {
   columnBtn: false,
   border: true,
   selection: true,
-  // index: true,
-  // indexLabel: '#',
   stripe: true,
   menuAlign: 'center',
-  // menuWidth: 350,
   menuFixed: false,
   align: 'center',
   refreshBtn: true,
@@ -25,48 +22,32 @@ export const tableOption = {
   column: [
   {
     label: "#",
-    prop: "prodId",
+    prop: "id",
   }, {
     label: '产品名字',
-    prop: 'prodName',
+    prop: 'name',
     search: true,
-    minWidth: 300,
   }, {
     label: '商品原价',
-    prop: 'oriPrice',
-    formatter: row_currencyFormatter,
-    // sortable: true,
-  }, {
-    label: '商品现价',
     prop: 'price',
     formatter: row_currencyFormatter,
-    // sortable: true,
   }, {
     label: '商品库存',
-    prop: 'totalStocks',
-    // sortable: true,
+    prop: 'stockAmount',
+  }, {
+    label: '运费',
+    prop: 'deliverPrice',
+    formatter: row_currencyFormatter,
+  }, {
+    label: '售出',
+    prop: 'soldAmount',
+  }, {
+    label: '类别',
+    prop: 'kind',
   }, {
     label: '产品图片',
-    prop: 'pic',
+    prop: 'cover',
     type: 'upload',
-    // width: 150,
     listType: 'picture-img'
-
-  }, {
-    // width: 150,
-    label: '状态',
-    prop: 'status',
-    search: true,
-    slot: true,
-    type: 'select',
-    dicData: [
-      {
-        label: '未上架',
-        value: 0
-      }, {
-        label: '上架',
-        value: 1
-      }
-    ]
   }]
 }

+ 81 - 0
src/avue/form/prodinfo.ts

@@ -0,0 +1,81 @@
+const number_input_props = (message: string, precision: number = 0, nonzero: boolean = false) => {
+  return {
+    type: "number",
+    step: 1,
+    precision,
+    min: 0, //! 这个选项似乎没有用
+    span: 8,
+    rules: [{
+      required: true,
+      message,
+      trigger: 'blur'
+    }, {
+      validator: (_: any, v: number, callback: Function) => {
+        callback((v > 0 || v === 0 && !nonzero) ? undefined : new Error(nonzero ? "应当为正数" : "应当为非负数"))
+      },
+      trigger: 'blur'
+    }]
+  }
+}
+
+export default {
+  column: [
+    {
+      label: '产品名称',
+      prop: 'name',
+      type: 'input',
+      span: 12,
+      row: true,
+      rules: [{
+        required: true,
+        message: "请输入产品名称",
+      }]
+    }, {
+      label: '产品描述',
+      prop: 'desc',
+      type: 'textarea',
+      minRows: 3,
+      maxRows: 5,
+      row: true,
+    }, {
+      label: "价格(¥)",
+      prop: "price",
+      ...number_input_props("请输入产品价格", 2, true),
+
+    }, {
+      label: "运费(¥)",
+      ...number_input_props("请输入运费价格", 2),
+      prop: "deliverPrice",
+      row: true,
+    }, {
+      label: "库存(件)",
+      prop: "stockAmount",
+      ...number_input_props("请输入库存数"),
+    }, {
+      label: "售出(件)",
+      prop: "soldAmount",
+      ...number_input_props("请输入售出量"),
+      row: true,
+    }, {
+      label: "商品分类",
+      prop: "kind",
+      formslot: true,
+      span: 24,
+      row: true,
+    }, {
+      label: '封面图片',
+      prop: 'cover',
+      type: 'upload',
+      listType: 'picture-card',
+      span: 24,
+      accept: 'image/png, image/jpeg',
+      limit: 1,
+      fileSize: 5 * 1024,
+      propsHttp: {
+        res: 'data'
+      },
+      tip: '只能上传jpg/png图片,且不超过5MiB(暂时没用)',
+      action: ''
+    }
+  ]
+}

+ 2 - 1
src/shims-vue.d.ts

@@ -4,4 +4,5 @@ declare module '*.vue' {
 }
 
 declare module '@smallwei/avue';
-declare module 'vue-cookie';
+declare module 'vue-cookie';
+declare module '@/components/transfer-box';

+ 57 - 285
src/views/modules/prod/prodInfo.vue

@@ -1,302 +1,74 @@
 <template>
-  <div class="mod-prod-info">
-    <el-form :model="dataForm"
-             ref="dataForm"
-             label-width="100px">
-      <el-form-item label="产品图片">
-        <mul-pic-upload v-model="dataForm.imgs" />
-      </el-form-item>
-      <el-form-item label="状态">
-        <el-radio-group v-model="dataForm.status">
-          <el-radio :label="1">上架</el-radio>
-          <el-radio :label="0">下架</el-radio>
-        </el-radio-group>
-      </el-form-item>
-      <el-form-item label="产品分类"
-                    :rules="[{ required: true, message: '请选择产品分类'}]"
-                    prop="categoryId">
-        <el-col :span="8">
-          <el-cascader expand-trigger="hover"
-                        :options="category.list"
-                        :props="category.props"
-                        v-model="category.selected"
-                        change-on-select
-                        @change="handleCategoryChange">
-          </el-cascader>
-        </el-col>
-      </el-form-item>
-      <el-form-item label="产品分组" :rules="[{ required: true, message: '请选择产品分组'}]">
-        <el-col :span="8">
-          <el-select v-model="dataForm.tagList"
-                    multiple
-                    style="width: 250px"
-                    placeholder="请选择">
-            <el-option v-for="item in this.tags"
-                      :key="item.id"
-                      :label="item.title"
-                      :value="item.id">
-            </el-option>
-          </el-select>
-        </el-col>
-      </el-form-item>
-      <el-form-item label="产品名称"
-                    prop="prodName"
-                    :rules="[
-                      { required: true, message: '产品名称不能为空'},
-                      { pattern: /\s\S+|S+\s|\S/, message: '请输入正确的产品名称', trigger: 'blur' }
-                    ]">
-        <el-col :span="8">
-          <el-input v-model="dataForm.prodName"
-                    placeholder="产品名称"
-                    maxlength="50"></el-input>
-        </el-col>
-      </el-form-item>
-      <el-form-item label="产品卖点"
-                    prop="brief":rules="[
-                      { required: false, pattern: /\s\S+|S+\s|\S/, message: '请输入正确的产品卖点', trigger: 'blur' }
-                    ]">
-        <el-col :span="8">
-          <el-input v-model="dataForm.brief"
-                    type="textarea"
-                    :autosize="{minRows: 2, maxRows: 4}"
-                    placeholder="产品卖点"></el-input>
-        </el-col>
-      </el-form-item>
-      <el-form-item label="配送方式">
-        <el-checkbox v-model="dataForm.deliveryMode.hasShopDelivery">商家配送</el-checkbox>
-        <el-checkbox v-model="dataForm.deliveryMode.hasUserPickUp">用户自提</el-checkbox>
-      </el-form-item>
-      <prod-transport v-show="dataForm.deliveryMode.hasShopDelivery"
-                      v-model="dataForm.deliveryTemplateId"></prod-transport>
-      <sku-tag ref="skuTag"
-                :skuList="dataForm.skuList"
-               @change="skuTagChangeSkuHandler"></sku-tag>
-      <sku-table ref="skuTable"
-                 v-model="dataForm.skuList"
-                 :prodName.sync="dataForm.prodName"></sku-table>
-
-      <el-form-item label="产品详情"
-                    prop="content">
-        <tiny-mce v-model="dataForm.content"
-                  ref="content"
-                  style="width:1000px"></tiny-mce>
-      </el-form-item>
-      <el-form-item>
-        <el-button type="primary"
-                   @click="dataFormSubmit()">确定</el-button>
-      </el-form-item>
-    </el-form>
-  </div>
+  <avue-form :option="option" v-model="form" @submit="onSubmit">
+    <template slot="kind">
+      <el-transfer v-model="form.kind" filterable :data="categories_selections" :titles="['备选项', '已选项']"></el-transfer>
+    </template>
+  </avue-form>
 </template>
 
-<script>
-import { treeDataTranslate, idList } from '@/utils'
-import MulPicUpload from '@/components/mul-pic-upload'
-import ProdTransport from './prod-transport'
-import SkuTag from './sku-tag'
-import SkuTable from './sku-table'
-import TinyMce from '@/components/tiny-mce'
-import { Debounce } from '@/utils/debounce'
+<script lang="ts">
+import Vue from 'vue'
+import httpx, { AxiosResponse } from '@/utils/httpx'
+import formOption from "@/avue/form/prodinfo"
+import { ICategory } from '@/utils/vo'
+// import TransferBox from '@/components/transfer-box'
+
+interface ISelection {
+  key: number,
+  label: string,
+  disabled?: boolean
+  hidden?: boolean
+}
 
-export default {
-  data () {
+export default Vue.extend({
+  data() {
     return {
-      // 分类树展示与回显
-      category: {
-        list: [],
-        selected: [],
-        props: {
-          value: 'categoryId',
-          label: 'categoryName'
-        }
+      form: {
+        name: "",
+        desc: "",
+        price: 0,
+        deliverPrice: 0,
+        stockAmount: 0,
+        soldAmount: 0,
+        cover: "",
+        kind: [] as number[],
       },
-      // 规格列表
-      dataForm: {
-        prodName: '',
-        brief: '',
-        pic: '',
-        imgs: '',
-        categoryId: 0,
-        prodId: 0,
-        skuList: [],
-        tagList: [],
-        content: '',
-        status: 1,
-        deliveryMode: {
-          hasShopDelivery: false,
-          hasUserPickUp: false
-        },
-        deliveryTemplateId: null
-      },
-      tags: [],
-      resourcesUrl: process.env.VUE_APP_RESOURCES_URL
-    }
-  },
-  components: {
-    MulPicUpload,
-    ProdTransport,
-    TinyMce,
-    SkuTag,
-    SkuTable
-  },
-  computed: {
-    defalutSku () {
-      return this.$store.state.prod.defalutSku
+      option: formOption,
+      categories: [] as ICategory[],
     }
   },
-  activated () {
-    this.dataForm.prodId = this.$route.query.prodId
-    this.getDataList()
+  // components: {
+  //   TransferBox
+  // },
+
+  mounted() {
+    this.getCategoryList("")
   },
+
   methods: {
-    // 获取分类数据
-    getDataList () {
-      this.getTagList()
-      this.getCategoryList().then(() => {
-        if (this.dataForm.prodId) {
-          // 获取产品数据
-          this.$http({
-            url: this.$http.adornUrl(`/prod/prod/info/${this.dataForm.prodId}`),
-            method: 'get',
-            params: this.$http.adornParams()
-          }).then(({ data }) => {
-            this.dataForm = data
-            this.dataForm.deliveryMode = JSON.parse(data.deliveryMode)
-            this.$refs.skuTag.init(data.skuList)
-            this.$refs.skuTable.init()
-            this.category.selected = idList(this.category.list, this.dataForm.categoryId, 'categoryId', 'children').reverse()
-            this.dataForm.tagList = data.tagList
-          })
-        } else {
-          this.$nextTick(() => {
-            this.$refs['dataForm'].resetFields()
-            this.$refs.skuTag.init()
-            this.dataForm.pic = ''
-            this.dataForm.imgs = ''
-          })
-        }
+    getCategoryList(name: string = "") {
+      return httpx.post("/goodsTypes/queryGoodsTypeList", {
+        name: name, limit: 1000, page: 1
+      }).then(({ data }: AxiosResponse<{ goodsTypeList: ICategory[], total: number }>) => {
+        this.categories = data.goodsTypeList
       })
     },
-    // 获取分类信息
-    getCategoryList () {
-      return this.$http({
-        url: this.$http.adornUrl('/prod/category/listCategory'),
-        method: 'get',
-        params: this.$http.adornParams()
-      }).then(({ data }) => {
-        this.category.list = treeDataTranslate(data, 'categoryId', 'parentId')
-      })
-    },
-    // 选择分类改变事件
-    handleCategoryChange (val) {
-      this.dataForm.categoryId = val[val.length - 1]
+    onSubmit(form: typeof this.form, done: Function) {
+      console.log(form)
+      // TODO
+      done()
     },
-    // 表单提交
-    dataFormSubmit: Debounce(function () {
-      this.$refs['dataForm'].validate((valid) => {
-        if (!valid) {
-          return
-        }
-        if (!this.dataForm.imgs) {
-          this.errorMsg('请选择图片上传')
-          return
-        }
-        if (!this.dataForm.deliveryMode) {
-          this.errorMsg('请选择配送方式')
-          return
-        }
-        if (this.dataForm.deliveryMode.hasShopDelivery && !this.dataForm.deliveryTemplateId) {
-          this.errorMsg('请选择运费模板')
-          return
-        }
-        let param = Object.assign({}, this.dataForm)
-        // 设置价格和库存
-        this.paramSetPriceAndStocks(param)
+  },
 
-        param.deliveryMode = undefined
-        param.deliveryModeVo = this.dataForm.deliveryMode
-        // 商品主图
-        param.pic = this.dataForm.imgs.split(',')[0]
-        this.$http({
-          url: this.$http.adornUrl(`/prod/prod`),
-          method: param.prodId ? 'put' : 'post',
-          data: this.$http.adornData(param)
-        }).then(({ data }) => {
-          this.$message({
-            message: '操作成功',
-            type: 'success',
-            duration: 1500,
-            onClose: () => {
-              this.visible = false
-              this.$store.commit('common/removeMainActiveTab')
-              this.$router.push({ name: 'prod-prodList' })
-              this.$emit('refreshDataList')
-            }
-          })
-        })
-      })
-    }),
-    paramSetPriceAndStocks (param) {
-      // 获取规格属性信息
-      // param.skuList = this.$refs.prodSpec.getTableSpecData()
-      // 商品库存
-      param.totalStocks = 0
-      // 商品价格
-      param.price = 0
-      // 商品原价
-      param.oriPrice = 0
-      // 商品实际库存
-      for (let i = 0; i < param.skuList.length; i++) {
-        const element = param.skuList[i]
-        if (element.status !== 1) {
-          continue
-        }
-        if (param.price === 0) {
-          param.price = element.price ? Number.parseFloat(element.price) : 0
-        }
-        // 商品价格为最低价的那件商品的价格
-        param.price = Math.min(param.price, element.price)
-        if (param.price === element.price) {
-          param.oriPrice = element.oriPrice ? Number.parseFloat(element.oriPrice) : 0
-        }
-        param.totalStocks += element.stocks ? Number.parseInt(element.stocks) : 0
-      }
-      // 如果sku没有商品名称,则使用商品的商品名称
-      if (param.skuList.length === 1) {
-        param.skuList[0].prodName = this.dataForm.prodName
-      }
-    },
-    skuTagChangeSkuHandler (skuList) {
-      const prodName = this.dataForm.prodName
-      skuList.forEach(sku => {
-        if (sku.properties) {
-          sku.skuName = ''
-          let properties = sku.properties.split(';')
-          for (const propertiesKey in properties) {
-            sku.skuName += properties[propertiesKey].split(':')[1] + ' '
-          }
-          sku.prodName = prodName + ' ' + sku.skuName
+  computed: {
+    categories_selections(): ISelection[] {
+      return this.categories.map((v, i) => {
+        return {
+          key: v.id,
+          label: v.name,
         }
       })
-      this.dataForm.skuList = skuList
-    },
-    errorMsg (message) {
-      this.$message({
-        message: message,
-        type: 'error',
-        duration: 1500
-      })
-    },
-    // 获取所有的分组信息
-    getTagList () {
-      this.$http({
-        url: this.$http.adornUrl('/prod/prodTag/listTagList'),
-        method: 'get',
-        params: this.$http.adornParams()
-      }).then(({ data }) => {
-        this.tags = data
-      })
     }
-  }
-}
-</script>
+  },
+})
+</script>

+ 65 - 95
src/views/modules/prod/prodList.vue

@@ -1,59 +1,27 @@
 <template>
-  <div class="mod-prod">
-    <avue-crud ref="crud"
-               :page="page"
-               :data="dataList"
-               :table-loading="dataListLoading"
-               :permission="permission"
-               :option="tableOption"
-               @search-change="searchChange"
-               @selection-change="selectionChange"
-               @on-load="getDataList"
-               >
-      <template slot="menuLeft">
-        <el-button type="primary"
-                   icon="el-icon-plus"
-                   size="small"
-                   v-if="isAuth('shop:pickAddr:save')"
-                   @click.stop="addOrUpdateHandle()">新增</el-button>
+  <avue-crud ref="crud" :page="page" :data="dataList" :table-loading="dataListLoading" :permission="permission"
+    :option="tableOption" @search-change="searchChange" @selection-change="selectionChange" @on-load="getDataList">
+    <template slot="menuLeft">
+      <el-button type="primary" icon="el-icon-plus" size="small" v-if="isAuth('shop:pickAddr:save')"
+        @click.stop="addOrUpdateHandle()">新增</el-button>
+      <el-button type="danger" @click="deleteHandle()" size="small" v-if="isAuth('shop:pickAddr:delete')"
+        :disabled="dataListSelections.length <= 0">批量删除</el-button>
+    </template>
 
-        <el-button type="danger"
-                   @click="deleteHandle()"
-                   size="small"
-                   v-if="isAuth('shop:pickAddr:delete')"
-                   :disabled="dataListSelections.length <= 0">批量删除</el-button>
-      </template>
-
-      <template slot-scope="scope"
-                slot="status">
-        <el-tag v-if="scope.row.status === 1"
-                size="small">上架</el-tag>
-        <el-tag v-else
-                size="small">未上架</el-tag>
-      </template>
-
-      <template slot-scope="scope"
-                slot="menu">
-        <el-button type="primary"
-                   icon="el-icon-edit"
-                   size="small"
-                   v-if="isAuth('prod:prod:update')"
-                   @click="addOrUpdateHandle(scope.row.prodId)">修改</el-button>
-        <el-button type="danger"
-                   icon="el-icon-delete"
-                   size="small"
-                   v-if="isAuth('prod:prod:delete')"
-                   @click="deleteHandle(scope.row.prodId)">删除</el-button>
-
-      </template>
-    </avue-crud>
-  </div>
+    <template slot-scope="scope" slot="menu">
+      <el-button type="primary" icon="el-icon-edit" size="small" v-if="isAuth('prod:prod:update')"
+        @click="addOrUpdateHandle(scope.row.prodId)">修改</el-button>
+      <el-button type="danger" icon="el-icon-delete" size="small" v-if="isAuth('prod:prod:delete')"
+        @click="deleteGood(scope.row.id)">删除</el-button>
+    </template>
+  </avue-crud>
 </template>
 
 <script>
-import { tableOption } from '@/crud/prod/prodList'
+import { tableOption } from '@/avue/crud/prodList.js'
+import Axios from 'axios'
 export default {
-  data () {
+  data() {
     return {
       dataForm: {
         prodName: ''
@@ -74,48 +42,54 @@ export default {
     }
   },
   methods: {
-    onedit(...data){
-      console.log(...data)
-    },
     // 获取数据列表
-    getDataList (page, params, done) {
+    getDataList(page, params, done) {
       this.dataListLoading = true
-      this.$http({
-        url: this.$http.adornUrl('/prod/prod/page'),
-        method: 'get',
-        params: this.$http.adornParams(
-          Object.assign(
-            {
-              current: page == null ? this.page.currentPage : page.currentPage,
-              size: page == null ? this.page.pageSize : page.pageSize
-            },
-            params
-          )
-        )
+      Axios.post(this.$http.adornUrl('/goods/queryGoodList'), {
+        name: params?.name || "",
+        limit: page == null ? this.page.pageSize : page.pageSize,
+        page: page == null ? this.page.currentPage : page.currentPage,
       }).then(({ data }) => {
-        this.dataList = data.records
-        for (const key in this.dataList) {
-          if (this.dataList.hasOwnProperty(key)) {
-            const element = this.dataList[key]
-            element.imgs = element.imgs.split(',')[0]
-          }
-        }
-        this.page.total = data.total
+        console.log(data)
+        const items = data.data.goodList
+        this.dataList = items
+        // this.page.total = data.total
         this.dataListLoading = false
         if (done) {
           done()
         }
       })
     },
+    deleteGood(id) {
+      this.$confirm(`确定进行删除操作?`, '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        console.log(id)
+        Axios.post("/goods/deleteGood", { id }
+        ).then(({ data }) => {
+          console.log(data)
+          this.$message({
+            message: '操作成功',
+            type: 'success',
+            duration: 1500,
+            onClose: () => {
+              this.getDataList()
+            }
+          })
+        })
+      })
+    },
     // 新增 / 修改
-    addOrUpdateHandle (id) {
+    addOrUpdateHandle(id) {
       this.$router.push({
         path: '/prodInfo',
         query: { prodId: id }
       })
     },
     // 删除和批量删除
-    deleteHandle (id) {
+    deleteHandle(id) {
       let prodIds = this.getSeleProdIds()
       if (id) {
         prodIds.push(id)
@@ -124,35 +98,31 @@ export default {
         confirmButtonText: '确定',
         cancelButtonText: '取消',
         type: 'warning'
-      })
-        .then(() => {
-          this.$http({
-            url: this.$http.adornUrl(`/prod/prod`),
-            method: 'delete',
-            data: this.$http.adornData(prodIds, false)
-          }).then(({ data }) => {
-            this.$message({
-              message: '操作成功',
-              type: 'success',
-              duration: 1500,
-              onClose: () => {
-                this.getDataList(this.page)
-              }
-            })
+      }).then(() => {
+        this.$http({
+          url: this.$http.adornUrl(`/prod/prod`),
+          method: 'delete',
+          data: this.$http.adornData(prodIds, false)
+        }).then(({ data }) => {
+          this.getDataList(this.page)
+          this.$message({
+            message: '操作成功',
+            type: 'success',
+            duration: 1500
           })
         })
-        .catch(() => { })
+      })
     },
     // 条件查询
-    searchChange (params, done) {
+    searchChange(params, done) {
       this.getDataList(this.page, params, done)
     },
     // 多选变化
-    selectionChange (val) {
+    selectionChange(val) {
       this.dataListSelections = val
     },
     // 获取选中的商品Id列表
-    getSeleProdIds () {
+    getSeleProdIds() {
       return this.dataListSelections.map(item => {
         return item.prodId
       })