- 框架初始化
 - 安装插件
 - 修复PHP8.4报错
This commit is contained in:
2025-04-19 17:21:20 +08:00
commit c6a4e1f5f6
5306 changed files with 967782 additions and 0 deletions

View File

@@ -0,0 +1,210 @@
{include file="/shopro/common/script" /}
<style>
.coupon-form .w-120 {
width: 120px;
}
.coupon-form .el-form-item-inner {
--el-form-label-font-size: 12px;
}
.coupon-form .el-form-item-inner .el-form-item__label {
width: fit-content !important;
}
.coupon-form .key .el-form-item__content {
flex-wrap: nowrap;
}
.coupon-form .el-date-editor {
flex: none;
}
</style>
<div id="addEdit" class="coupon-form" v-cloak>
<el-container class="panel-block">
<el-main>
<el-scrollbar height="100%">
<el-form :model="form.model" :rules="form.rules" ref="formRef" label-width="110px">
<el-form-item label="券名称" prop="name">
<el-input class="sa-w-360" v-model="form.model.name" placeholder="例如:国庆优惠券"></el-input>
</el-form-item>
<el-form-item label="名称备注" prop="description">
<el-input class="sa-w-360" v-model="form.model.description" placeholder="请输入名称备注"></el-input>
</el-form-item>
<el-form-item label="券类型" prop="type">
<el-radio-group v-model="form.model.type" :disabled="state.type == 'edit'">
<el-radio label="reduce">满减券</el-radio>
<el-radio label="discount">折扣券</el-radio>
</el-radio-group>
</el-form-item>
<div class="el-form-item-inner">
<el-form-item>
<el-form-item label="消费满" prop="enough">
<el-input class="w-120" type="number" v-model="form.model.enough" :min="0"
:disabled="state.type == 'edit'">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item v-if="form.model.type == 'reduce'" class="is-no-asterisk ml-2" label="立减"
prop="amount">
<el-input class="w-120" type="number" v-model="form.model.amount" :min="0"
:disabled="state.type == 'edit'">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item v-if="form.model.type == 'discount'" class="is-no-asterisk ml-2" label="打"
prop="amount">
<el-input class="w-120" type="number" v-model="form.model.amount" :min="0" :max="10"
:disabled="state.type == 'edit'">
<template #append></template>
</el-input>
</el-form-item>
</el-form-item>
<el-form-item v-if="form.model.type == 'discount'">
<el-form-item label="最多优惠" prop="max_amount">
<el-input class="w-120" type="number" v-model="form.model.max_amount" :min="0"
:disabled="state.type == 'edit'">
<template #append></template>
</el-input>
</el-form-item>
</el-form-item>
</div>
<el-form-item label="发券总量" prop="stock">
<el-input class="w-120" type="number" v-model="form.model.stock" :min="0">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item label="每人限领次数">
<el-input class="w-120" type="number" v-model="form.model.limit_num" :min="0">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item label="领券时间" prop="get_time">
<el-date-picker v-model="form.model.get_time" type="datetimerange"
value-format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)]"
range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" prefix-icon="Calendar"
:editable="false"></el-date-picker>
</el-form-item>
<el-form-item label="券有效期" prop="use_time_type">
<el-radio-group v-model="form.model.use_time_type">
<el-radio label="days">相对天数</el-radio>
<el-radio label="range">固定区间</el-radio>
</el-radio-group>
</el-form-item>
<div class="el-form-item-inner">
<el-form-item>
<template v-if="form.model.use_time_type == 'days'">
<el-form-item class="is-no-asterisk" label="领券" prop="start_days">
<el-input class="w-120" type="number" v-model="form.model.start_days" :min="0">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item class="is-no-asterisk ml-2" label="后生效,有效期" prop="days">
<el-input class="w-120" type="number" v-model="form.model.days" :min="0">
<template #append></template>
</el-input>
</el-form-item>
</template>
<el-form-item v-if="form.model.use_time_type == 'range'" class="is-no-asterisk" label="固定时间"
prop="useTime">
<el-date-picker v-model="form.model.use_time" type="datetimerange"
value-format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)]"
range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"
prefix-icon="Calendar" :editable="false"></el-date-picker>
</el-form-item>
</el-form-item>
</div>
<el-form-item label="优惠叠加">
<div>
<div class="sa-flex">
<el-switch v-model="form.model.is_double_discount" :active-value="1"
:inactive-value="0">
</el-switch>
<div class="ml-2" :class="form.model.is_double_discount == 1?'sa-color--primary':''">
{{form.model.is_double_discount == 1?'开启':'关闭'}}
</div>
</div>
<div class="tip"> 开启优惠叠加,优惠券将可以和活动一起使用 </div>
</div>
</el-form-item>
<el-form-item label="券状态" prop="status">
<div>
<el-radio-group v-model="form.model.status">
<el-radio label="normal">公开发放</el-radio>
<el-radio label="hidden">后台发放</el-radio>
<el-radio label="disabled">禁止使用</el-radio>
</el-radio-group>
<div class="tip">
后台发放状态改为别的状态,将导致满赠活动无法赠送该优惠券
</div>
</div>
</el-form-item>
<el-form-item label="可用范围" prop="use_scope">
<el-radio-group v-model="form.model.use_scope" @change="form.model.items_value = []">
<el-radio label="all_use">全场通用</el-radio>
<el-radio label="goods">指定商品可用</el-radio>
<el-radio label="disabled_goods">指定商品不可用</el-radio>
<el-radio label="category">指定分类可用</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item>
<el-button v-if="form.model.use_scope == 'goods' || form.model.use_scope == 'disabled_goods'"
type="primary" link @click="onSelectGoods">选择商品</el-button>
<el-button v-if="form.model.use_scope == 'category'" type="primary" link
@click="onSelectCategory">选择分类
</el-button>
</el-form-item>
<el-form-item>
<div v-if="form.model.use_scope == 'goods' || form.model.use_scope == 'disabled_goods'"
class="sa-template-wrap">
<template v-if="form.model.items_value.length > 0">
<div class="header sa-flex">
<div class="key">商品信息</div>
<div class="oper">操作</div>
</div>
<div class="item" v-for="(element, index) in form.model.items_value" :key="element">
<div class="key">
<sa-image class="mr-2" :url="element.image" size="40"></sa-image>
<div class="sa-table-line-1">
{{ element.title }}
</div>
</div>
<div class="oper">
<el-button type="danger" link @click="onDeleteGoods(index)">
移除
</el-button>
</div>
</div>
</template>
</div>
<div v-if="form.model.use_scope == 'category'" class="sa-template-wrap">
<template v-if="form.model.items_value.length > 0">
<div class="header sa-flex">
<div class="key">分类信息</div>
<div class="oper">操作</div>
</div>
<div class="item" v-for="(element, index) in form.model.items_value" :key="element">
<div class="key">
<div class="goods-title sa-m-b-6">{{ element.name }}</div>
</div>
<div class="oper">
<el-button type="danger" link @click="onDeleteCategory(index)">
移除
</el-button>
</div>
</div>
</template>
</div>
</el-form-item>
</el-form>
</el-scrollbar>
</el-main>
<el-footer class="sa-footer--submit sa-flex sa-row-right">
<el-button type="primary" @click="onConfirm">确定</el-button>
</el-footer>
</el-container>
</div>

View File

@@ -0,0 +1,209 @@
{include file="/shopro/common/script" /}
<style>
.coupon-index .card {
height: 80px;
background: var(--sa-background-assist);
border: 1px solid var(--sa-space);
box-shadow: 0px 2px 6px rgba(140, 140, 140, 0.12);
border-radius: 8px;
padding: 16px;
margin-bottom: 16px;
}
.coupon-index .card .num {
font-weight: 400;
font-size: 24px;
line-height: 26px;
color: var(--sa-subfont);
}
.coupon-index .card .oper {
font-weight: 400;
font-size: 12px;
line-height: 14px;
color: #FAAD14;
cursor: pointer;
}
.coupon-index .card .name {
font-weight: 400;
font-size: 12px;
line-height: 14px;
color: var(--sa-font);
}
.coupon-index .card .tip {
font-size: 14px;
color: var(--sa-subfont);
}
.coupon-index .sa-title {
padding-top: 0;
}
</style>
<div id="index" class="coupon-index panel panel-default panel-intro" v-cloak>
<el-container class="panel-block">
<el-header class="sa-header">
<el-row class="mt-4" :gutter="20">
<el-col v-for="(value,key) in state.dashboard" :xs="24" :sm="12" :md="6" :lg="6" :xl="6">
<div class="card">
<div class="sa-flex sa-row-between mb-1">
<div class="num">{{value.num}}</div>
</div>
<div class="sa-flex sa-row-between">
<div class="name">{{value.name}}</div>
<el-popover popper-class="sa-popper" trigger="hover">
{{value.tip}}
<template #reference>
<el-icon class="tip">
<warning />
</el-icon>
</template>
</el-popover>
</div>
</div>
</el-col>
</el-row>
<div class="sa-title sa-flex sa-row-between">
<div class="sa-title-left">
<div class="left-name">优惠券</div>
<sa-filter-condition v-model="state.filter" @filter-delete="onChangeFilter">
</sa-filter-condition>
</div>
<div class="sa-title-right">
<el-button class="sa-button-refresh" icon="RefreshRight" @click="getData"></el-button>
<el-button class="sa-button-refresh" icon="Search" @click="onOpenFilter"></el-button>
{if $auth->check('shopro/coupon/add')}
<el-button icon="Plus" type="primary" @click="onAdd">添加</el-button>
{/if}
{if $auth->check('shopro/coupon/recyclebin')}
<el-button type="danger" icon="Delete" plain @click="onRecyclebin">回收站</el-button>
{/if}
</div>
</div>
</el-header>
<el-main class="sa-main">
<el-table height="100%" class="sa-table" :data="state.data" stripe @sort-change="onChangeSort">
<el-table-column prop="id" label="ID" min-width="90" sortable="custom"> </el-table-column>
<el-table-column label="优惠券名称" min-width="172">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.name }}</div>
</template>
</el-table-column>
<el-table-column label="类型" min-width="74">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.type_text }}</div>
</template>
</el-table-column>
<el-table-column label="可用范围" min-width="116">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.use_scope_text }}</div>
</template>
</el-table-column>
<el-table-column label="优惠内容" min-width="214">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.amount_text }}</div>
</template>
</el-table-column>
<el-table-column label="领取状态" min-width="80">
<template #default="scope">
<el-popover popper-class="sa-popper" placement="bottom" title="优惠券有效期" trigger="hover">
<div v-if="scope.row.use_time_type == 'days'">
领取{{ scope.row.start_days }}天后生效,有效期{{ scope.row.days }}天
</div>
<div v-if="scope.row.use_time_type == 'range'">
<div>开始时间:{{ scope.row.use_start_time }}</div>
<div>结束时间:{{ scope.row.use_end_time }}</div>
</div>
<template #reference>
<div class="sa-table-line-1 get-time-text" :class="
scope.row.get_time_status == 'ing'
? 'sa-color--success'
: scope.row.get_time_status == 'ended'
? 'sa-color--danger'
: 'sa-color--info'
">
{{ scope.row.get_time_text }}
</div>
</template>
</el-popover>
</template>
</el-table-column>
<el-table-column label="已领取" min-width="96">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.get_num }}</div>
</template>
</el-table-column>
<el-table-column label="已使用" min-width="96">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.use_num }}</div>
</template>
</el-table-column>
<el-table-column label="剩余" min-width="96">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.stock }}</div>
</template>
</el-table-column>
<el-table-column label="状态" min-width="130">
<template #default="scope">
{if $auth->check('shopro/coupon/edit')}
<el-dropdown trigger="click" @command="onCommand">
<el-button link>
<el-tag type="info">
{{ scope.row.status_text }}
<el-icon>
<arrow-down />
</el-icon>
</el-tag>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :command="{
id: scope.row.id,
type: 'normal',
}">公开发放</el-dropdown-item>
<el-dropdown-item :command="{
id: scope.row.id,
type: 'hidden',
}">后台发放</el-dropdown-item>
<el-dropdown-item :command="{
id: scope.row.id,
type: 'disabled',
}">禁止使用</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
{/if}
</template>
</el-table-column>
<el-table-column label="操作" min-width="260" fixed="right">
<template #default="scope">
{if $auth->check('shopro/coupon/send')}
<el-button type="primary" link @click="onSend(scope.row.id)">手动发放</el-button>
{/if}
{if $auth->check('shopro/user/coupon/index')}
<el-button type="primary" link @click="onCoupon(scope.row.id)">领取记录</el-button>
{/if}
{if $auth->check('shopro/coupon/edit')}
<el-button type="primary" link @click="onEdit(scope.row.id)">编辑</el-button>
{/if}
<el-popconfirm width="fit-content" confirm-button-text="确认" cancel-button-text="取消"
title="确认删除这条记录?" @confirm="onDelete(scope.row.id)">
<template #reference>
{if $auth->check('shopro/coupon/delete')}
<el-button type="danger" link>删除</el-button>
{/if}
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</el-main>
<el-footer class="sa-footer sa-flex sa-row-right">
<sa-pagination v-model="pagination" @pagination-change="getData"></sa-pagination>
</el-footer>
</el-container>
<sa-filter v-model="state.filter" @filter-change="onChangeFilter"></sa-filter>
</div>

View File

@@ -0,0 +1,54 @@
{include file="/shopro/common/script" /}
<div id="recyclebin" class="coupon-recyclebin" v-cloak>
<el-container class="panel-block">
<el-main>
<el-table height="100%" class="sa-table" :data="state.data" stripe @selection-change="onChangeSelection"
@sort-change="onChangeSort">
<el-table-column type="selection" width="48" align="center"></el-table-column>
<el-table-column prop="id" label="ID" min-width="90" sortable="custom"></el-table-column>
<el-table-column label="名称" min-width="100">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.name || '-' }}</div>
</template>
</el-table-column>
<el-table-column prop="deletetime" label="删除时间" min-width="172" sortable="custom"></el-table-column>
<el-table-column fixed="right" label="操作" min-width="120">
<template #default="scope">
{if $auth->check('shopro/coupon/restore')}
<el-button type="primary" link @click="onRestore(scope.row.id)">还原</el-button>
{/if}
<el-popconfirm width="fit-content" confirm-button-text="确认" cancel-button-text="取消"
title="确认销毁这条记录?" @confirm="onDestroy(scope.row.id)">
<template #reference>
{if $auth->check('shopro/coupon/destroy')}
<el-button type="danger" link>销毁</el-button>
{/if}
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</el-main>
<el-footer class="sa-footer sa-flex sa-row-between sa-flex-wrap">
<div class="sa-batch sa-flex">
<div class="tip">
已选择 <span>{{batchHandle.data.length}}</span></div>
<div class="sa-flex">
{if $auth->check('shopro/coupon/restore')}
<el-button type="primary" :disabled="!batchHandle.data.length" @click="onBatchHandle('restore')">还原
</el-button>
{/if}
{if $auth->check('shopro/coupon/destroy')}
<el-button type="danger" :disabled="!batchHandle.data.length" @click="onBatchHandle('destroy')">销毁
</el-button>
{/if}
{if $auth->check('shopro/coupon/destroy')}
<el-button type="danger" @click="onBatchHandle('all')">清空回收站</el-button>
{/if}
</div>
</div>
<sa-pagination class="is-ellipsis" v-model="pagination" @pagination-change="getData"></sa-pagination>
</el-footer>
</el-container>
</div>

View File

@@ -0,0 +1,79 @@
{include file="/shopro/common/script" /}
<div id="select" class="coupon-select" v-cloak>
<el-container class="panel-block">
<el-main>
<el-table class="sa-table" :data="state.data" stripe @selection-change="onChangeSelection">
<el-table-column v-if="state.multiple" type="selection"></el-table-column>
<el-table-column label="优惠券名称" min-width="128">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.name }}
</div>
</template>
</el-table-column>
<el-table-column label="类型" min-width="74">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.type_text }}
</div>
</template>
</el-table-column>
<el-table-column label="可用范围" min-width="88">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.use_scope_text }}
</div>
</template>
</el-table-column>
<el-table-column label="优惠内容" min-width="154">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.amount_text }}
</div>
</template>
</el-table-column>
<el-table-column label="领取状态" min-width="80">
<template #default="scope">
<el-popover popper-class="sa-popper" placement="bottom" title="优惠券有效期" trigger="hover">
<div v-if="scope.row.use_time_type == 'days'">
领取{{ scope.row.start_days }}天后生效,有效期{{ scope.row.days }}天
</div>
<div v-if="scope.row.use_time_type == 'range'">
<div>开始时间:{{ scope.row.use_start_time }}</div>
<div>结束时间:{{ scope.row.use_end_time }}</div>
</div>
<template #reference>
<div class="sa-table-line-1 get-time-text" :class="
scope.row.get_time_status == 'ing'
? 'sa-color--success'
: scope.row.get_time_status == 'ended'
? 'sa-color--danger'
: 'sa-color--info'
">
{{ scope.row.get_time_text }}
</div>
</template>
</el-popover>
</template>
</el-table-column>
<el-table-column label="剩余" min-width="88">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.stock }}
</div>
</template>
</el-table-column>
<el-table-column v-if="!state.multiple" label="操作" min-width="88">
<template #default="scope">
<el-button type="primary" link @click="onSelect(scope.row)">选择</el-button>
</template>
</el-table-column>
</el-table>
</el-main>
<el-footer class="sa-flex" :class="state.multiple ? 'sa-row-between' : 'sa-row-right'">
<sa-pagination class="is-ellipsis" v-model="pagination" @pagination-change="getData"></sa-pagination>
<el-button v-if="state.multiple" type="primary" @click="onConfirm">确 定</el-button>
</el-footer>
</el-container>
</div>