- 框架初始化
 - 安装插件
 - 修复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,248 @@
{include file="/shopro/common/script" /}
<style>
.comment-form .sa-template-wrap .item {
border-bottom: none
}
.comment-form .goods-image {
margin-right: 8px;
}
.comment-form .goods-price {
color: var(--el-color-danger);
}
.comment-form .top {
background: var(--sa-table-header-bg);
padding: 20px 24px 0;
font-size: 12px;
color: #8c8c8c;
}
.comment-form .top .el-col {
margin-bottom: 20px;
}
.comment-form .top .title {
font-size: 14px;
line-height: 18px;
font-weight: 500;
color: var(--sa-title);
margin-bottom: 8px;
}
.comment-form .top .goods-title {
color: var(--el-color-primary);
margin-bottom: 8px;
}
.comment-form .left {
flex-shrink: 0;
}
.comment-form .bottom {
margin: 32px 20px 0;
}
.comment-form .avatar {
margin-right: 12px;
}
.comment-form .list {
padding: 20px 0;
border-bottom: 1px solid var(--sa-space);
}
.comment-form .nickname {
font-weight: 500;
font-size: 12px;
color: var(--sa-subfont);
margin-bottom: 4px;
}
.comment-form .reply-time {
font-weight: 400;
font-size: 12px;
color: var(--sa-subfont);
margin-bottom: 8px;
}
.comment-form .reply-content {
color: var(--sa-subtitle);
font-weight: 500;
font-size: 12px;
margin-bottom: 8px;
}
.comment-form .list-image {
margin-right: 8px;
}
.comment-form .list-image:last-of-type {
margin-right: 0;
}
</style>
<div id="addEdit" class="comment-form" v-cloak>
<el-container v-if="state.type=='add'" class="panel-block">
<el-main>
<el-scrollbar height="100%">
<el-form :model="form.model" :rules="form.rules" ref="formRef" label-width="100px">
<el-form-item label="评价内容" prop="content">
<el-input class="sa-w-360" v-model="form.model.content" autosize type="textarea"
placeholder="请输入评价内容">
</el-input>
</el-form-item>
<el-form-item label="评价图片">
<sa-uploader v-model="form.model.images" :multiple="true"></sa-uploader>
</el-form-item>
<el-form-item label="评价星级" prop="level">
<el-rate v-model="form.model.level"></el-rate>
</el-form-item>
<el-form-item label="评价用户" prop="user_id">
<el-button v-if="!form.model.user_id" type="primary" link @click="onSelectFakeUser">
选择虚拟用户
</el-button>
<div v-if="form.model.user_id" class="sa-template-wrap">
<div class="item">
<div class="key id">{{ state.fakeUserData?.id }}</div>
<div class="key">{{ state.fakeUserData?.nickname }}</div>
<div class="oper">
<el-button type="danger" link @click="onDeleteFakeUser">
移除
</el-button>
</div>
</div>
</div>
</el-form-item>
<el-form-item label="商品选择" prop="goods_id">
<el-button v-if="!form.model.goods_id" type="primary" link @click="onSelectGoods">选择商品
</el-button>
<div v-if="form.model.goods_id" class="sa-template-wrap">
<div class="item">
<div class="key id">{{ form.model.goods_id }}</div>
<div class="key">
<sa-image class="goods-image" :url="state.goodsData?.image" size="40"></sa-image>
<div class="right">
<div class="goods-title sa-table-line-1">
{{ state.goodsData?.title }}
</div>
<div class="goods-price">
¥{{ state.goodsData?.price.join('~') || 0 }}
</div>
</div>
</div>
<div class="oper">
<el-button type="danger" link @click="onDeleteGoods">移除</el-button>
</div>
</div>
</div>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.model.status">
<el-radio label="normal">显示</el-radio>
<el-radio label="hidden">隐藏</el-radio>
</el-radio-group>
</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>
<el-container v-if="state.type=='edit'" class="panel-block">
<el-main>
<el-row class="top" :gutter="10">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<div class="title">评价信息</div>
<div class="item sa-flex">
<div class="left">用户昵称:</div>
<div class="right">{{form.model.user?.nickname || form.model.user_id}}</div>
</div>
<div class="item sa-flex">
<div class="left">评价星级:</div>
<div class="right">
<el-rate v-model="form.model.level" disabled></el-rate>
</div>
</div>
<div class="item sa-flex">
<div class="left">显示状态:</div>
<div class="right">
<el-radio-group v-model="form.model.status" @change="onChangeStatus">
<el-radio label="normal">正常</el-radio>
<el-radio label="hidden">隐藏</el-radio>
</el-radio-group>
</div>
</div>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<div class="title">商品信息</div>
<div v-if="form.model.order_item" class="sa-flex">
<sa-image class="mr-2" :url="form.model.order_item.goods_image" size="64"></sa-image>
<div class="right">
<div class="goods-title sa-table-line-1">
{{ form.model.order_item.goods_title }}
</div>
<div class="sa-flex mb-2">
<div class="left">单价:</div>
<div class="right goods-num">{{ form.model.order_item.goods_price }}×{{
form.model.order_item.goods_num }}</div>
</div>
<div v-if="form.model.order_item.goods_sku_text" class="sa-flex">
<div class="left">规格:</div>
<div class="right goods-num">{{ form.model.order_item.goods_sku_text }},</div>
</div>
</div>
</div>
<div v-else-if="form.model.goods" class="sa-flex">
<sa-image class="mr-2" :url="form.model.goods.image" size="64"></sa-image>
<div class="right">
<div class="goods-title sa-table-line-1">{{form.model.goods.title}}</div>
<div class="item sa-flex">
<div class="left">单价:</div>
<div class="right goods-num">
{{form.model.goods.price.join(',')}}
</div>
</div>
<div v-if="form.model.goods.sku_text" class="item sa-flex">
<div class="left">规格:</div>
<div class="right goods-num">{{form.model.goods.sku_text }}</div>
</div>
</div>
</div>
</el-col>
</el-row>
<div class="bottom">
<div class="title sa-flex sa-row-between">
<div>评价记录</div>
{if $auth->check('shopro/goods/comment/reply')}
<el-button v-if="!form.model.reply_time" type="primary" link @click="onReply">点击回复</el-button>
{/if}
</div>
<div v-if="form.model.admin" class="list sa-flex sa-col-top">
<sa-image class="avatar" :url="form.model.admin.avatar" size="48"></sa-image>
<div>
<div class="nickname">{{ form.model.admin.nickname }}</div>
<div class="reply-time">{{ form.model.reply_time }}</div>
<div class="reply-content">{{ form.model.reply_content }}</div>
</div>
</div>
<div v-if="form.model.user" class="list sa-flex sa-col-top">
<sa-image class="avatar" :url="form.model.user.avatar" size="48"></sa-image>
<div>
<div class="nickname">{{ form.model.user.nickname }}</div>
<div class="reply-time">{{ form.model.createtime }}</div>
<div class="reply-content">{{ form.model.content }}</div>
<div class="sa-flex">
<template v-for="item in form.model.images">
<sa-image class="list-image" :url="item" size="48"></sa-image>
</template>
</div>
</div>
</div>
</div>
</el-main>
</el-container>
</div>

View File

@@ -0,0 +1,178 @@
{include file="/shopro/common/script" /}
<style>
.comment-index .image {
margin-right: 4px;
}
.comment-index .goods-item .goods-image {
margin-right: 8px;
}
.comment-index .goods-item .goods-title {
color: var(--el-color-primary);
cursor: pointer;
}
</style>
<div id="index" class="comment-index panel panel-default panel-intro" v-cloak>
<el-container class="panel-block">
<el-header class="sa-header">
<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/goods/comment/add')}
<el-button plain @click="onAdd">添加虚拟评价</el-button>
{/if}
{if $auth->check('shopro/goods/comment/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 @selection-change="onChangeSelection">
<el-table-column type="selection" width="48"></el-table-column>
<el-table-column label="商品信息" min-width="310">
<template #default="scope">
<div v-if="scope.row.order_item" class="goods-item sa-flex">
<sa-image class="goods-image" :url="scope.row.order_item.goods_image" size="40"></sa-image>
<div class="right">
<span class="goods-title sa-table-line-1"
@click="onOpenGoodsDetail(scope.row.order_item.goods_id)">
{{ scope.row.order_item.goods_title || '-' }}
</span>
<span v-if="scope.row.order" class="sa-table-line-1">
订单号:{{ scope.row.order.order_sn }}
<el-icon class="copy-document" @click="onClipboard(scope.row.order.order_sn)">
<copy-document />
</el-icon>
</span>
<span v-else>订单号:-</span>
</div>
</div>
<div v-else-if="scope.row.goods" class="goods-item sa-flex">
<sa-image class="goods-image" :url="scope.row.goods.image" size="40"></sa-image>
<div class="right">
<span class=" goods-title sa-table-line-1"
@click="onOpenGoodsDetail(scope.row.goods.id)">
{{ scope.row.goods.title || '-' }}
</span>
<span>虚拟评价</span>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="用户信息" min-width="96" align="center">
<template #default="scope">
<sa-user-profile :user="scope.row.user" :id="scope.row.user_id" mode="col"
:ishover="scope.row.user_type != 'fake_user'"></sa-user-profile>
</template>
</el-table-column>
<el-table-column label="评价星级" min-width="146">
<template #default="scope">
<el-rate v-model="scope.row.level" disabled></el-rate>
</template>
</el-table-column>
<el-table-column label="评价图片" width="200">
<template #default="scope">
<el-scrollbar>
<div class="sa-flex">
<template v-for="item in scope.row.images" :key="item">
<sa-image class="image" :url="item" size="30"></sa-image>
</template>
</div>
</el-scrollbar>
</template>
</el-table-column>
<el-table-column label="评价内容" min-width="162">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.content || '-' }}
</div>
</template>
</el-table-column>
<el-table-column label="评价时间" width="172">
<template #default="scope">
{{ scope.row.createtime || '-' }}
</template>
</el-table-column>
<el-table-column label="显示状态" min-width="130">
<template #default="scope">
{if $auth->check('shopro/goods/comment/edit')}
<el-dropdown @command="onCommand">
<el-button link>
<el-tag :type="scope.row.status == 'normal' ? 'success' : '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',
}">
<span class="status-normal">正常</span>
</el-dropdown-item>
<el-dropdown-item :command="{
id: scope.row.id,
type: 'hidden',
}">
<span class="status-hidden">隐藏</span>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
{/if}
</template>
</el-table-column>
<el-table-column fixed="right" label="操作" min-width="120">
<template #default="scope">
{if $auth->check('shopro/goods/comment/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/goods/comment/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-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/goods/comment/delete')}
<el-button type="danger" :disabled="!batchHandle.data.length" @click="onBatchHandle('delete')">删除
</el-button>
{/if}
{if $auth->check('shopro/goods/comment/edit')}
<el-button type="success" :disabled="!batchHandle.data.length" @click="onBatchHandle('normal')">正常
</el-button>
{/if}
{if $auth->check('shopro/goods/comment/edit')}
<el-button type="info" :disabled="!batchHandle.data.length" @click="onBatchHandle('hidden')">隐藏
</el-button>
{/if}
</div>
</div>
<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="comment-recyclebin panel panel-default panel-intro" 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" 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.content || '-' }}</div>
</template>
</el-table-column>
<el-table-column prop="deletetime" label="删除时间" width="172" sortable="custom"></el-table-column>
<el-table-column fixed="right" label="操作" min-width="120">
<template #default="scope">
{if $auth->check('shopro/goods/comment/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/goods/comment/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/goods/comment/restore')}
<el-button type="primary" :disabled="!batchHandle.data.length" @click="onBatchHandle('restore')">还原
</el-button>
{/if}
{if $auth->check('shopro/goods/comment/destroy')}
<el-button type="danger" :disabled="!batchHandle.data.length" @click="onBatchHandle('destroy')">销毁
</el-button>
{/if}
{if $auth->check('shopro/goods/comment/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,18 @@
{include file="/shopro/common/script" /}
<div id="reply" class="comment-reply" 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="100px">
<el-form-item label="回复内容" prop="content">
<el-input class="sa-w-360" v-model="form.model.content" placeholder="请输入回复内容"></el-input>
</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,889 @@
{include file="/shopro/common/script" /}
<style>
.goods-form .el-header {
--el-header-padding: 10px 20px 0;
--el-header-height: fit-content;
}
.goods-form .el-header .el-tabs__header {
margin: 0;
}
.goods-form .goods-type {
width: 140px;
height: 56px;
border: 1px solid rgb(230, 230, 230);
border-radius: 4px;
margin-left: 16px;
cursor: pointer;
}
.goods-form .goods-type.is-active {
border: 1px solid var(--el-color-primary);
}
.goods-form .title {
width: 100%;
height: 40px;
line-height: 40px;
padding-left: 16px;
background: var(--sa-table-striped);
margin: 24px 0 16px;
font-weight: 500;
font-size: 14px;
color: #434343;
}
.goods-form .sku-wrap {
width: 100%;
border: 1px solid var(--sa-border);
padding: 8px;
box-sizing: border-box;
}
.goods-form .sku-wrap .sku {
width: 100%;
min-height: 100px;
}
.goods-form .sku-wrap .sku .sku-key {
width: 100%;
height: 40px;
color: var(--sa-subtitle);
padding: 0 16px;
background: var(--sa-table-header-bg);
font-size: 14px;
}
.goods-form .sku-wrap .sku .sku-key .sku-value-title {
margin-right: 16px;
}
.goods-form .sku-wrap .sku .sku-key .sku-key-input {
width: 120px;
}
.goods-form .sku-wrap .sku .sku-key .sku-key-icon {
color: var(--el-color-primary);
cursor: pointer;
}
.goods-form .sku-wrap .sku .sku-value {
padding: 12px 0 0 30px;
font-size: 14px;
color: var(--sa-subtitle);
}
.goods-form .sku-wrap .sku .sku-value .sku-value-title {
height: 32px;
margin-right: 16px;
margin-bottom: 16px;
}
.goods-form .sku-wrap .sku .sku-value .sku-value-box {
position: relative;
margin-right: 24px;
margin-bottom: 16px;
}
.goods-form .sku-wrap .sku .sku-value .sku-value-box .sku-value-input {
width: 104px;
}
.goods-form .sku-wrap .sku .sku-value .sku-value-box .sku-value-icon {
position: absolute;
right: -8px;
top: -8px;
width: 16px;
height: 16px;
color: var(--el-color-primary);
}
.goods-form .sku-wrap .sku .sku-value .sku-value-add {
margin-right: 24px;
margin-bottom: 16px;
}
.goods-form .sku-wrap .sku-tools {
width: 100%;
height: 40px;
color: #434343;
padding-left: 16px;
background: var(--sa-table-header-bg);
font-size: 12px;
}
.goods-form .sku-table-wrap {
width: 100%;
overflow: auto;
margin-top: 16px;
}
.goods-form .sku-table-wrap .sku-table {
width: 100%;
border: 1px solid var(--sa-border);
}
.goods-form .sku-table-wrap .sku-table tbody {
font-size: 12px;
}
.goods-form .sku-table-wrap .sku-table th {
font-size: 12px;
color: var(--subtitle);
height: 32px;
line-height: 1;
padding-left: 12px;
box-sizing: border-box;
text-align: left;
}
.goods-form .sku-table-wrap .sku-table th .sku-table-header-title {
margin-right: 10px;
}
.goods-form .sku-table-wrap .sku-table th .th-title {
font-size: 12px;
color: var(--subtitle);
font-weight: bold;
}
.goods-form .sku-table-wrap .sku-table td {
min-width: 88px;
padding: 0 10px;
height: 40px;
box-sizing: border-box;
}
.goods-form .sku-table-wrap .sku-table td.image {
min-width: 48px;
}
.goods-form .sku-table-wrap .sku-table td.stock {
min-width: 138px;
}
.goods-form .sku-table-wrap .sku-table td.stock_warning {
min-width: 168px;
}
.goods-form .sku-table-wrap .sku-table td.stock_warning .sku-stock-switch {
margin-right: 10px;
}
.goods-form .sku-table-wrap .sku-table td.sn {
min-width: 116px;
}
.goods-form .batch-icon {
font-size: 12px;
color: var(--el-color-primary);
margin-left: 8px;
cursor: pointer;
}
.sales-show-type .exact,
.sales-show-type .sketchy {
width: 220px;
height: 98px;
}
.stock-show-type .exact,
.stock-show-type .sketchy {
width: 220px;
height: 74px;
}
.goods-form .el-select {
flex: 1;
}
.goods-form .category-tag-wrap {
flex: 1;
min-height: 32px;
padding-right: 12px;
border-radius: 4px;
border: 1px solid var(--sa-border);
cursor: pointer;
position: relative;
}
.goods-form .category-tag-wrap .el-tag {
display: inline-flex;
align-items: center;
max-width: 100%;
margin: 2px 0 2px 6px;
text-overflow: ellipsis;
}
.goods-form .category-tag-wrap-suffix {
width: 12px;
height: 100%;
position: absolute;
right: 6px;
top: 0;
display: flex;
align-items: center;
justify-content: center;
}
.goods-form .category-tag-wrap-suffix .circle-close {
display: none;
}
.goods-form .category-tag-wrap-suffix.is-active:hover .circle-close {
display: block;
}
.goods-form .category-tag-wrap-suffix.is-active:hover .arrow-down {
display: none;
}
.category-tooltip {}
.goods-form .is-error {
color: #FF4D4F;
}
.goods-form .el-affix, .goods-form .el-tabs{
width: 100%;
}
.editor-form-item .el-form-item__content {
margin-left: 16px !important;
}
.note-editable {
height: 300px !important;
}
</style>
<div id="addEdit" class="goods-form" v-cloak>
<el-container class="panel-block">
<el-header>
<el-tabs v-model="state.activeStep" @tab-click="isValidate">
<el-tab-pane :name="0">
<template #label>
<div class="sa-flex" :class="validateData['0']?'is-error':''">
基本信息
<el-icon v-if="validateData['0']" class="ml-1">
<warning-filled />
</el-icon>
</div>
</template>
</el-tab-pane>
<el-tab-pane :name="1">
<template #label>
<div class="sa-flex" :class="validateData['1']?'is-error':''">
价格/库存
<el-icon v-if="validateData['1']" class="ml-1">
<warning-filled />
</el-icon>
</div>
</template>
</el-tab-pane>
<el-tab-pane :name="2">
<template #label>
<div class="sa-flex" :class="validateData['2']?'is-error':''">
发货设置
<el-icon v-if="validateData['2']" class="ml-1">
<warning-filled />
</el-icon>
</div>
</template>
</el-tab-pane>
<el-tab-pane :name="3">
<template #label>
<div class="sa-flex" :class="validateData['3']?'is-error':''">
商品参数
<el-icon v-if="validateData['3']" class="ml-1">
<warning-filled />
</el-icon>
</div>
</template>
</el-tab-pane>
<el-tab-pane :name="4">
<template #label>
<div class="sa-flex" :class="validateData['4']?'is-error':''">
商品详情
<el-icon v-if="validateData['4']" class="ml-1">
<warning-filled />
</el-icon>
</div>
</template>
</el-tab-pane>
</el-tabs>
</el-header>
<el-main>
<el-scrollbar height="100%">
<el-form :model="form.model" :rules="form.rules" ref="formRef0" label-width="100px">
<div v-show="state.activeStep==0">
<div class="sa-flex mb-4">
<img v-if="!(state.type=='edit' && form.model.type=='virtual')" class="goods-type" :class="form.model.type=='normal'?'is-active':''"
src="/assets/addons/shopro/img/goods/normal.png" @click="onChangeGoodsType('normal')" />
<img v-if="!(state.type=='edit' && form.model.type=='normal')" class="goods-type" :class="form.model.type=='virtual'?'is-active':''"
src="/assets/addons/shopro/img/goods/virtual.png"
@click="onChangeGoodsType('virtual')" />
</div>
<el-form-item label="商品标题" prop="title">
<el-input class="sa-w-360" v-model="form.model.title" placeholder="请输入商品标题"></el-input>
</el-form-item>
<el-form-item label="副标题">
<el-input class="sa-w-360" v-model="form.model.subtitle" placeholder="请输入副标题"></el-input>
</el-form-item>
<el-form-item label="商品主图" prop="image">
<sa-uploader v-model="form.model.image" type="size" @success="onSuccess"></sa-uploader>
<div class="warning"> 作用于商城列表、分享图片建议尺寸750*750 px </div>
</el-form-item>
<el-form-item label="轮播图" prop="images">
<sa-uploader v-model="form.model.images" :multiple="true"></sa-uploader>
<div class="warning">
作用于商品详情顶部轮播显示,<br />轮播图可以拖拽调整顺序
</div>
</el-form-item>
<el-form-item label="商品分类">
<div class="sa-w-360">
<el-popover popper-class="category-tooltip sa-popper" effect="light"
placement="top-start" trigger="click">
<el-tabs v-model="tempCategory.tabActive">
<el-tab-pane v-for="tab in category.select" :key="tab" :label="tab.name"
:name="tab.id + ''">
<el-cascader-panel v-model="tempCategory.idsArr[tab.id]"
:ref="(el) => setCategoryRef(el, tab)" :options="tab.children" :props="{
multiple: true,
checkStrictly: true,
value: 'id',
label: 'name',
children: 'children',
emitPath: false,
}" @change="onChangeCategoryIds"></el-cascader-panel>
</el-tab-pane>
</el-tabs>
<template #reference>
<div class="category-tag-wrap">
<el-tag v-for="(value, key) in tempCategory.label" :key="key" type="info"
closable @close.stop="onDeleteCategoryIds(key)">{{ value }}</el-tag>
<div class="category-tag-wrap-suffix"
:class="JSON.stringify(tempCategory.label) == '{}'?'':'is-active'">
<el-icon class="arrow-down">
<arrow-down />
</el-icon>
<el-icon class="circle-close" @click.stop="onClearCategoryIds">
<circle-close />
</el-icon>
</div>
</div>
</template>
</el-popover>
{if $auth->check('shopro/category/add')}
<el-button class="label-tip" type="primary" link @click="onAddCategory">添加商品分类</el-button>
{/if}
</div>
</el-form-item>
<el-form-item label="商品排序">
<el-input class="sa-w-360" v-model="form.model.weigh" placeholder="请输入商品排序" type="number"
:min="0">
</el-input>
</el-form-item>
<el-form-item label="限购类型">
<el-radio-group v-model="form.model.limit_type">
<el-radio label="none">不限购</el-radio>
<el-radio label="daily">每日</el-radio>
<el-radio label="all">累计</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="form.model.limit_type != 'none'" label="限购数量">
<el-input class="sa-w-360" v-model="form.model.limit_num" placeholder="请输入限购数量" :min="0"
type="number">
</el-input>
</el-input>
</el-form-item>
<el-form-item label="商品状态">
<el-radio-group v-model="form.model.status">
<el-radio label="up">上架</el-radio>
<el-radio label="hidden">隐藏</el-radio>
<el-radio label="down">下架</el-radio>
</el-radio-group>
</el-form-item>
</div>
</el-form>
<el-form :model="form.model" :rules="form.rules" ref="formRef1" label-width="100px">
<div v-show="state.activeStep==1">
<el-form-item label="商品规格">
<div class="sa-flex">
<el-radio-group :disabled="state.type == 'edit'" v-model="form.model.is_sku">
<el-radio :label="0">单规格</el-radio>
<el-radio :label="1">多规格</el-radio>
</el-radio-group>
<div class="warning">
如商品参与了拼团、秒杀、积分等活动,切换规格,可能导致活动规格不可用
</div>
</div>
</el-form-item>
<template v-if="form.model.is_sku == 1">
<div class="sku-wrap">
<div class="sku" v-for="(s, k) in form.model.skus" :key="k">
<div class="sku-key sa-flex sa-row-between">
<div class="sa-flex">
<div class="sku-value-title">规格名称</div>
<el-input class="sku-key-input" v-model="s.name" placeholder="请输入规格名称">
</el-input>
</div>
<el-icon class="sku-key-icon" @click="deleteMainSku(k)">
<circle-close-filled />
</el-icon>
</div>
<div class="sku-value sa-flex sa-flex-wrap">
<div class="sku-value-title sa-flex"> 规格值 </div>
<div class="sku-value-box" v-for="(sc, c) in s.children" :key="c">
<el-input class="sku-value-input" v-model="sc.name" placeholder="请输入规格值">
</el-input>
<el-icon class="sku-value-icon" @click="deleteChildrenSku(k, c)">
<circle-close-filled />
</el-icon>
</div>
<el-button class="sku-value-add" type="primary" link @click="addChildrenSku(k)">
添加规格值
</el-button>
</div>
</div>
<div class="sku-tools sa-flex">
<el-button class="add" type="primary" @click="addMainSku">+ 添加规格</el-button>
</div>
</div>
<!-- 表格 -->
<div class="sku-table-wrap mb-4">
<table class="sku-table" rules="all">
<thead>
<tr>
<template v-for="(item, i) in form.model.skus" :key="i">
<th v-if="item.children.length">{{ item.name }}</th>
</template>
<th>图片</th>
<th>
<div class="sa-flex">
<div class="th-title">价格(元)</div>
<el-popover placement="top" width="160"
v-model:visible="batchPopover.flag.price" trigger="click">
<template #reference>
<el-icon class="batch-icon">
<Edit />
</el-icon>
</template>
<el-input class="mb-2" v-model="batchPopover.value"
placeholder="请输入价格" size="small" type="number" :step="0.01"
:min="0" :precision="2"></el-input>
<div class="sa-flex sa-row-right">
<el-button type="primary" link size="small"
@click="onbatchPopover('price', 'cancel')">取消
</el-button>
<el-button type="primary" size="small"
@click="onbatchPopover('price', 'confirm')">确定
</el-button>
</div>
</el-popover>
</div>
</th>
<th>
<div class="sa-flex">
<div class="th-title">划线价格</div>
<el-popover placement="top" width="160"
v-model:visible="batchPopover.flag.original_price"
trigger="click">
<template #reference>
<el-icon class="batch-icon">
<Edit />
</el-icon>
</template>
<el-input class="mb-2" v-model="batchPopover.value"
placeholder="请输入划线价格" size="small" type="number"
:step="0.01" :min="0" :precision="2"></el-input>
<div class="sa-flex sa-row-right">
<el-button type="primary" link size="small"
@click="onbatchPopover('original_price', 'cancel')">取消
</el-button>
<el-button type="primary" size="small"
@click="onbatchPopover('original_price', 'confirm')">确定
</el-button>
</div>
</el-popover>
</div>
</th>
<th>
<div class="sa-flex">
<div class="th-title">成本价</div>
<el-popover placement="top" width="160"
v-model:visible="batchPopover.flag.cost_price" trigger="click">
<template #reference>
<el-icon class="batch-icon">
<Edit />
</el-icon>
</template>
<el-input class="mb-2" v-model="batchPopover.value"
placeholder="请输入成本价" size="small" type="number" :step="0.01"
:min="0" :precision="2"></el-input>
<div class="sa-flex sa-row-right">
<el-button type="primary" link size="small"
@click="onbatchPopover('cost_price', 'cancel')">取消
</el-button>
<el-button type="primary" size="small"
@click="onbatchPopover('cost_price', 'confirm')">确定
</el-button>
</div>
</el-popover>
</div>
</th>
<th>库存(件)</th>
<th>库存预警(件)</th>
<th>
<div class="sa-flex">
<div class="th-title">重量(kg)</div>
<el-popover placement="top" width="160"
v-model:visible="batchPopover.flag.weight" trigger="click">
<template #reference>
<el-icon class="batch-icon">
<Edit />
</el-icon>
</template>
<el-input class="mb-2" v-model="batchPopover.value"
placeholder="请输入重量" size="small" type="number" :step="0.01"
:min="0" :precision="2"></el-input>
<div class="sa-flex sa-row-right">
<el-button type="primary" link size="small"
@click="onbatchPopover('weight', 'cancel')">取消
</el-button>
<el-button type="primary" size="small"
@click="onbatchPopover('weight', 'confirm')">确定
</el-button>
</div>
</el-popover>
</div>
</th>
<th>
<div class="sa-flex">
<div class="th-title">规格编码</div>
<el-popover placement="top" width="160"
v-model:visible="batchPopover.flag.sn" trigger="click">
<template #reference>
<el-icon class="batch-icon">
<Edit />
</el-icon>
</template>
<el-input class="mb-2" v-model="batchPopover.value"
placeholder="请输入规格编码" size="small" type="number"></el-input>
<div class="sa-flex sa-row-right">
<el-button type="primary" link size="small"
@click="onbatchPopover('sn', 'cancel')">取消</el-button>
<el-button type="primary" size="small"
@click="onbatchPopover('sn', 'confirm')">确定</el-button>
</div>
</el-popover>
</div>
</th>
<th>商品状态</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, i) in form.model.sku_prices" :key="i">
<template v-for="(v, j) in item.goods_sku_text" :key="j">
<td>
<span class="th-center">{{ v }}</span>
</td>
</template>
<td class="image">
<sa-uploader v-model="item.image" size="28">
</sa-uploader>
</td>
<td>
<el-input v-model="item.price" placeholder="请输入价格" size="small"
type="number" :step="0.01" :min="0" :precision="2"></el-input>
</td>
<td>
<el-input v-model="item.original_price" placeholder="请输入划线价格"
size="small" type="number" :step="0.01" :min="0" :precision="2">
</el-input>
</td>
<td>
<el-input v-model="item.cost_price" placeholder="请输入成本价" size="small"
type="number" :step="0.01" :min="0" :precision="2"></el-input>
</td>
<td class="stock">
<el-input v-if="state.type == 'add'" v-model="item.stock"
placeholder="请输入库存" size="small" type="number" :step="1" :min="0">
</el-input>
</el-input>
<span v-if="state.type == 'edit'">
{{ item.stock }}
</span>
</td>
<td class="stock_warning">
<div class="sa-flex">
<el-switch class="sku-stock-switch"
v-model="item.stock_warning_switch"
@change="onChangeStockWarningSwitch(i)"></el-switch>
<span v-if="!item.stock_warning_switch">使用默认库存预警</span>
<el-input v-if="item.stock_warning_switch"
v-model="item.stock_warning" placeholder="请输入" size="small"
type="number" :step="1" :min="0"></el-input>
</div>
</td>
<td>
<el-input v-model="item.weight" placeholder="请输入" size="small"
type="number" :step="0.01" :min="0" :precision="2"></el-input>
</td>
<td class="sn">
<el-input v-model="item.sn" placeholder="请输入" size="small"></el-input>
</td>
<td>
<el-select v-model="item.status" placeholder="请选择" size="small">
<el-option label="上架" value="up"></el-option>
<el-option label="下架" value="down"></el-option>
</el-select>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<template v-if="form.model.is_sku == 0">
<el-form-item label="售卖价格" prop="price">
<el-input class="sa-w-360" v-model="form.model.price" placeholder="请输入售卖价格" type="number">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item label="划线价格">
<el-input class="sa-w-360" v-model="form.model.original_price" placeholder="请输入划线价格"
type="number" :step="0.01" :min="0" :precision="2">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item label="成本价格">
<el-input class="sa-w-360" v-model="form.model.cost_price" placeholder="请输入成本价格"
type="number" :step="0.01" :min="0" :precision="2">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item label="库存类型">
<el-radio-group v-model="form.model.stock_show_type">
<el-radio label="exact">
<div class="sa-flex">
<div>精确显示</div>
<el-popover popper-class="stock-show-type sa-popper" trigger="hover">
<img class="exact"
src="/assets/addons/shopro/img/goods/stock-exact.png" />
<template #reference>
<el-icon class="warning">
<warning />
</el-icon>
</template>
</el-popover>
</div>
</el-radio>
<el-radio label="sketchy">
<div class="sa-flex">
<div>粗略显示</div>
<el-popover popper-class="stock-show-type sa-popper" trigger="hover">
<img class="sketchy"
src="/assets/addons/shopro/img/goods/stock-sketchy.png" />
<template #reference>
<el-icon class="warning">
<warning />
</el-icon>
</template>
</el-popover>
</div>
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="商品库存">
<el-input class="sa-w-360" v-model="form.model.stock" placeholder="请输入商品库存"
type="number" :step="1" :min="0" :disabled="state.type == 'edit'">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item label="库存预警">
<el-switch v-model="state.tempData.isStockWarning"></el-switch>
<div class="warning"> 库存预警在未开启的状态下,使用默认库存预警 </div>
</el-form-item>
<el-form-item v-if="state.tempData.isStockWarning" label="预警数量">
<el-input class="sa-w-360" v-model="form.model.stock_warning" placeholder="请输入库存预警数量">
<template #append></template>
</el-input>
</el-form-item>
</template>
<el-form-item label="销量类型">
<el-radio-group v-model="form.model.sales_show_type">
<el-radio label="exact">
<div class="sa-flex">
<div>精确显示</div>
<el-popover popper-class="sales-show-type sa-popper" trigger="hover">
<img class="exact" src="/assets/addons/shopro/img/goods/sales-exact.png" />
<template #reference>
<el-icon class="warning">
<warning />
</el-icon>
</template>
</el-popover>
</div>
</el-radio>
<el-radio label="sketchy">
<div class="sa-flex">
<div>粗略显示</div>
<el-popover popper-class="sales-show-type sa-popper" trigger="hover">
<img class="sketchy"
src="/assets/addons/shopro/img/goods/sales-sketchy.png" />
<template #reference>
<el-icon class="warning">
<warning />
</el-icon>
</template>
</el-popover>
</div>
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="虚拟销量">
<div class="sa-form-wrap">
<el-input class="sa-w-360" v-model="form.model.show_sales" placeholder="请输入虚拟销量"
type="number" :min="0">
</el-input>
<div class="warning"> 可以提高商品的销量排行榜,鼓励用户下单 </div>
</div>
</el-form-item>
<template v-if="form.model.is_sku == 0">
<el-form-item label="商品重量">
<el-input class="sa-w-360" v-model="form.model.weight" placeholder="请输入商品重量"
type="number" :step="0.01" :min="0" :precision="2">
<template #append>kg</template>
</el-input>
</el-form-item>
<el-form-item label="商品编号">
<el-input class="sa-w-360" v-model="form.model.sn" placeholder="请输入商品编号"></el-input>
</el-form-item>
</template>
</div>
</el-form>
<el-form :model="form.model" :rules="form.rules" ref="formRef2" label-width="100px">
<div v-show="state.activeStep==2">
<template v-if="form.model.type=='normal'">
<el-form-item label="配送方式">
<el-radio-group v-model="form.model.dispatch_type">
<el-radio label="express">物流快递</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="form.model.dispatch_type" label="物流快递" prop="dispatch_id">
<div class="sa-w-360">
<el-select v-model="form.model.dispatch_id" placeholder="请选择物流快递">
<el-option v-for="item in dispatch.select" :key="item.id" :label="item.name"
:value="item.id"></el-option>
</el-select>
{if $auth->check('shopro/dispatch/dispatch/add')}
<el-button class="label-tip" type="primary" link @click="onAddDispatch('express')">
添加物流快递
</el-button>
{/if}
</div>
</el-form-item>
<el-form-item label="货到付款">
<el-switch v-model="form.model.is_offline" :active-value="1" :inactive-value="0"></el-switch>
</el-form-item>
</template>
<template v-if="form.model.type=='virtual'">
<el-form-item label="配送方式">
<el-radio-group v-model="form.model.dispatch_type" @change="onChangeDispatchType">
<el-radio label="autosend">自动发货</el-radio>
<el-radio label="custom">手动发货
<el-popover popper-class="sa-popper" trigger="hover">
在订单管理,手动对订单进行发货,发货时填写自定义发货内容
<template #reference>
<el-icon class="warning">
<warning />
</el-icon>
</template>
</el-popover>
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="form.model.dispatch_type=='autosend'" label="自动发货" prop="dispatch_id">
<div class="sa-w-360">
<el-select v-model="form.model.dispatch_id" placeholder="请选择自动发货">
<el-option v-for="item in dispatch.select" :key="item.id" :label="item.name"
:value="item.id"></el-option>
</el-select>
{if $auth->check('shopro/dispatch/dispatch/add')}
<el-button class="label-tip" type="primary" link @click="onAddDispatch('autosend')">
添加自动发货
</el-button>
{/if}
</div>
</el-form-item>
</template>
</div>
</el-form>
<el-form :model="form.model" :rules="form.rules" ref="formRef3" label-width="100px">
<div v-show="state.activeStep==3">
<el-form-item label="服务保障" prop="service_ids">
<div class="sa-w-360">
<el-select v-model="form.model.service_ids" placeholder="请选择服务保障" multiple>
<el-option v-for="item in service.select" :key="item.id" :label="item.name"
:value="item.id"></el-option>
</el-select>
{if $auth->check('shopro/goods/service/add')}
<el-button class="label-tip" type="primary" link @click="onAddService">
添加服务保障
</el-button>
{/if}
</div>
</el-form-item>
<el-form-item label="参数详情">
<div class="sa-template-wrap">
<div class="header">
<div class="key">参数名称</div>
<div class="key">内容</div>
<div class="oper">操作</div>
</div>
<draggable v-model="form.model.params" :animation="300" handle=".sortable-drag"
item-key="element">
<template #item="{ element, index }">
<div class="item">
<el-form-item class="key" :prop="'params.' + index + '.title'"
:rules="paramsRules.title">
<el-input placeholder="请输入名称" v-model="element.title"></el-input>
</el-form-item>
<el-form-item class="key" :prop="'params.' + index + '.content'"
:rules="paramsRules.content">
<el-input placeholder="请输入内容" v-model="element.content"></el-input>
</el-form-item>
<el-form-item class="oper">
<el-button type="danger" link @click="onDeleteParams(index)">删除
</el-button>
<i class="iconfont iconmove sortable-drag"></i>
</el-form-item>
</div>
</template>
</draggable>
<el-button class="add-params" icon="Plus" @click="onAddParams">添加
</el-button>
</div>
</el-form-item>
</div>
</el-form>
<el-form :model="form.model" :rules="form.rules" ref="formRef4" label-width="100px">
<div v-show="state.activeStep==4">
<el-form-item class="editor-form-item" label="">
<form role="form">
<textarea id="goodsContent" class="editor"></textarea>
</form>
</el-form-item>
</div>
</el-form>
</el-scrollbar>
</el-main>
<el-footer class="sa-footer--submit sa-flex sa-row-right">
<!-- <el-button plain v-if="state.activeStep > 0" @click="onBack">上一步</el-button>
<el-button v-if="state.activeStep < 4" type="primary" @click="onNext">下一步</el-button> -->
<el-button type="primary" @click="onConfirm">确定</el-button>
</el-footer>
</el-container>
</div>

View File

@@ -0,0 +1,153 @@
{include file="/shopro/common/script" /}
<style>
.goods-add-stock .sku-table-wrap {
width: 100%;
overflow: auto;
}
.goods-add-stock .sku-table-wrap .sku-table {
width: 100%;
border: 1px solid var(--sa-border);
}
.goods-add-stock .sku-table-wrap .sku-table th {
font-size: 12px;
color: var(--subtitle);
height: 32px;
line-height: 1;
padding-left: 12px;
box-sizing: border-box;
text-align: left;
}
.goods-add-stock .sku-table-wrap .sku-table th .th-title {
font-size: 12px;
color: var(--subtitle);
font-weight: bold;
}
.goods-add-stock .sku-table-wrap .sku-table td {
min-width: 88px;
padding: 0 10px;
height: 40px;
box-sizing: border-box;
}
.goods-add-stock .sku-table-wrap .sku-table td.image {
min-width: 48px;
}
.goods-add-stock .sku-table-wrap .sku-table td.stock {
min-width: 190px;
}
.goods-add-stock .sku-table-wrap .sku-table td.stock .addsku-input {
width: 80px;
}
.goods-add-stock .sku-table-wrap .sku-table td.stock_warning {
min-width: 168px;
}
.goods-add-stock .sku-table-wrap .sku-table td.sn {
min-width: 116px;
}
.sku-table-wrap .sku-table .up {
color: var(--el-color-success);
}
.goods-add-stock .sku-table-wrap .sku-table .down {
color: var(--el-color-danger);
}
.goods-add-stock .sku-table-wrap .sku-table .hidden {
color: var(--el-color-info);
}
</style>
<div id="addStock" class="goods-add-stock" 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="100px">
<el-form-item v-if="state.is_sku == 0" label="商品库存:" prop="add_stock">
<div class="sa-w-360">
<div class="mr-2">{{ state.stock }}</div>
<el-input type="number" v-model="form.model.add_stock" placeholder="补充库存"><template
#append></template></el-input>
</div>
</el-form-item>
<div v-if="state.is_sku == 1" class="sku-table-wrap">
<table class="sku-table" rules="all">
<thead>
<tr>
<th>规格值</th>
<th>图片</th>
<th>价格(元)</th>
<th>划线价格</th>
<th>成本价</th>
<th>
<div class="sa-flex">
<div class="th-title">库存(件)</div>
<el-popover placement="top" width="160" trigger="click"
v-model:visible="batchPopover.flag">
<template #reference>
<el-icon class="sa-color--primary ml-1">
<Edit />
</el-icon>
</template>
<el-input class="mb-2" v-model="batchPopover.add_stock"
placeholder="请输入内容" size="small"></el-input>
<div class="sa-flex sa-row-right">
<el-button type="primary" link size="small"
@click="onBatchPopover('cancel')">取消</el-button>
<el-button type="primary" size="small"
@click="onBatchPopover('define')">确定</el-button>
</div>
</el-popover>
</div>
</th>
<th>库存预警(件)</th>
<th>重量(kg)</th>
<th>规格编码</th>
<th>商品状态</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, i) in form.model.sku_prices" :key="i">
<td>{{ item.goods_sku_text.join('/') }}</td>
<td class="image">
<sa-image :url="item.image" size="28"></sa-image>
</td>
<td>{{ item.price }}</td>
<td>{{ item.original_price }}</td>
<td>{{ item.cost_price }}</td>
<td class="stock">
<div class="sa-flex sa-row-between">
<div class="stock-title">{{ item.stock }}</div>
<el-input v-model="item.add_stock" placeholder="补充库存量" size="small"
class="addsku-input"
οnkeyup="value=value.replace(/[^\d]/g, '').replace(/^0{1,}/g,'')">
</el-input>
</div>
</td>
<td class="stock_warning">{{ item.stock_warning }}</td>
<td>{{ item.weight }}</td>
<td>{{ item.sn }}</td>
<td :class="item.status">
{{ item.status == 'up' ? `${item.status_text}中` : `已${item.status_text}` }}
</td>
</tr>
</tbody>
</table>
</div>
</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,494 @@
{include file="/shopro/common/script" /}
<style>
.goods-index .goods-index-main {
overflow: hidden;
}
.goods-index .el-aside {
--el-aside-width: 161px;
border-right: 1px solid var(--sa-border);
padding: 0 3px;
}
.goods-index .el-aside .category-all {
line-height: 48px;
border-radius: 4px;
padding: 0 12px;
position: relative;
cursor: pointer;
font-size: 14px;
color: var(--sa-title);
}
.goods-index .el-aside .category-all span:last-child {
color: var(--el-color-primary);
}
.goods-index .el-aside .category-all:hover {
background: var(--t-bg-hover);
}
.goods-index .el-aside .category-all.is-active {
background: var(--t-bg-active);
color: var(--el-color-primary);
}
.goods-index .el-aside .category-all::after {
content: '';
position: absolute;
right: 9px;
bottom: 0;
width: 138px;
height: 1px;
background: var(--sa-space);
}
.goods-index .el-aside .el-tree {
--el-tree-node-content-height: 40px;
--el-tree-node-hover-bg-color: var(--t-bg-hover);
}
.goods-index .el-aside .el-tree>.el-tree-node>.el-tree-node__content {
--el-tree-node-content-height: 54px;
align-items: flex-start;
position: relative;
}
.goods-index .el-aside .el-tree>.el-tree-node>.el-tree-node__content::after {
content: '';
position: absolute;
right: 9px;
bottom: 0;
width: 138px;
height: 1px;
background: var(--sa-space);
}
.goods-index .el-aside .el-tree .el-tree-node__content {
/* align-items: flex-start; */
padding-top: 6px;
border-radius: 4px;
}
.goods-index .el-aside .el-tree .name {
line-height: 20px;
font-size: 12px;
color: var(--sa-font);
}
.goods-index .el-aside .el-tree .goods {
line-height: 16px;
font-size: 12px;
color: var(--sa-subfont);
}
.goods-index .el-aside .el-tree:not(.all) .el-tree-node.is-current>.el-tree-node__content {
background: var(--t-bg-active);
}
.goods-index .el-aside .el-tree:not(.all) .el-tree-node.is-current>.el-tree-node__content .el-tree-node__expand-icon {
color: var(--el-color-primary);
}
.goods-index .el-aside .el-tree:not(.all) .el-tree-node.is-current>.el-tree-node__content .name {
color: var(--el-color-primary);
}
.goods-index .el-aside .el-tree:not(.all) .el-tree-node.is-current>.el-tree-node__content .goods {
color: var(--el-color-primary);
}
.goods-index .goods-item .goods-image {
margin-right: 12px;
}
.goods-index .goods-item .goods-title {
height: 20px;
line-height: 20px;
font-size: 14px;
font-weight: 500;
color: var(--sa-font);
}
.goods-index .goods-item .goods-subtitle {
height: 16px;
line-height: 16px;
font-size: 12px;
font-weight: 400;
color: var(--sa-subfont);
margin-bottom: 6px;
}
.goods-index .activity-tag {
padding: 3px 8px;
border-radius: 10px;
line-height: 14px;
font-size: 12px;
font-weight: 400;
margin-right: 8px;
cursor: pointer;
}
.goods-index .activity-tag:last-of-type {
margin-right: 0;
}
.goods-index .activity-tag.groupon,
.goods-index .activity-tag.groupon_ladder {
color: var(--el-color-primary);
background: var(--t-bg-active);
}
.goods-index .activity-tag.seckill {
color: #ff4d4f;
background: rgba(255, 77, 79, .16);
}
.goods-index .activity-tag.promos {
color: #faad14;
background: rgba(250, 173, 20, 0.16);
}
.goods-index .sku {
width: fit-content;
height: 20px;
line-height: 1;
padding: 0 8px;
font-size: 12px;
color: #fff;
background: var(--el-color-primary);
border-radius: 10px;
cursor: pointer;
}
.goods-index .sku .el-icon {
margin-left: 4px;
}
.goods-index .add-stock {
margin-left: 8px;
}
.goods-index .add-stock .iconfont {
font-size: 12px;
color: var(--el-color-primary);
}
.goods-index .sku-image {
margin-left: 16px;
margin-right: 28px;
}
.goods-index .sku-text {
font-size: 12px;
color: var(--sa-font);
}
.goods-index .price .el-input,
.goods-index .sales .el-input {
flex: 1;
}
.goods-index .price span,
.goods-index .sales span {
margin: 0 8px;
}
.goods-index .sa-table-wrap {
height: 100%;
margin-left: -48px;
overflow: hidden;
}
.goods-index .sa-table-wrap .sa-expand-table .el-table__header-wrapper {
display: none;
}
</style>
<div id="index" class="goods-index panel panel-default panel-intro" v-cloak>
<el-container class="panel-block">
<el-container class="goods-index-main">
<el-aside>
<el-scrollbar height="100%">
<div class="category-all sa-flex sa-row-between"
:class="state.filter.data.category_ids == 'all'?'is-active':''"
@click.stop="onChangeCategoryIds()">
<span>全部商品</span>
<span @click.stop="onFold">折叠</span>
</div>
<el-tree ref="treeRef" :class="state.filter.data.category_ids" :data="category.select" :props="{
label:'name'
}" :expand-on-click-node="false" node-key="id" :current-node-key="state.filter.data.category_ids"
:indent="12" :default-expanded-keys="defaultExpandedKeys" @node-click="onChangeCategoryIds">
<template #default="{ node, data }">
<div>
<div class="name">{{ node.label }}</div>
<div v-if="node.level = 1" class="goods mt-1">
<span v-if="data.children?.length">
子分类{{data.children.length}}
</span>
</div>
</div>
</template>
</el-tree>
</el-scrollbar>
</el-aside>
<el-container>
<el-header class="sa-header">
<el-tabs class="sa-tabs" v-model="state.filter.data.status" @tab-change="onChangeTab">
<el-tab-pane v-for="sl in type.data.status" :key="sl" :label="sl.name" :name="sl.type">
</el-tab-pane>
</el-tabs>
<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/goods/goods/add')}
<el-button icon="Plus" type="primary" @click="onAdd">添加</el-button>
{/if}
{if $auth->check('shopro/goods/goods/recyclebin')}
<el-button type="danger" icon="Delete" plain @click="onRecyclebin">回收站</el-button>
{/if}
</div>
</div>
</el-header>
<el-main class="sa-main">
<div class="sa-table-wrap">
<el-table height="100%" class="sa-table" :data="state.data"
@selection-change="onChangeSelection" @sort-change="onChangeSort"
:expand-row-keys="expandRowKeys" row-key="id" stripe>
<el-table-column type="expand">
<template #default="props">
<el-table class="sa-table sa-expand-table" :data="skuPrice.data" stripe>
<el-table-column width="96"></el-table-column>
<el-table-column prop="id" label="ID" min-width="90"></el-table-column>
<el-table-column label="商品" min-width="440">
<template #default="scope">
<div class="sa-flex">
<sa-image class="sku-image"
:url="scope.row.image || props.row.image" size="32"></sa-image>
<div class="sku-text">
{{ scope.row.goods_sku_text?.join('/') }}
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="price" label="价格" min-width="150"></el-table-column>
<el-table-column prop="sales" label="销量" min-width="100"></el-table-column>
<el-table-column label="浏览量" min-width="100">
<template #default="scope">
{{ scope.row.views || '-' }}</template>
</el-table-column>
<el-table-column prop="stock" label="库存" min-width="100"></el-table-column>
<el-table-column label="更新时间" width="172">
<template #default>-</template>
</el-table-column>
<el-table-column label="操作" min-width="240">
<template #default="scope">
{if $auth->check('shopro/goods/sku_price/edit')}
<el-dropdown popper-class="goods-dropdown" @command="onSkuCommand">
<el-button link>
<el-tag :type="state.statusData.type[scope.row.status]">
{{ scope.row.status_text }}
<el-icon>
<arrow-down />
</el-icon>
</el-tag>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<template v-for="item in type.data.status">
<el-dropdown-item
v-if="item.type!='all' && item.type!='hidden'"
:command="{
goods_id: props.row.id,
id: scope.row.id,
type: item.type,
}">
<span
:style="{color:state.statusData.color[item.type]}">
{{item.name}}
</span>
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
{/if}
</template>
</el-table-column>
</el-table>
</template>
</el-table-column>
<el-table-column type="selection" width="48" align="center"></el-table-column>
<el-table-column sortable="custom" prop="id" label="ID" min-width="90"></el-table-column>
<el-table-column label="商品" min-width="440">
<template #default="scope">
<div class="goods-item sa-flex sa-col-top">
<sa-image class="goods-image" :url="scope.row.image" size="64"></sa-image>
<div class="right">
<div class="goods-title sa-table-line-1">{{scope.row.title}}</div>
<div class="goods-subtitle sa-table-line-1">{{scope.row.subtitle}}</div>
<el-scrollbar>
<div class="sa-flex">
<template v-for="activity in scope.row.activities">
<el-popover popper-class="sa-popper" trigger="hover">
<el-button type="primary" link
@click="onOpenActivityDetail(activity)">
{{ activity.title }}
</el-button>
<template #reference>
<div class="activity-tag" :class="activity.type">
{{ activity.type_text }}
</div>
</template>
</el-popover>
</template>
<template v-for="promo in scope.row.promos">
<el-popover popper-class="sa-popper" trigger="hover">
<el-button type="primary" link
@click="onOpenActivityDetail(activity)">
{{ promo.title }}
</el-button>
<template #reference>
<div class="activity-tag promos">
{{ promo.type_text }}
</div>
</template>
</el-popover>
</template>
</div>
</el-scrollbar>
</div>
</div>
</template>
</el-table-column>
<el-table-column sortable="custom" prop="price" label="价格" min-width="150">
<template #default="scope">
<div>{{ scope.row.price?.join('~') || 0 }}</div>
<div v-if="scope.row.is_sku" class="sku sa-flex sa-row-center"
@click.stop="onExpand(scope.row.id)">
<span>多规格</span>
<el-icon
:class="[ 'expand-arrow', expandRowKeys.includes(scope.row.id) ? 'expand-arrow-up' : 'expand-arrow-down',]">
<arrow-down />
</el-icon>
</div>
</template>
</el-table-column>
<el-table-column sortable="custom" prop="sales" label="销量" min-width="100">
</el-table-column>
<el-table-column sortable="custom" prop="views" label="浏览量" min-width="100">
</el-table-column>
<el-table-column label="库存" min-width="100">
<template #default="scope">
<div class="sa-flex">
<span>{{ scope.row.stock || 0 }}</span>
{if $auth->check('shopro/goods/goods/addStock')}
<el-button class="add-stock" link @click="onEditStock(scope.row)">
<i class="iconfont iconadd-stock"></i>
</el-button>
{/if}
</div>
</template>
</el-table-column>
<el-table-column label="更新时间" width="172">
<template #default="scope">{{ scope.row.createtime || '-' }}</template>
</el-table-column>
<el-table-column label="操作" min-width="240" fixed="right">
<template #default="scope">
<div class="sa-flex">
{if $auth->check('shopro/goods/goods/edit')}
<el-dropdown popper-class="goods-dropdown" @command="onCommand">
<el-button link>
<el-tag :type="state.statusData.type[scope.row.status]">
{{ scope.row.status_text }}
<el-icon>
<arrow-down />
</el-icon>
</el-tag>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<template v-for="item in type.data.status">
<el-dropdown-item v-if="item.type!='all'" :command="{
id: scope.row.id,
type: item.type,
}">
<span :style="{color:state.statusData.color[item.type]}">
{{item.name}}
</span>
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-button type="primary" link @click="onEdit(scope.row.id)">编辑</el-button>
{/if}
{if $auth->check('shopro/goods/goods/add')}
<el-button type="primary" link @click="onCopy(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/goods/goods/delete')}
<el-button type="danger" link>删除</el-button>
{/if}
</template>
</el-popconfirm>
</div>
</template>
</el-table-column>
</el-table>
</div>
</el-main>
</el-container>
</el-container>
<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/goods/goods/delete')}
<el-button type="danger" :disabled="!batchHandle.data.length" @click="onBatchHandle('delete')">删除
</el-button>
{/if}
{if $auth->check('shopro/goods/goods/edit')}
<el-button type="success" :disabled="!batchHandle.data.length" @click="onBatchHandle('up')">上架
</el-button>
{/if}
{if $auth->check('shopro/goods/goods/edit')}
<el-button type="danger" :disabled="!batchHandle.data.length" @click="onBatchHandle('down')">下架
</el-button>
{/if}
{if $auth->check('shopro/goods/goods/edit')}
<el-button type="info" :disabled="!batchHandle.data.length" @click="onBatchHandle('hidden')">隐藏
</el-button>
{/if}
</div>
</div>
<sa-pagination v-model="pagination" @pagination-change="getData"></sa-pagination>
</el-footer>
</el-container>
<sa-filter v-model="state.filter" @filter-change="onChangeFilter">
<template #supplement>
<el-form-item class="price" label="价格区间">
<el-input v-model="state.filter.data.price.min" placeholder="最低价格"></el-input>
<span></span>
<el-input v-model="state.filter.data.price.max" placeholder="最高价格"></el-input>
</el-form-item>
<el-form-item class="sales" label="销量区间">
<el-input v-model="state.filter.data.sales.min" placeholder="最低销量"></el-input>
<span></span>
<el-input v-model="state.filter.data.sales.max" placeholder="最高销量"></el-input>
</el-form-item>
</template>
</sa-filter>
</div>

View File

@@ -0,0 +1,54 @@
{include file="/shopro/common/script" /}
<div id="recyclebin" class="goods-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.title || '-' }}</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/goods/goods/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/goods/goods/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/goods/goods/restore')}
<el-button type="primary" :disabled="!batchHandle.data.length" @click="onBatchHandle('restore')">还原
</el-button>
{/if}
{if $auth->check('shopro/goods/goods/destroy')}
<el-button type="danger" :disabled="!batchHandle.data.length" @click="onBatchHandle('destroy')">销毁
</el-button>
{/if}
{if $auth->check('shopro/goods/goods/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,168 @@
{include file="/shopro/common/script" /}
<style>
.goods-select .el-aside {
--el-aside-width: 180px;
border-right: 1px solid var(--sa-border);
padding: 20px;
}
.goods-select .category-select {
margin-bottom: 16px;
}
.goods-select .el-tree-node__expand-icon {
display: none;
}
.goods-select .el-tree-node__content {
height: 32px;
}
.goods-select .el-tree-node__label {
width: 100%;
}
.goods-select .custom-tree-node {
width: 100%;
height: 32px;
line-height: 32px;
border-radius: 4px;
}
.goods-select .custom-tree-node.is-active {
background: var(--t-bg-active);
color: var(--el-color-primary);
}
.goods-select .expand-arrow {
margin-left: 8px;
}
.goods-select .search-wrap {
--el-header-height: auto;
padding-top: var(--sa-padding);
}
.goods-select .search-price span {
margin-right: 12px;
}
.goods-select .search-price .search-price-min,
.goods-select .search-price .search-price-max {
width: 88px;
}
.goods-select .search-price .search-price-min {
margin-right: 12px;
}
.goods-select .search-keyword {
width: 180px;
}
.goods-select .goods-item {}
.goods-select .goods-item .goods-image {
margin-right: 8px;
}
.goods-select .goods-item .goods-title {
height: 16px;
line-height: 16px;
font-size: 12px;
font-weight: 400;
color: var(--sa-subtitle);
margin-bottom: 6px;
}
.goods-select .goods-item .goods-price {
line-height: 16px;
font-size: 12px;
font-weight: 400;
color: #ff4d4f;
}
</style>
<div id="select" class="goods-select" v-cloak>
<el-container class="panel-block">
<el-aside>
<el-scrollbar height="100%">
<el-select class="category-select" v-model="category.id" placeholder="Select"
@change="getCategoryDetail">
<el-option v-for="item in category.select" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
<el-tree :data="category.detail" empty-text="" :props="{
children: 'children',
label: 'name',
}" :indent="0" :accordion="true">
<template #default="{ node, data }">
<span class="custom-tree-node sa-flex"
:class="data.id == state.filter.data.category_ids ? 'is-active' : ''"
:style="{ 'padding-left': `${node.level * 16}px` }" @click.stop="changeCategoryIds(data)">
<div class="sa-table-line-1">{{ data.name }}</div>
<el-icon v-if="data.children && data.children.length"
:class="['expand-arrow',node.expanded ? 'expand-arrow-up' : 'expand-arrow-down']"
@click.stop="node.expanded = !node.expanded">
<arrow-down />
</el-icon>
</span>
</template>
</el-tree>
</el-scrollbar>
</el-aside>
<el-container>
<el-header class="search-wrap sa-flex sa-flex-wrap sa-row-between">
<div class="sa-flex sa-flex-wrap search-price">
<span>商品价格</span>
<el-input class="search-price-min" v-model="state.filter.data.price.min" placeholder="最低价格">
</el-input>
<span></span>
<el-input class="search-price-max" v-model="state.filter.data.price.max" placeholder="最高价格">
</el-input>
</div>
<el-input class="search-keyword" v-model="state.filter.data.keyword" prefix-icon="Search"
placeholder="请输入搜索内容"></el-input>
</el-header>
<el-main>
<el-table height="100%" class="sa-table" ref="multipleTableRef" :data="state.data" stripe
@select="onSelect" @select-all="onSelectAll">
<el-table-column v-if="state.multiple" type="selection" width="48"></el-table-column>
<el-table-column prop="id" label="ID" min-width="90"></el-table-column>
<el-table-column label="商品信息" min-width="310">
<template #default="scoped">
<div class="goods-item sa-flex sa-col-top">
<sa-image class="goods-image" :url="scoped.row.image" size="40"></sa-image>
<div>
<div class="goods-title sa-m-b-6 sa-table-line-1">
{{ scoped.row.title }}
</div>
<div class="goods-price">¥{{ scoped.row.price.join('~¥') }}</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="stock" label="库存" min-width="120"></el-table-column>
<el-table-column v-if="!state.multiple" label="操作" width="80">
<template #default="scope">
<template v-if="state.data_type == 'score_shop'">
<span v-if="scope.row.is_score_shop">已参加</span>
<el-button v-if="!scope.row.is_score_shop" type="primary" link
@click="onSingleSelect(scope.row)">参加</el-button>
</template>
<template v-else>
<el-button type="primary" link @click="onSingleSelect(scope.row)">选择
</el-button>
</template>
</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>
</el-container>
</div>

View File

@@ -0,0 +1,24 @@
{include file="/shopro/common/script" /}
<div id="addEdit" class="service-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="100px">
<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="服务标识">
<sa-uploader v-model="form.model.image"></sa-uploader>
</el-form-item>
<el-form-item label="说明">
<el-input class="sa-w-360" v-model="form.model.description" placeholder="请输入说明"></el-input>
</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,83 @@
{include file="/shopro/common/script" /}
<div id="index" class="service-index panel panel-default panel-intro" v-cloak>
<el-container class="panel-block">
<el-header class="sa-header">
<div class="sa-title sa-flex sa-row-between">
<div class="sa-title-left">
<div class="left-name">服务保障</div>
</div>
<div class="sa-title-right">
<el-button class="sa-button-refresh" icon="RefreshRight" @click="getData"></el-button>
{if $auth->check('shopro/goods/service/add')}
<el-button icon="Plus" type="primary" @click="onAdd">添加</el-button>
{/if}
</div>
</div>
</el-header>
<el-main class="sa-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="120">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.name || '-' }}
</div>
</template>
</el-table-column>
<el-table-column label="服务标识" min-width="100">
<template #default="scope">
<sa-image :url="scope.row.image" size="30"></sa-image>
</template>
</el-table-column>
<el-table-column label="说明" min-width="170">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.description || '-' }}
</div>
</template>
</el-table-column>
<el-table-column label="创建时间" width="172">
<template #default="scope">
{{ scope.row.createtime || '-' }}
</template>
</el-table-column>
<el-table-column label="更新时间" width="172">
<template #default="scope">
{{ scope.row.updatetime || '-' }}
</template>
</el-table-column>
<el-table-column fixed="right" label="操作" min-width="120">
<template #default="scope">
{if $auth->check('shopro/goods/service/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/goods/service/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-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/goods/service/delete')}
<el-button type="danger" :disabled="!batchHandle.data.length" @click="onBatchHandle('delete')">删除
</el-button>
{/if}
</div>
</div>
<sa-pagination v-model="pagination" @pagination-change="getData"></sa-pagination>
</el-footer>
</el-container>
</div>

View File

@@ -0,0 +1,51 @@
{include file="/shopro/common/script" /}
<div id="index" class="stock-log-index panel panel-default panel-intro" v-cloak>
<el-container class="panel-block">
<el-header class="sa-header">
<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>
</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="400">
<template #default="scope">
<div v-if="scope.row.goods" class="sa-goods-item sa-flex sa-col-top">
<sa-image class="goods-image" :url="scope.row.goods.image" size="48"></sa-image>
<div class="right">
<div class="goods-title sa-table-line-1">{{scope.row.goods.title}}</div>
<div v-if="scope.row.goods_sku_text" class="goods-sku-text">{{scope.row.goods_sku_text}}
</div>
</div>
</div>
<div v-else>{{scope.row.goods_id}}</div>
</template>
</el-table-column>
<el-table-column prop="before" label="补货前" min-width="106"></el-table-column>
<el-table-column prop="stock" label="补货库存" min-width="106"></el-table-column>
<el-table-column prop="msg" label="补货备注" min-width="124"></el-table-column>
<el-table-column prop="createtime" label="创建时间" width="172"></el-table-column>
<el-table-column prop="updatetime" label="更新时间" width="172"></el-table-column>
<el-table-column label="操作人" min-width="140" fixed="right">
<template #default="scope">
<sa-user-profile type="oper" :user="scope.row.oper" :id="scope.row.admin_id" />
</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,23 @@
{include file="/shopro/common/script" /}
<div id="addStock" class="stock-warning-add-stock" 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="100px">
<el-form-item label="商品库存:" prop="stock">
<div class="sa-w-360">
<div class="mr-2">{{ state.stock }}</div>
<el-input v-model="form.model.stock" placeholder="补充库存" type="number">
<template #append></template>
</el-input>
</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,60 @@
{include file="/shopro/common/script" /}
<div id="index" class="stock-warning-index panel panel-default panel-intro" v-cloak>
<el-container class="panel-block">
<el-header class="sa-header">
<el-tabs class="sa-tabs" v-model="state.filter.data.stock_type" @tab-change="onChangeTab">
<el-tab-pane v-for="(value, key) in type.data.stock_type" :key="key"
:label="`${value.name}${value.num ? '(' + value.num + ')' : ''}`" :name="key"></el-tab-pane>
</el-tabs>
<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/goods/stock_warning/recyclebin')}
<el-button type="danger" 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="440">
<template #default="scope">
<div v-if="scope.row.goods" class="sa-goods-item sa-flex sa-col-top">
<sa-image class="goods-image" :url="scope.row.goods.image" size="48"></sa-image>
<div>
<div class="goods-title sa-table-line-1">{{scope.row.goods.title}}</div>
<div v-if="scope.row.goods_sku_text" class="goods-sku-text">{{scope.row.goods_sku_text}}
</div>
</div>
</div>
<div v-else>{{scope.row.goods_id}}</div>
</template>
</el-table-column>
<el-table-column prop="stock" label="库存" min-width="100"></el-table-column>
<el-table-column prop="stock_warning" label="预警库存" min-width="100"></el-table-column>
<el-table-column label="更新时间" width="172">
<template #default="scope">{{ scope.row.createtime || '-' }}</template>
</el-table-column>
<el-table-column label="操作" min-width="100" fixed="right">
<template #default="scope">
{if $auth->check('shopro/goods/stock_warning/addStock')}
<el-button type="primary" link @click="onAddStock(scope.row)">补货</el-button>
{/if}
</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,20 @@
{include file="/shopro/common/script" /}
<div id="recyclebin" class="stock-warning-recyclebin" v-cloak>
<el-container class="panel-block">
<el-main>
<el-table height="100%" class="sa-table" :data="state.data" stripe @sort-change="onChangeSort">
<el-table-column prop="id" label="ID" width="90" sortable="custom"></el-table-column>
<el-table-column label="名称" min-width="120">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.goods?.title || scope.row.goods_id }}</div>
</template>
</el-table-column>
<el-table-column prop="deletetime" label="补货时间" width="172" sortable="custom"></el-table-column>
</el-table>
</el-main>
<el-footer class="sa-footer sa-flex sa-row-right">
<sa-pagination class="is-ellipsis" v-model="pagination" @pagination-change="getData"></sa-pagination>
</el-footer>
</el-container>
</div>