mayf
2024-09-03 3a68c4380090ce1ded8941ef30d22a8a576ca6a3
优惠券,会员等级,积分商城dev
已修改4个文件
已添加17个文件
2295 ■■■■■ 文件已修改
assets/coupon/detail.scss 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
components/base-sidebar.vue 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
components/coupon/member-rule.vue 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
components/coupon/select-shop-user.vue 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
components/input-select.vue 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
config/default-dev.json5 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/marketing/coupon/activity/_id.vue 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/marketing/coupon/activity/index.vue 259 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/marketing/coupon/member/_id.vue 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/marketing/coupon/member/index.vue 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/marketing/coupon/user/_id.vue 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/marketing/coupon/user/index.vue 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/marketing/member-level.vue 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/marketing/point-mall/coupon/_id.vue 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/marketing/point-mall/coupon/index.vue 238 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/marketing/point-mall/goods.vue 242 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pages/marketing/point-mall/point-distribution.vue 224 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
plugins/mixins/coupon-detail.vue 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
utils/coupon-form.js 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
assets/coupon/detail.scss
对比新文件
@@ -0,0 +1,11 @@
.coupon-detail {
  border-radius: 0;
  .el-bus-title {
    margin-bottom: 10px;
  }
  ::v-deep {
    .el-form-item {
      margin-bottom: 0;
    }
  }
}
components/base-sidebar.vue
@@ -162,26 +162,19 @@
        ::v-deep .el-submenu__icon-arrow {
          color: #fff;
        }
        .el-submenu {
          @for $i from 1 through 4 {
            .el-menu-item {
              padding-left: 64px !important;
        .el-menu-item {
          @for $i from 2 through 4 {
            &.el-bus-level-#{$i} {
              padding-left: 20px * $i + 24px !important;
            }
            .el-submenu.level-#{$i} {
              ::v-deep {
                .el-submenu__title {
                  @if $i==0 {
                    padding-left: 20px !important;
                  } @else {
                    padding-left: 32px * ($i + 1) !important;
                  }
                }
              }
          }
        }
        .el-menu {
          @for $i from 2 through 4 {
            &:has(.el-submenu.el-bus-level-#{$i}) {
              .el-menu-item {
                @if $i==0 {
                  padding-left: 64px !important;
                } @else {
                  padding-left: 32px * ($i + 1) + 10px !important;
                &.el-bus-level-#{$i} {
                  padding-left: 20px * $i !important;
                }
              }
            }
components/coupon/member-rule.vue
对比新文件
@@ -0,0 +1,125 @@
<template>
  <div class="member-rule">
    <div class="mr-8">消费</div>
    <el-input-number
      v-model="amountValue"
      v-bind="inputAttrs"
      @input="onAmountChange"
    ></el-input-number>
    <div class="mx-8">元等于</div>
    <el-input-number
      v-model="growthValue"
      v-bind="inputAttrs"
      @input="onGrowthChange"
    ></el-input-number>
    <div class="ml-8">成长值</div>
  </div>
</template>
<script>
import { t } from 'el-business'
import utils from 'el-business-utils'
export default {
  props: {
    value: {
      type: Array,
      default: () => [],
    },
  },
  rules(item) {
    const errorMsg = `${t('elBus.common.pleaseEnter')}${
      item.label ? item.label.replace(/:/g, '').replace(/:/g, '') : ''
    }`
    return [
      {
        required: true,
        message: errorMsg,
      },
      {
        validator: (rule, value, callback) => {
          if (
            Array.isArray(value) &&
            value.filter((i) => !utils.isTrueEmpty(i)).length === 2
          ) {
            callback()
          } else {
            callback(new Error(errorMsg))
          }
        },
      },
    ]
  },
  inputFormat(row, item) {
    if (
      Array.isArray(item.commonFormatProps) &&
      item.commonFormatProps.length === 2
    ) {
      const amount = item.commonFormatProps[0]
      const growth = item.commonFormatProps[1]
      if (amount in row || growth in row) {
        return [row[amount], row[growth]]
      }
    } else {
      console.warn('please set commonFormatProps')
    }
  },
  outputFormat(val, item) {
    if (
      Array.isArray(item.commonFormatProps) &&
      item.commonFormatProps.length === 2
    ) {
      const amount = item.commonFormatProps[0]
      const growth = item.commonFormatProps[1]
      return {
        [amount]: !utils.isTrueEmpty(val?.[0]) ? val[0] : null,
        [growth]: !utils.isTrueEmpty(val?.[1]) ? val[1] : null,
      }
    } else {
      console.warn('please set commonFormatProps')
    }
  },
  data() {
    return {
      amountValue: null,
      growthValue: null,
      inputAttrs: {
        precision: 0,
        min: 0,
        controls: false,
      },
    }
  },
  watch: {
    value: {
      immediate: true,
      handler(value) {
        value = value || []
        this.amountValue = value?.[0] || undefined
        this.growthValue = value?.[1] || undefined
      },
    },
  },
  methods: {
    onAmountChange(e) {
      const value = [e, this.growthValue]
      this.emitValue(value)
    },
    onGrowthChange(e) {
      const value = [this.amountValue, e]
      this.emitValue(value)
    },
    emitValue(value) {
      this.$emit('input', value)
      this.$emit('change', value)
    },
  },
}
</script>
<style lang="scss" scoped>
.member-rule {
  display: flex;
  align-items: center;
}
</style>
components/coupon/select-shop-user.vue
对比新文件
@@ -0,0 +1,187 @@
<template>
  <div class="select-shop-user">
    <el-button v-if="!disabled" type="primary" @click="chooseUser"
      >指定用户</el-button
    >
    <el-table v-if="value && value.length > 0" :data="value">
      <el-table-column label="id" prop="id"></el-table-column>
      <el-table-column label="店铺名称" prop="name"></el-table-column>
      <el-table-column label="联系方式" prop="tel"></el-table-column>
      <el-table-column v-if="!disabled" label="操作">
        <template #default="{ $index }">
          <text-button type="danger" @click="deleteUser($index)"
            >删除</text-button
          >
        </template>
      </el-table-column>
    </el-table>
    <el-dialog
      :visible.sync="dialogVisible"
      title="指定用户"
      append-to-body
      :close-on-click-modal="false"
      custom-class="shop-user-dialog"
      width="80%"
    >
      <div class="dialog-container">
        <div class="dialog-container__list">
          <el-bus-crud v-bind="tableConfig" />
        </div>
        <div class="dialog-container__selected">
          <el-bus-title title="已添加用户" size="mini" />
          <el-tag
            v-for="(tag, i) in currentValue"
            :key="tag.id"
            closable
            @close="deleteCurrentUser(i)"
            >{{ tag.name }}</el-tag
          >
        </div>
      </div>
      <div slot="footer">
        <el-button @click="cancel">取消</el-button>
        <el-button type="primary" @click="confirm">确定</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import cloneDeep from 'lodash.clonedeep'
export default {
  props: {
    value: {
      type: Array,
      default: () => [],
    },
    disabled: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      dialogVisible: false,
      currentValue: [],
      tableConfig: {
        url: 'flower/api/customer/page',
        saveQuery: false,
        hasEdit: false,
        hasDelete: false,
        hasView: false,
        columns: [
          { label: 'id', prop: 'id' },
          { label: '店铺名称', prop: 'name' },
          { label: '联系方式', prop: 'tel' },
        ],
        extraButtons: [
          {
            text: '选择',
            show: (row) =>
              !this.currentValue.find((item) => item.id === row.id),
            atClick: (row) => {
              this.currentValue.push({
                id: row.id,
                name: row.name,
                tel: row.tel,
              })
              return false
            },
          },
          {
            text: '取消选择',
            show: (row) => this.currentValue.find((item) => item.id === row.id),
            atClick: (row) => {
              const index = this.currentValue.findIndex(
                (item) => item.id === row.id
              )
              this.currentValue.splice(index, 1)
              return false
            },
          },
        ],
        searchFormAttrs: {
          labelWidth: 'auto',
        },
        searchForm: [
          {
            type: 'row',
            span: 12,
            items: [
              { label: 'id:', id: 'id', type: 'input' },
              { label: '店铺名称:', id: 'name', type: 'input' },
              { label: '联系方式:', id: 'tel', type: 'input' },
            ],
          },
        ],
      },
    }
  },
  watch: {
    value: {
      immediate: true,
      handler(value) {
        this.currentValue = cloneDeep(value || [])
      },
    },
  },
  methods: {
    chooseUser() {
      this.currentValue = cloneDeep(this.value || [])
      this.dialogVisible = true
    },
    deleteCurrentUser(i) {
      this.currentValue.splice(i, 1)
    },
    deleteUser(i) {
      this.$elBusUtil
        .confirm('确定要删除吗?')
        .then(() => {
          const userList = cloneDeep(this.value || [])
          userList.splice(i, 1)
          this.$emit('input', userList)
          this.$emit('change', userList)
        })
        .catch(() => {})
    },
    confirm() {
      this.$emit('input', this.currentValue)
      this.$emit('change', this.currentValue)
      this.dialogVisible = false
    },
    cancel() {
      this.dialogVisible = false
    },
  },
}
</script>
<style lang="scss" scoped>
.select-shop-user {
}
</style>
<style lang="scss">
.shop-user-dialog {
  .dialog-container {
    display: flex;
    align-items: flex-start;
    &__list {
      flex: 1;
      border-right: 1px solid #eee;
      height: 100%;
    }
    &__selected {
      width: 40%;
      height: 100%;
      padding: 24px;
      .el-bus-title {
        margin-bottom: 15px;
      }
      .el-tag {
        margin-right: 6px;
        margin-bottom: 6px;
      }
    }
  }
}
</style>
components/input-select.vue
对比新文件
@@ -0,0 +1,129 @@
<template>
  <div class="input-select">
    <el-input-number
      v-model="inputValue"
      v-bind="inputAttrs"
      class="input-select__input"
      @input="onInputChange"
    />
    <el-bus-select-dict
      v-model="selectValue"
      v-bind="selectAttrs"
      class="input-select__select"
      @change="onSelectChange"
    />
  </div>
</template>
<script>
import { t } from 'el-business'
import utils from 'el-business-utils'
export default {
  props: {
    value: {
      type: Array,
      default: () => [],
    },
    inputAttrs: {
      type: Object,
      default: () => ({}),
    },
    selectAttrs: {
      type: Object,
      default: () => ({}),
    },
  },
  rules(item) {
    const errorMsg = `${t('elBus.common.pleaseEnter')}${
      item.label ? item.label.replace(/:/g, '').replace(/:/g, '') : ''
    }`
    return [
      {
        required: true,
        message: errorMsg,
      },
      {
        validator: (rule, value, callback) => {
          if (
            Array.isArray(value) &&
            value.filter((i) => !utils.isTrueEmpty(i)).length === 2
          ) {
            callback()
          } else {
            callback(new Error(errorMsg))
          }
        },
      },
    ]
  },
  inputFormat(row, item) {
    if (
      Array.isArray(item.commonFormatProps) &&
      item.commonFormatProps.length === 2
    ) {
      const input = item.commonFormatProps[0]
      const select = item.commonFormatProps[1]
      if (select in row || input in row) {
        return [row[input], row[select]]
      }
    } else {
      console.warn('please set commonFormatProps')
    }
  },
  outputFormat(val, item) {
    if (
      Array.isArray(item.commonFormatProps) &&
      item.commonFormatProps.length === 2
    ) {
      const input = item.commonFormatProps[0]
      const select = item.commonFormatProps[1]
      return {
        [input]: !utils.isTrueEmpty(val?.[0]) ? val[0] : null,
        [select]: !utils.isTrueEmpty(val?.[1]) ? val[1] : null,
      }
    } else {
      console.warn('please set commonFormatProps')
    }
  },
  data() {
    return {
      inputValue: null,
      selectValue: null,
    }
  },
  watch: {
    value: {
      immediate: true,
      handler(value) {
        value = value || []
        this.inputValue = value?.[0] || undefined
        this.selectValue = value?.[1] || null
      },
    },
  },
  methods: {
    onInputChange(e) {
      const value = [e, this.selectValue]
      this.emitValue(value)
    },
    onSelectChange(e) {
      const value = [this.inputValue, e]
      this.emitValue(value)
    },
    emitValue(value) {
      this.$emit('input', value)
      this.$emit('change', value)
    },
  },
}
</script>
<style lang="scss" scoped>
.input-select {
  display: flex;
  align-items: center;
  &__input {
    margin-right: 8px;
  }
}
</style>
config/default-dev.json5
@@ -1,3 +1,3 @@
{
  httpBaseUri: 'http://106.14.123.210:8080',
  httpBaseUri: 'http://localhost:8080',
}
package-lock.json
@@ -16,7 +16,7 @@
        "css-vars-ponyfill": "^2.4.8",
        "dayjs": "^1.11.10",
        "echarts": "^5.5.0",
        "el-business": "^1.1.21",
        "el-business": "^1.1.22",
        "el-business-cache-utils": "^1.0.0",
        "el-business-cookie": "^1.0.0",
        "el-business-http": "^1.1.4",
@@ -9371,9 +9371,9 @@
      "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
    },
    "node_modules/el-business": {
      "version": "1.1.21",
      "resolved": "https://registry.npmjs.org/el-business/-/el-business-1.1.21.tgz",
      "integrity": "sha512-rtMLZ1o0M/hMPYi1/mNPgb5LI0DYOSY7jhJwIueocuHw3+yt3G8gPmZ8eP383AsRbvouOMBwq7EwoO9u4b9nFA==",
      "version": "1.1.22",
      "resolved": "https://registry.npmjs.org/el-business/-/el-business-1.1.22.tgz",
      "integrity": "sha512-l5IUsX6HKgAZCusej+pybry+XQCqWwGYhtKGzU8D+hjBp3/46rti+ajeO2ffDyTMydl1w9FqE3tgPHuNRHeLXA==",
      "dependencies": {
        "axios": "^0.19.2",
        "cookie-universal": "^2.1.4",
@@ -30591,9 +30591,9 @@
      "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
    },
    "el-business": {
      "version": "1.1.21",
      "resolved": "https://registry.npmjs.org/el-business/-/el-business-1.1.21.tgz",
      "integrity": "sha512-rtMLZ1o0M/hMPYi1/mNPgb5LI0DYOSY7jhJwIueocuHw3+yt3G8gPmZ8eP383AsRbvouOMBwq7EwoO9u4b9nFA==",
      "version": "1.1.22",
      "resolved": "https://registry.npmjs.org/el-business/-/el-business-1.1.22.tgz",
      "integrity": "sha512-l5IUsX6HKgAZCusej+pybry+XQCqWwGYhtKGzU8D+hjBp3/46rti+ajeO2ffDyTMydl1w9FqE3tgPHuNRHeLXA==",
      "requires": {
        "axios": "^0.19.2",
        "cookie-universal": "^2.1.4",
package.json
@@ -3,7 +3,7 @@
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "start": "cross-env NODE_APP_INSTANCE=test NODE_ENV=development nuxt",
    "start": "cross-env NODE_APP_INSTANCE=dev NODE_ENV=development nuxt",
    "build:dev": "cross-env NODE_APP_INSTANCE=dev NODE_ENV=production nuxt build",
    "build:prod": "cross-env NODE_APP_INSTANCE=prod NODE_ENV=production nuxt build",
    "launch": "nuxt start",
@@ -25,7 +25,7 @@
    "css-vars-ponyfill": "^2.4.8",
    "dayjs": "^1.11.10",
    "echarts": "^5.5.0",
    "el-business": "^1.1.21",
    "el-business": "^1.1.22",
    "el-business-cache-utils": "^1.0.0",
    "el-business-cookie": "^1.0.0",
    "el-business-http": "^1.1.4",
pages/marketing/coupon/activity/_id.vue
对比新文件
@@ -0,0 +1,72 @@
<template>
  <div class="base-page-wrapper coupon-detail">
    <el-bus-title title="优惠券信息" size="small" />
    <el-bus-form
      ref="form"
      label-width="auto"
      :content="formContent"
      readonly
    />
    <div class="base-page-wrapper__line"></div>
    <el-bus-title title="领取记录" size="small" />
    <el-bus-crud v-bind="recordTableConfig" />
    <div class="text-center mt-20">
      <el-button class="min-w-100" @click="goBack">返回</el-button>
    </div>
  </div>
</template>
<script>
import {
  couponForm,
  couponRecordColumn,
  recordTableConfig,
  getActivityReceiveTime,
  getActivityEffectiveTime,
} from '@/utils/coupon-form'
import CouponDetail from '@/plugins/mixins/coupon-detail.vue'
export default {
  mixins: [CouponDetail],
  data() {
    return {
      detailUrl: `flower/api/v2/coupon/avtivy`,
      formContent: [
        {
          type: 'row',
          items: [
            ...couponForm(),
            { label: '总数:', id: 'couponAmount', type: 'input' },
            { label: '已领取:', id: 'getNum', type: 'input' },
            { label: '剩余:', id: 'unGetNum', type: 'input' },
            {
              label: '领取时间:',
              id: 'getStartDate',
              inputFormat: (row) => getActivityReceiveTime(row),
              span: 24,
            },
            {
              label: '有效期:',
              id: 'usageStartDate',
              inputFormat: (row) => getActivityEffectiveTime(row),
              span: 24,
            },
          ],
        },
      ],
      recordTableConfig: {
        ...recordTableConfig(this.$route.params.id),
        columns: [...couponRecordColumn()],
      },
    }
  },
  head() {
    return {
      title: '活动优惠券详情',
    }
  },
}
</script>
<style lang="scss" scoped>
@import '@/assets/coupon/detail.scss';
</style>
pages/marketing/coupon/activity/index.vue
对比新文件
@@ -0,0 +1,259 @@
<template>
  <el-bus-crud v-bind="tableConfig" />
</template>
<script>
import InputSelect from '@/components/input-select'
import {
  couponForm,
  couponSearchForm,
  getActivityEffectiveTime,
  getActivityReceiveTime,
  couponColumn,
} from '@/utils/coupon-form'
export default {
  data() {
    return {
      tableConfig: {
        url: 'flower/api/v2/coupon/avtivy/page',
        newUrl: 'flower/api/v2/coupon/avtivy',
        viewUrl: 'flower/api/v2/coupon/avtivy',
        viewOnPath: true,
        editUrl: 'flower/api/v2/coupon/avtivy',
        editMethodType: 'put',
        editOnPath: true,
        deleteUrl: 'flower/api/v2/coupon/avtivy',
        deleteMethodType: 'delete',
        deleteOnPath: true,
        canEdit: (row) => row.status === 'inactive' || row.status === 'expired',
        canDelete: (row) =>
          row.status === 'inactive' || row.status === 'expired',
        operationAttrs: {
          width: 180,
          fixed: 'right',
        },
        onResetView: (row) => {
          this.$router.push(`${this.$route.path}/${row.id}`)
        },
        beforeOpen: (row, isNew) => {
          if (!isNew) {
            row.usageTypeStr = getActivityEffectiveTime(row)
            row.getStartDateStr = getActivityReceiveTime(row)
          }
        },
        columns: [
          ...couponColumn(),
          {
            label: '领取时间',
            formatter: getActivityReceiveTime,
            minWidth: 320,
          },
          {
            label: '有效期',
            formatter: getActivityEffectiveTime,
            minWidth: 320,
          },
          { label: '已领取总数', prop: 'getNum', minWidth: 150 },
          { label: '剩余未领取总数', prop: 'unGetNum', minWidth: 150 },
          { label: '状态', prop: 'statusName', minWidth: 120 },
          { label: '操作人', prop: 'createByName', minWidth: 120 },
        ],
        // 页面上要到分,后端要传到秒
        beforeConfirm: (data) => {
          if (data.getStartDate) {
            data.getStartDate = this.$elBusUtil.formatDate(
              data.getStartDate,
              'YYYY-MM-DD HH:mm:ss'
            )
          }
          if (data.getEndDate) {
            data.getEndDate = this.$elBusUtil.formatDate(
              data.getEndDate,
              'YYYY-MM-DD HH:mm:ss'
            )
          }
          if (data.usageStartDate) {
            data.usageStartDate = this.$elBusUtil.formatDate(
              data.usageStartDate,
              'YYYY-MM-DD HH:mm:ss'
            )
          }
          if (data.usageEndDate) {
            data.usageEndDate = this.$elBusUtil.formatDate(
              data.usageEndDate,
              'YYYY-MM-DD HH:mm:ss'
            )
          }
        },
        searchForm: [
          {
            type: 'row',
            items: [...couponSearchForm()],
          },
        ],
        form: [
          ...couponForm(),
          {
            label: '领取渠道:',
            id: 'getType',
            type: 'bus-select-dict',
            el: {
              code: 'COUPON_GET_TYPE',
              style: 'width:100%',
            },
            str: true,
            strKey: 'getTypeName',
            rules: { required: true, message: '请选择领取渠道' },
          },
          {
            label: '领取时间:',
            id: 'getStartDate',
            component: 'el-bus-date-range',
            el: {
              type: 'datetime',
              format: 'yyyy-MM-dd HH:mm',
              valueFormat: 'yyyy-MM-dd HH:mm',
            },
            str: true,
            commonRules: true,
            commonFormat: true,
            commonFormatProps: ['getStartDate', 'getEndDate'],
          },
          {
            label: '使用时间:',
            id: 'usageType',
            type: 'bus-select-dict',
            el: {
              code: 'COUPON_USAGE_TYPE',
              style: 'width:100%',
            },
            str: true,
            rules: { required: true, message: '请选择使用时间' },
            on: {
              change: (e, updateForm) => {
                updateForm({
                  usageStartDate: null,
                  usageEndDate: null,
                  usageTimeNum: undefined,
                  usageTimeType: null,
                })
              },
            },
          },
          {
            label: '使用固定时间:',
            id: 'usageStartDate',
            component: 'el-bus-date-range',
            el: {
              type: 'datetime',
              format: 'yyyy-MM-dd HH:mm',
              valueFormat: 'yyyy-MM-dd HH:mm',
            },
            commonRules: true,
            commonFormat: true,
            commonFormatProps: ['usageStartDate', 'usageEndDate'],
            hidden: (row, item, mode) =>
              row.usageType !== 'fixed' || mode === 'view',
          },
          {
            label: '领取后有效时间:',
            id: 'usageTimeNum',
            component: InputSelect,
            commonRules: true,
            commonFormat: true,
            commonFormatProps: ['usageTimeNum', 'usageTimeType'],
            el: {
              inputAttrs: {
                min: 1,
                precision: 0,
                controls: false,
              },
              selectAttrs: {
                code: 'COUPON_USAGE_TIME_TYPE',
              },
            },
            hidden: (row, item, mode) =>
              row.usageType !== 'get_after_time' || mode === 'view',
          },
          {
            label: '发放数量:',
            id: 'couponAmount',
            type: 'input-number',
            el: {
              precision: 0,
              min: 1,
              controls: false,
            },
            unit: '张',
            rules: {
              required: true,
              message: '请输入发放数量',
              trigger: 'blur',
            },
          },
          {
            label: '每人限领:',
            id: 'getLimit',
            type: 'input-number',
            el: {
              precision: 0,
              min: 1,
              controls: false,
            },
            unit: '张',
            rules: {
              required: true,
              message: '请输入每人限领',
              trigger: 'blur',
            },
          },
        ],
        extraButtons: [
          {
            text: '发布',
            show: (row) =>
              row.status === 'inactive' || row.status === 'expired',
            atClick: async (row) => {
              try {
                await this.$elBusUtil.confirm('确定要发布吗?')
                const { code } = await this.$elBusHttp.request(
                  `flower/api/v2/coupon/avtivy/active/${row.id}`,
                  { method: 'put' }
                )
                if (code === 0) {
                  this.$message.success('发布成功')
                }
              } catch (e) {
                return false
              }
            },
          },
          {
            text: '下架',
            show: (row) => row.status === 'active',
            atClick: async (row) => {
              try {
                await this.$elBusUtil.confirm('确定要下架吗?')
                const { code } = await this.$elBusHttp.request(
                  `flower/api/v2/coupon/avtivy/expire/${row.id}`,
                  { method: 'put' }
                )
                if (code === 0) {
                  this.$message.success('下架成功')
                }
              } catch (e) {
                return false
              }
            },
          },
        ],
      },
    }
  },
  head() {
    return {
      title: '活动优惠券',
    }
  },
}
</script>
pages/marketing/coupon/member/_id.vue
对比新文件
@@ -0,0 +1,66 @@
<template>
  <div class="base-page-wrapper coupon-detail">
    <el-bus-title title="优惠券信息" size="small" />
    <el-bus-form
      ref="form"
      label-width="auto"
      :content="formContent"
      readonly
    />
    <div class="base-page-wrapper__line"></div>
    <el-bus-title title="发放记录" size="small" />
    <el-bus-crud v-bind="recordTableConfig" />
    <div class="text-center mt-20">
      <el-button class="min-w-100" @click="goBack">返回</el-button>
    </div>
  </div>
</template>
<script>
import {
  couponForm,
  couponRecordColumn,
  recordTableConfig,
} from '@/utils/coupon-form'
import CouponDetail from '@/plugins/mixins/coupon-detail.vue'
export default {
  mixins: [CouponDetail],
  data() {
    return {
      detailUrl: `flower/api/v2/coupon/vip`,
      formContent: [
        {
          type: 'row',
          items: [
            ...couponForm(),
            { label: '已发放总数:', id: 'todo' },
            {
              label: '有效期:',
              id: 'usageStartDate',
              inputFormat: (row) => {
                return row.usageStartDate
                  ? `${row.usageStartDate} ~ ${row.usageEndDate || ''}`
                  : ''
              },
              span: 24,
            },
          ],
        },
      ],
      recordTableConfig: {
        ...recordTableConfig(this.$route.params.id),
        columns: [...couponRecordColumn()],
      },
    }
  },
  head() {
    return {
      title: '会员优惠券详情',
    }
  },
}
</script>
<style lang="scss" scoped>
@import '@/assets/coupon/detail.scss';
</style>
pages/marketing/coupon/member/index.vue
对比新文件
@@ -0,0 +1,80 @@
<template>
  <el-bus-crud v-bind="tableConfig" />
</template>
<script>
import { couponForm, couponSearchForm, couponColumn } from '@/utils/coupon-form'
export default {
  data() {
    return {
      tableConfig: {
        url: 'flower/api/v2/coupon/vip/page',
        newUrl: 'flower/api/v2/coupon/vip',
        viewUrl: 'flower/api/v2/coupon/vip',
        viewOnPath: true,
        editUrl: 'flower/api/v2/coupon/vip',
        editMethodType: 'put',
        editOnPath: true,
        deleteUrl: 'flower/api/v2/coupon/vip',
        deleteMethodType: 'delete',
        deleteOnPath: true,
        onResetView: (row) => {
          this.$router.push(`${this.$route.path}/${row.id}`)
        },
        operationAttrs: {
          width: 140,
          fixed: 'right',
        },
        columns: [
          ...couponColumn(),
          { label: '会员等级', prop: 'memberName' },
          {
            label: '有效期',
            formatter: (row) =>
              row.usageStartDate
                ? `${row.usageStartDate || ''} ~ ${row.usageEndDate || ''}`
                : '',
            minWidth: 320,
          },
          { label: '已发放数量', prop: 'getNum', minWidth: 120 },
          { label: '操作人', prop: 'createByName', minWidth: 120 },
        ],
        searchForm: [
          {
            type: 'row',
            items: [...couponSearchForm()],
          },
        ],
        form: [
          {
            label: '会员等级:',
            id: 'memberId',
            type: 'bus-select',
            el: {
              interfaceUri: 'flower/api/member/list',
              props: {
                label: 'name',
                value: 'id',
                dataPath: 'records',
              },
              extraQuery: {
                current: 1,
                size: 2000,
              },
              filterable: true,
              style: 'width:100%',
            },
            rules: { required: true, message: '请选择会员等级' },
          },
          ...couponForm(),
        ],
      },
    }
  },
  head() {
    return {
      title: '会员优惠券',
    }
  },
}
</script>
pages/marketing/coupon/user/_id.vue
对比新文件
@@ -0,0 +1,65 @@
<template>
  <div class="base-page-wrapper coupon-detail">
    <el-bus-title title="优惠券信息" size="small" />
    <el-bus-form
      ref="form"
      label-width="auto"
      :content="formContent"
      readonly
    />
    <div class="base-page-wrapper__line"></div>
    <el-bus-title title="发放记录" size="small" />
    <el-bus-crud v-bind="recordTableConfig" />
    <div class="text-center mt-20">
      <el-button class="min-w-100" @click="goBack">返回</el-button>
    </div>
  </div>
</template>
<script>
import {
  couponForm,
  couponRecordColumn,
  recordTableConfig,
} from '@/utils/coupon-form'
import CouponDetail from '@/plugins/mixins/coupon-detail.vue'
export default {
  mixins: [CouponDetail],
  data() {
    return {
      detailUrl: `flower/api/v2/coupon/user`,
      formContent: [
        {
          type: 'row',
          items: [
            ...couponForm(),
            {
              label: '有效期:',
              id: 'usageStartDate',
              inputFormat: (row) => {
                return row.usageStartDate
                  ? `${row.usageStartDate} ~ ${row.usageEndDate || ''}`
                  : ''
              },
              span: 24,
            },
          ],
        },
      ],
      recordTableConfig: {
        ...recordTableConfig(this.$route.params.id),
        columns: [...couponRecordColumn()],
      },
    }
  },
  head() {
    return {
      title: '用户优惠券详情',
    }
  },
}
</script>
<style lang="scss" scoped>
@import '@/assets/coupon/detail.scss';
</style>
pages/marketing/coupon/user/index.vue
对比新文件
@@ -0,0 +1,138 @@
<template>
  <el-bus-crud v-bind="tableConfig" />
</template>
<script>
import InputSelect from '@/components/input-select'
import SelectShopUser from '@/components/coupon/select-shop-user'
import { couponForm, couponSearchForm, couponColumn } from '@/utils/coupon-form'
export default {
  data() {
    return {
      tableConfig: {
        url: 'flower/api/v2/coupon/user/page',
        newUrl: 'flower/api/v2/coupon/user',
        viewUrl: 'flower/api/v2/coupon/user',
        viewOnPath: true,
        editUrl: 'flower/api/v2/coupon/user',
        editMethodType: 'put',
        editOnPath: true,
        deleteUrl: 'flower/api/v2/coupon/user',
        deleteMethodType: 'delete',
        deleteOnPath: true,
        dialogNeedRequest: true,
        canEdit: (row) => row.status === 'inactive' || row.status === 'expired',
        canDelete: (row) =>
          row.status === 'inactive' || row.status === 'expired',
        onResetView: (row) => {
          this.$router.push(`${this.$route.path}/${row.id}`)
        },
        operationAttrs: {
          width: 200,
          fixed: 'right',
        },
        columns: [
          ...couponColumn(),
          { label: '发放时间', prop: 'usageStartDate', minWidth: 180 },
          {
            label: '有效期',
            formatter: (row) =>
              row.usageStartDate
                ? `${row.usageStartDate} ~ ${row.usageEndDate || ''}`
                : '',
            minWidth: 400,
          },
          { label: '状态', prop: 'statusName', minWidth: 120 },
          { label: '操作人', prop: 'createByName', minWidth: 120 },
        ],
        searchForm: [
          {
            type: 'row',
            items: [...couponSearchForm()],
          },
        ],
        form: [
          ...couponForm(),
          {
            label: '发放后有效期:',
            id: 'usageTimeNum',
            component: InputSelect,
            commonRules: true,
            commonFormat: true,
            commonFormatProps: ['usageTimeNum', 'usageTimeType'],
            el: {
              inputAttrs: {
                min: 1,
                precision: 0,
                controls: false,
              },
              selectAttrs: {
                code: 'COUPON_USAGE_TIME_TYPE',
              },
            },
          },
          {
            label: '领取用户:',
            id: 'pointCostomIdList',
            component: SelectShopUser,
            rules: { required: true, message: '请选择领取用户' },
            inputFormat: (row) => {
              if ('customerList' in row) {
                return row.customerList
              }
            },
            outputFormat: (val) => {
              return val?.length ? val.map((i) => i.id) : []
            },
            forceDisabled: true,
          },
        ],
        extraButtons: [
          {
            text: '发布',
            show: (row) =>
              row.status === 'inactive' || row.status === 'expired',
            atClick: async (row) => {
              try {
                await this.$elBusUtil.confirm('确定要发布吗?')
                const { code } = await this.$elBusHttp.request(
                  `flower/api/v2/coupon/user/active/${row.id}`,
                  { method: 'put' }
                )
                if (code === 0) {
                  this.$message.success('发布成功')
                }
              } catch (e) {
                return false
              }
            },
          },
          {
            text: '下架',
            show: (row) => row.status === 'active',
            atClick: async (row) => {
              try {
                await this.$elBusUtil.confirm('确定要下架吗?')
                const { code } = await this.$elBusHttp.request(
                  `flower/api/v2/coupon/user/expire/${row.id}`,
                  { method: 'put' }
                )
                if (code === 0) {
                  this.$message.success('下架成功')
                }
              } catch (e) {
                return false
              }
            },
          },
        ],
      },
    }
  },
  head() {
    return {
      title: '用户优惠券',
    }
  },
}
</script>
pages/marketing/member-level.vue
对比新文件
@@ -0,0 +1,146 @@
<template>
  <el-bus-crud v-bind="tableConfig" />
</template>
<script>
import MemberRule from '@/components/coupon/member-rule.vue'
export default {
  data() {
    return {
      tableConfig: {
        url: 'flower/api/member/list',
        newUrl: 'flower/api/member/new',
        editUrl: 'flower/api/member/edit',
        deleteUrl: 'flower/api/member/delete',
        columns: [
          { label: '序号', type: 'index' },
          { label: '等级名称', prop: 'name' },
          { label: '成长值', prop: 'startPoint' },
          { label: '等级折扣', prop: 'discountTypeStr' },
          { label: '操作人', prop: 'createName' },
        ],
        beforeOpen: (row, isNew) => {
          if (!isNew) {
            row.consumptionAmountStr = `消费${row.consumptionAmount}元等于${row.growthValue}成长值`
            row.startPointStr = `${
              this.$elBusUtil.isTrueEmpty(row.startPoint) ? '' : row.startPoint
            } ~ ${
              this.$elBusUtil.isTrueEmpty(row.endPoint) ? '' : row.endPoint
            }`
          }
        },
        searchForm: [
          {
            type: 'row',
            items: [{ label: '等级名称:', id: 'name', type: 'input' }],
          },
        ],
        form: [
          {
            label: '会员等级名称:',
            id: 'name',
            type: 'input',
            rules: { required: true, message: '请输入会员等级名称' },
          },
          {
            label: '成长值范围:',
            id: 'startPoint',
            component: 'el-bus-number-range',
            el: {
              unit: '',
              separator: '<= 成长值范围 <',
              inputAttrs: {
                controls: false,
              },
            },
            commonFormat: true,
            commonFormatProps: ['startPoint', 'endPoint'],
            commonRules: true,
            commonRulesLevel: 1,
            str: true,
          },
          {
            label: '折扣类型:',
            id: 'discountType',
            type: 'bus-select-dict',
            el: {
              code: 'DISCOUNT_TYPE',
              style: 'width:100%',
            },
            str: true,
            rules: { required: true, message: '请选择折扣类型' },
            on: {
              change: (e, updateForm) => {
                updateForm({
                  discountRatio: undefined,
                  discountAmount: undefined,
                })
              },
            },
          },
          {
            label: '会员折扣:',
            id: 'discountRatio',
            type: 'input-number',
            el: {
              precision: 0,
              min: 0,
              max: 100,
              controls: false,
            },
            unit: '%',
            rules: {
              required: true,
              message: '请输入会员折扣',
              trigger: 'blur',
            },
            hidden: (row) => row.discountType !== 'ratio',
          },
          {
            label: '会员优惠:',
            id: 'discountAmount',
            type: 'input-number',
            el: {
              precision: 2,
              min: 0,
              controls: false,
            },
            unit: '元',
            rules: {
              required: true,
              message: '请输入会员优惠',
              trigger: 'blur',
            },
            hidden: (row) => row.discountType !== 'amount',
          },
          {
            label: '会员规则:',
            id: 'consumptionAmount',
            component: MemberRule,
            commonRules: true,
            commonFormat: true,
            commonFormatProps: ['consumptionAmount', 'growthValue'],
            str: true,
          },
          {
            label: '降级规则:',
            id: 'downgradeValue',
            type: 'input-number',
            el: {
              precision: 0,
              min: 0,
              controls: false,
            },
            unit: '成长值',
            rules: {
              required: true,
              message: '请输入降级规则',
              trigger: 'blur',
            },
          },
        ],
      },
    }
  },
}
</script>
pages/marketing/point-mall/coupon/_id.vue
对比新文件
@@ -0,0 +1,64 @@
<template>
  <div class="base-page-wrapper coupon-detail">
    <el-bus-title title="优惠券信息" size="small" />
    <el-bus-form
      ref="form"
      label-width="auto"
      :content="formContent"
      readonly
    />
    <div class="base-page-wrapper__line"></div>
    <el-bus-title title="兑换记录" size="small" />
    <el-bus-crud v-bind="recordTableConfig" />
    <div class="text-center mt-20">
      <el-button class="min-w-100" @click="goBack">返回</el-button>
    </div>
  </div>
</template>
<script>
import {
  couponForm,
  couponRecordColumn,
  recordTableConfig,
} from '@/utils/coupon-form'
import CouponDetail from '@/plugins/mixins/coupon-detail.vue'
export default {
  mixins: [CouponDetail],
  data() {
    return {
      detailUrl: `flower/api/v2/coupon/point`,
      formContent: [
        {
          type: 'row',
          items: [
            ...couponForm(),
            {
              label: '领取后有效时间:',
              id: 'usageTimeNum',
              inputFormat: (row) => {
                return `${row.usageTimeNum}${row.usageTimeTypeName}`
              },
            },
            { label: '库存:', id: 'couponAmount' },
            { label: '积分数量:', id: 'point' },
          ],
        },
      ],
      recordTableConfig: {
        ...recordTableConfig(this.$route.params.id),
        columns: [...couponRecordColumn()],
      },
    }
  },
  head() {
    return {
      title: '会员优惠券详情',
    }
  },
}
</script>
<style lang="scss" scoped>
@import '@/assets/coupon/detail.scss';
</style>
pages/marketing/point-mall/coupon/index.vue
对比新文件
@@ -0,0 +1,238 @@
<template>
  <el-bus-crud v-bind="tableConfig" />
</template>
<script>
import { couponForm, couponSearchForm, couponColumn } from '@/utils/coupon-form'
import InputSelect from '@/components/input-select'
export default {
  data() {
    return {
      tableConfig: {
        url: 'flower/api/v2/coupon/point/page',
        newUrl: 'flower/api/v2/coupon/point',
        viewUrl: 'flower/api/v2/coupon/point',
        viewOnPath: true,
        editUrl: 'flower/api/v2/coupon/point',
        editMethodType: 'put',
        editOnPath: true,
        deleteUrl: 'flower/api/v2/coupon/point',
        deleteMethodType: 'delete',
        deleteOnPath: true,
        canEdit: (row) => row.status === 'inactive' || row.status === 'expired',
        canDelete: (row) =>
          row.status === 'inactive' || row.status === 'expired',
        onResetView: (row) => {
          this.$router.push(`${this.$route.path}/${row.id}`)
        },
        persistSelection: true,
        operationAttrs: {
          width: 160,
          fixed: 'right',
        },
        columns: [
          {
            label: '',
            type: 'selection',
            minWidth: 60,
          },
          ...couponColumn(),
          { label: '状态', prop: 'statusName', minWidth: 120 },
          { label: '库存', prop: 'couponAmount', minWidth: 120 },
          { label: '所需积分', prop: 'point', minWidth: 120 },
        ],
        searchForm: [
          {
            type: 'row',
            items: [...couponSearchForm()],
          },
        ],
        form: [
          ...couponForm(),
          {
            label: '领取后有效时间:',
            id: 'usageTimeNum',
            component: InputSelect,
            commonRules: true,
            commonFormat: true,
            commonFormatProps: ['usageTimeNum', 'usageTimeType'],
            el: {
              inputAttrs: {
                min: 1,
                precision: 0,
                controls: false,
              },
              selectAttrs: {
                code: 'COUPON_USAGE_TIME_TYPE',
              },
            },
          },
          {
            label: '库存:',
            id: 'couponAmount',
            type: 'input-number',
            el: {
              precision: 0,
              min: 0,
              controls: false,
            },
            rules: { required: true, message: '请输入库存', trigger: 'blur' },
          },
          {
            label: '积分数量:',
            id: 'point',
            type: 'input-number',
            el: {
              precision: 0,
              min: 1,
              controls: false,
            },
            rules: {
              required: true,
              message: '请输入积分数量',
              trigger: 'blur',
            },
          },
        ],
        extraButtons: [
          {
            text: '上架',
            show: (row) =>
              row.status === 'inactive' || row.status === 'expired',
            atClick: async (row) => {
              try {
                await this.$elBusUtil.confirm('确定要上架吗?')
                const { code } = await this.$elBusHttp.request(
                  `flower/api/v2/coupon/point/active/${row.id}`,
                  { method: 'put' }
                )
                if (code === 0) {
                  this.$message.success('上架成功')
                }
              } catch (e) {
                return false
              }
            },
          },
          {
            text: '下架',
            show: (row) => row.status === 'active',
            atClick: async (row) => {
              try {
                await this.$elBusUtil.confirm('确定要下架吗?')
                const { code } = await this.$elBusHttp.request(
                  `flower/api/v2/coupon/point/expire/${row.id}`,
                  { method: 'put' }
                )
                if (code === 0) {
                  this.$message.success('下架成功')
                }
              } catch (e) {
                return false
              }
            },
          },
        ],
        headerButtons: [
          {
            text: '批量上架',
            type: 'primary',
            disabled: (selected) =>
              selected.filter(
                (i) => i.status === 'inactive' || i.status === 'expired'
              ).length === 0,
            atClick: async (selected) => {
              try {
                const items = selected.filter(
                  (i) => i.status === 'inactive' || i.status === 'expired'
                )
                await this.$elBusUtil.confirm(
                  `确定要上架这${items.length}个商品吗?`
                )
                const { code } = await this.$elBusHttp.request(
                  'flower/api/v2/coupon/point/batch/active',
                  {
                    data: { idList: items.map((i) => i.id) },
                    method: 'post',
                  }
                )
                if (code === 0) {
                  this.$message.success('上架成功')
                }
              } catch (e) {
                return false
              }
            },
          },
          {
            text: '批量下架',
            type: 'primary',
            disabled: (selected) =>
              selected.filter((i) => i.status === 'active').length === 0,
            atClick: async (selected) => {
              try {
                const items = selected.filter((i) => i.status === 'active')
                await this.$elBusUtil.confirm(
                  `确定要下架这${items.length}个商品吗?`
                )
                const { code } = await this.$elBusHttp.request(
                  'flower/api/v2/coupon/point/batch/expire',
                  {
                    data: { idList: items.map((i) => i.id) },
                    method: 'post',
                  }
                )
                if (code === 0) {
                  this.$message.success('下架成功')
                }
              } catch (e) {
                return false
              }
            },
          },
          {
            text: '批量删除',
            type: 'danger',
            disabled: (selected) =>
              selected.filter(
                (i) => i.status === 'inactive' || i.status === 'expired'
              ).length === 0,
            atClick: async (selected) => {
              try {
                const items = selected.filter(
                  (i) => i.status === 'inactive' || i.status === 'expired'
                )
                await this.$elBusUtil.confirm(
                  `确定要删除这${items.length}个商品吗?`
                )
                const { code } = await this.$elBusHttp.request(
                  'flower/api/v2/coupon/point/batch/del',
                  {
                    data: { idList: items.map((i) => i.id) },
                    method: 'post',
                  }
                )
                if (code === 0) {
                  this.$message.success('删除成功')
                }
              } catch (e) {
                return false
              }
            },
          },
        ],
      },
    }
  },
  head() {
    return {
      title: '积分优惠券',
    }
  },
}
</script>
<style lang="scss" scoped>
.index {
}
</style>
pages/marketing/point-mall/goods.vue
对比新文件
@@ -0,0 +1,242 @@
<template>
  <el-bus-crud ref="crud" v-bind="tableConfig" />
</template>
<script>
export default {
  data() {
    return {
      tableConfig: {
        url: 'flower/api/point/goods/list',
        canEdit: (row) => row.status === 'I',
        canDelete: (row) => row.status === 'I',
        columns: [
          { label: '', type: 'selection' },
          { label: '序号', type: 'index' },
          {
            label: '商品图片',
            formatter: (row) =>
              row.cover ? (
                <el-bus-image
                  src={row.cover}
                  lazy={true}
                  style="width:50px;height:50px"
                ></el-bus-image>
              ) : null,
          },
          { label: '商品名称', prop: 'name' },
          { label: '状态', prop: 'statusStr' },
          { label: '库存', prop: 'stock' },
          { label: '所需积分', prop: 'point' },
        ],
        searchForm: [
          {
            type: 'row',
            items: [
              {
                label: '商品名称',
                id: 'name',
                type: 'input',
              },
              {
                label: '状态',
                id: 'status',
                type: 'bus-select-dict',
                el: {
                  code: 'POINT_GOODS_STATUS',
                  style: 'width:100%',
                  clearable: true,
                },
              },
            ],
          },
        ],
        form: [
          {
            label: '商品名称:',
            id: 'name',
            type: 'input',
            rules: {
              required: true,
              message: '请输入商品名称',
              trigger: 'blur',
            },
          },
          {
            label: '商品规格信息:',
            id: 'description',
            type: 'input',
            el: {
              type: 'textarea',
              rows: 4,
            },
            rules: {
              required: true,
              message: '请输入商品规格信息',
              trigger: 'blur',
            },
          },
          {
            label: '库存:',
            id: 'stock',
            type: 'input-number',
            el: {
              precision: 0,
              min: 0,
              controls: false,
            },
            rules: { required: true, message: '请输入库存', trigger: 'blur' },
          },
          {
            label: '商品图片:',
            id: 'cover',
            type: 'bus-upload',
            el: {
              listType: 'picture-card',
              limit: 1,
              limitSize: 2,
              tipText: '大小不超过2M',
              valueType: 'string',
            },
            forceDisabled: true,
            rules: {
              required: true,
              message: '请上传商品图片',
              trigger: 'blur',
            },
          },
          {
            label: '积分数量:',
            id: 'point',
            type: 'input-number',
            el: {
              precision: 0,
              min: 1,
              controls: false,
            },
            rules: {
              required: true,
              message: '请输入积分数量',
              trigger: 'blur',
            },
          },
        ],
        extraButtons: [
          {
            text: '上架',
            show: (row) => row.status === 'I',
            atClick: async (row) => {
              try {
                await this.$elBusUtil.confirm('确定要上架吗?')
                const { code } = await this.$elBusHttp.request(
                  'flower/api/point/goods/list/on',
                  { params: { id: row.id } }
                )
                if (code === 0) {
                  this.$message.success('上架成功')
                }
              } catch (e) {
                return false
              }
            },
          },
          {
            text: '下架',
            show: (row) => row.status === 'A',
            atClick: async (row) => {
              try {
                await this.$elBusUtil.confirm('确定要下架吗?')
                const { code } = await this.$elBusHttp.request(
                  'flower/api/point/goods/list/off',
                  { params: { id: row.id } }
                )
                if (code === 0) {
                  this.$message.success('下架成功')
                }
              } catch (e) {
                return false
              }
            },
          },
        ],
        headerButtons: [
          {
            text: '批量上架',
            type: 'primary',
            disabled: (selected) =>
              selected.filter((i) => i.status === 'I').length === 0,
            atClick: async (selected) => {
              try {
                const items = selected.filter((i) => i.status === 'I')
                await this.$elBusUtil.confirm(
                  `确定要上架这${items.length}个商品吗?`
                )
                const { code } = await this.$elBusHttp.request(
                  'flower/api/point/goods/list/on',
                  { params: { id: items.map((i) => i.id).join(',') } }
                )
                if (code === 0) {
                  this.$message.success('上架成功')
                }
              } catch (e) {
                return false
              }
            },
          },
          {
            text: '批量下架',
            type: 'primary',
            disabled: (selected) =>
              selected.filter((i) => i.status === 'A').length === 0,
            atClick: async (selected) => {
              try {
                const items = selected.filter((i) => i.status === 'A')
                await this.$elBusUtil.confirm(
                  `确定要下架这${items.length}个商品吗?`
                )
                const { code } = await this.$elBusHttp.request(
                  'flower/api/point/goods/list/off',
                  { params: { id: items.map((i) => i.id).join(',') } }
                )
                if (code === 0) {
                  this.$message.success('下架成功')
                }
              } catch (e) {
                return false
              }
            },
          },
          {
            text: '批量删除',
            type: 'danger',
            disabled: (selected) =>
              selected.filter((i) => i.status === 'I').length === 0,
            atClick: async (selected) => {
              try {
                const items = selected.filter((i) => i.status === 'I')
                await this.$elBusUtil.confirm(
                  `确定要删除这${items.length}个商品吗?`
                )
                const { code } = await this.$elBusHttp.request(
                  'flower/api/point/goods/list/delete',
                  { params: { id: items.map((i) => i.id).join(',') } }
                )
                if (code === 0) {
                  this.$message.success('删除成功')
                }
              } catch (e) {
                return false
              }
            },
          },
        ],
      },
    }
  },
  head() {
    return {
      title: '积分商品',
    }
  },
}
</script>
pages/marketing/point-mall/point-distribution.vue
对比新文件
@@ -0,0 +1,224 @@
<template>
  <div>
    <el-bus-crud ref="crud" v-bind="tableConfig" />
    <el-dialog title="积分变动记录" :visible.sync="dialogVisible" width="80%">
      <el-bus-crud
        v-if="customerId"
        :key="customerId"
        :extra-query="{ customerId }"
        v-bind="recordTableConfig"
      />
    </el-dialog>
  </div>
</template>
<script>
export default {
  data() {
    return {
      dialogVisible: false,
      customerId: null,
      tableConfig: {
        url: 'flower/api/customer/point/page',
        hasNew: false,
        hasEdit: false,
        hasDelete: false,
        hasView: false,
        columns: [
          { label: '序号', type: 'index' },
          { label: '用户信息', prop: 'customerName' },
          { label: '总积分', prop: 'totalPoint' },
          { label: '已使用积分', prop: 'usedPoint' },
          {
            label: '剩余积分',
            formatter: (row) =>
              parseInt(row.totalPoint) -
              parseInt(row.usedPoint) -
              parseInt(row.expiredPoint),
          },
        ],
        searchForm: [
          {
            type: 'row',
            items: [{ label: '用户名称', id: 'customerName', type: 'input' }],
          },
        ],
        extraDialogs: [
          {
            title: '积分赠送',
            form: [
              {
                id: 'customerId',
                type: 'input',
                hidden: () => true,
              },
              {
                label: '积分赠送:',
                id: 'point',
                type: 'input-number',
                el: {
                  precision: 0,
                  min: 1,
                  controls: false,
                },
                rules: {
                  required: true,
                  message: '请输入积分赠送',
                  trigger: 'blur',
                },
              },
              {
                label: '原因:',
                id: 'remarks',
                type: 'input',
                el: {
                  type: 'textarea',
                  rows: 6,
                },
                rules: {
                  required: true,
                  message: '请输入原因',
                  trigger: 'blur',
                },
              },
            ],
            atConfirm: async (val) => {
              const { code } = await this.$elBusHttp.request(
                'flower/api/customer/point/giveaway',
                {
                  method: 'post',
                  data: val,
                }
              )
              if (code === 0) {
                this.$message.success('赠送成功')
              }
            },
          },
          {
            title: '积分扣减',
            form: [
              {
                id: 'customerId',
                type: 'input',
                hidden: () => true,
              },
              {
                label: '积分扣减:',
                id: 'point',
                type: 'input-number',
                el: {
                  precision: 0,
                  min: 1,
                  controls: false,
                },
                rules: {
                  required: true,
                  message: '请输入积分扣减',
                  trigger: 'blur',
                },
              },
              {
                label: '原因:',
                id: 'remarks',
                type: 'input',
                el: {
                  type: 'textarea',
                  rows: 6,
                },
                rules: {
                  required: true,
                  message: '请输入原因',
                  trigger: 'blur',
                },
              },
            ],
            atConfirm: async (val) => {
              const { code } = await this.$elBusHttp.request(
                'flower/api/customer/point/deduction',
                {
                  method: 'post',
                  data: val,
                }
              )
              if (code === 0) {
                this.$message.success('扣减成功')
              }
            },
          },
        ],
        extraButtons: [
          {
            text: '积分变动记录',
            atClick: (row) => {
              this.customerId = row.customerId
              this.dialogVisible = true
            },
          },
          {
            text: '积分赠送',
            atClick: (row) => {
              this.$refs.crud.$refs.extraDialog[0].show(row)
              return false
            },
          },
          {
            text: '积分扣减',
            atClick: (row) => {
              this.$refs.crud.$refs.extraDialog[1].show(row)
              return false
            },
          },
        ],
      },
      recordTableConfig: {
        url: 'flower/api/customer/point/page/list',
        saveQuery: false,
        hasNew: false,
        hasOperation: false,
        columns: [
          { label: '序号', type: 'index' },
          { label: '变动类型', prop: 'changeTypeStr' },
          { label: '变动积分', prop: 'point' },
          { label: '变动原因', prop: 'typeStr' },
          { label: '变动时间', prop: 'recordDate' },
          { label: '备注', prop: 'remarks' },
        ],
        searchFormAttrs: {
          labelWidth: 'auto',
        },
        searchForm: [
          {
            type: 'row',
            items: [
              {
                label: '变动原因:',
                id: 'type',
                type: 'bus-radio',
                el: {
                  code: 'point_type',
                  childType: 'el-radio-button',
                  hasAll: true,
                },
                default: '',
                searchImmediately: true,
                span: 24,
              },
              {
                label: '备注:',
                id: 'remarks',
                type: 'input',
              },
            ],
          },
        ],
      },
    }
  },
  head() {
    return {
      title: '积分发放',
    }
  },
}
</script>
plugins/mixins/coupon-detail.vue
对比新文件
@@ -0,0 +1,27 @@
<script>
export default {
  data() {
    return {
      detailUrl: '',
    }
  },
  mounted() {
    this.getCouponDetail()
  },
  methods: {
    async getCouponDetail() {
      const { code, data } = await this.$elBusHttp.request(
        `${this.detailUrl}/${this.$route.params.id}`
      )
      if (code === 0) {
        if (this.$refs.form) {
          this.$refs.form.updateForm(data)
        }
      }
    },
    goBack() {
      this.$router.back()
    },
  },
}
</script>
utils/coupon-form.js
对比新文件
@@ -0,0 +1,173 @@
import utils from 'el-business-utils'
// 优惠券表单公共字段
export const couponForm = () => {
  return [
    {
      label: '优惠券名称:',
      id: 'couponName',
      type: 'input',
      rules: {
        required: true,
        message: '请输入优惠券名称',
        trigger: 'blur',
      },
    },
    {
      label: '优惠券类型:',
      id: 'couponDiscountType',
      type: 'bus-select-dict',
      el: {
        code: 'COUPON_TYPE',
        style: 'width:100%',
      },
      on: {
        change: (e, updateForm, obj) => {
          if (e[0] === 'zero') {
            updateForm({ minOrderAmount: 0 })
            obj.elBusForm
              .getComponentById('minOrderAmount')
              .$parent.clearValidate()
          }
        },
      },
      rules: { required: true, message: '请选择优惠券类型' },
      str: true,
      strKey: 'couponDiscountTypeName',
    },
    {
      label: '使用规则:',
      id: 'couponDescription',
      type: 'input',
      el: {
        type: 'textarea',
        rows: 6,
      },
      rules: {
        required: true,
        message: '请输入使用规则',
        trigger: 'blur',
      },
    },
    {
      label: '优惠券使用条件:',
      id: 'minOrderAmount',
      type: 'input-number',
      el: {
        min: 0,
        precision: 2,
        controls: false,
      },
      prefix: '满',
      unit: '元',
      rules: {
        required: true,
        message: '请输入优惠券使用条件',
        trigger: 'blur',
      },
      disabled: (row) => row.couponDiscountType === 'zero',
    },
    {
      label: '优惠券面值:',
      id: 'couponDiscountValue',
      type: 'input-number',
      el: {
        min: 0.01,
        precision: 2,
        controls: false,
      },
      unit: '元',
      rules: {
        required: true,
        message: '请输入优惠券面值',
        trigger: 'blur',
      },
    },
  ]
}
export const couponSearchForm = () => {
  return [
    {
      label: '优惠券类型',
      id: 'couponDiscountType',
      type: 'bus-select-dict',
      el: {
        code: 'COUPON_TYPE',
        style: 'width:100%',
        clearable: true,
      },
    },
    {
      label: '优惠券名称',
      id: 'name',
      type: 'input',
    },
  ]
}
export const getActivityEffectiveTime = (row) => {
  if (row.usageType === 'get') {
    return `${utils.formatDate(row.getStartDate, 'YYYY-MM-DD HH:mm') || ''} ~ ${
      utils.formatDate(row.getEndDate, 'YYYY-MM-DD HH:mm') || ''
    }`
  } else if (row.usageType === 'fixed') {
    return `${
      utils.formatDate(row.usageStartDate, 'YYYY-MM-DD HH:mm') || ''
    } ~ ${utils.formatDate(row.usageEndDate, 'YYYY-MM-DD HH:mm') || ''}`
  } else if (row.usageType === 'get_after_time') {
    return `领取后${row.usageTimeNum}${row.usageTimeTypeName || ''}`
  }
  return ''
}
export const getActivityReceiveTime = (row) => {
  return `${utils.formatDate(
    row.getStartDate,
    'YYYY-MM-DD HH:mm'
  )} ~ ${utils.formatDate(row.getEndDate, 'YYYY-MM-DD HH:mm')}`
}
// 优惠券列表公共字段
export const couponColumn = () => {
  return [
    { label: '序号', type: 'index', minWidth: 60, fixed: 'left' },
    { label: '优惠券名称', prop: 'couponName', minWidth: 150, fixed: 'left' },
    { label: '优惠券类型', prop: 'couponDiscountTypeName', minWidth: 120 },
    {
      label: '使用条件',
      formatter: (row) => `满${row.minOrderAmount}`,
      minWidth: 120,
    },
    { label: '优惠券面值', prop: 'couponDiscountValue', minWidth: 120 },
  ]
}
// 优惠券领取/发放记录
export const couponRecordColumn = () => {
  return [
    { label: '序号', type: 'index' },
    { label: '店铺名称', prop: 'customerName' },
    { label: '优惠券类型', prop: 'couponDiscountTypeName' },
    {
      label: '使用条件',
      formatter: (row) => `满${row.minOrderAmount}`,
    },
    { label: '优惠券面值', prop: 'couponDiscountValue' },
    { label: '状态', prop: 'statusName' },
    { label: '使用时间', prop: 'index' },
    { label: '订单号', prop: 'orderNo' },
  ]
}
export const recordTableConfig = (couponId) => {
  return {
    url: 'flower/v2/coupon-record/page',
    hasNew: false,
    hasOperation: false,
    saveQuery: false,
    extraQuery: {
      couponId,
    },
  }
}