- 框架初始化
 - 安装插件
 - 修复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

View File

@@ -0,0 +1,142 @@
<form id="config-form" class="edit-form form-horizontal" role="form" data-toggle="validator" method="POST" action="">
{if $addon.tips && $addon.tips.value}
<div class="alert {$addon.tips.extend|default='alert-info-light'}" style="margin-bottom:10px;">
{if $addon.tips.title}
<b>{$addon.tips.title|htmlentities}</b><br>
{/if}
{$addon.tips.value|htmlentities}
</div>
{/if}
<div class="panel panel-default panel-intro">
{if count($groupList)>1}
<div class="panel-heading mb-3">
<ul class="nav nav-tabs nav-group">
<li class="active"><a href="#all" data-toggle="tab">全部</a></li>
{foreach name="groupList" id="tab"}
<li><a href="#tab-{$key|htmlentities}" title="{$tab|htmlentities}" data-toggle="tab">{$tab|htmlentities}</a></li>
{/foreach}
</ul>
</div>
{/if}
<div class="panel-body no-padding">
<div id="myTabContent" class="tab-content">
{foreach name="groupList" id="group" key="groupName"}
<div class="tab-pane fade active in" id="tab-{$groupName|htmlentities}">
<table class="table table-striped table-config mb-0">
<tbody>
{foreach name="$addon.config" id="item"}
{if ((!isset($item['group']) || $item['group']=='') && $groupName=='other') || (isset($item['group']) && $item['group']==$group)}
<tr data-favisible="{$item.visible|default=''|htmlentities}" data-name="{$item.name|htmlentities}" class="{if $item.visible??''}hidden{/if}">
<td width="15%">{$item.title|htmlentities}</td>
<td>
<div class="row">
<div class="col-sm-8 col-xs-12">
{switch $item.type}
{case string}
<input {$item.extend} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule|htmlentities}" data-tip="{$item.tip|htmlentities}"/>
{/case}
{case password}
<input {$item.extend} type="password" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule|htmlentities}" data-tip="{$item.tip|htmlentities}"/>
{/case}
{case text}
<textarea {$item.extend} name="row[{$item.name|htmlentities}]" class="form-control" data-rule="{$item.rule|htmlentities}" rows="5" data-tip="{$item.tip|htmlentities}">{$item.value|htmlentities}</textarea>
{/case}
{case array}
<dl class="fieldlist" data-name="row[{$item.name|htmlentities}]">
<dd>
<ins>{:__('Array key')}</ins>
<ins>{:__('Array value')}</ins>
</dd>
<dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
<textarea name="row[{$item.name|htmlentities}]" cols="30" rows="5" class="hide">{$item.value|json_encode|htmlentities}</textarea>
</dl>
{/case}
{case date}
<input {$item.extend} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/>
{/case}
{case time}
<input {$item.extend} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="HH:mm:ss" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/>
{/case}
{case datetime}
<input {$item.extend} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/>
{/case}
{case number}
<input {$item.extend} type="number" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/>
{/case}
{case checkbox}
{foreach name="item.content" item="vo"}
<label for="row[{$item.name|htmlentities}][]-{$key|htmlentities}"><input id="row[{$item.name|htmlentities}][]-{$key|htmlentities}" name="row[{$item.name|htmlentities}][]" type="checkbox" value="{$key|htmlentities}" data-tip="{$item.tip|htmlentities}" {in name="key" value="$item.value" }checked{/in} /> {$vo|htmlentities}</label>
{/foreach}
<span class="msg-box n-right" for="row[{$item.name|htmlentities}]"></span>
{/case}
{case radio}
{foreach name="item.content" item="vo"}
<label for="row[{$item.name|htmlentities}]-{$key|htmlentities}"><input id="row[{$item.name|htmlentities}]-{$key|htmlentities}" name="row[{$item.name|htmlentities}]" type="radio" value="{$key|htmlentities}" data-tip="{$item.tip|htmlentities}" {in name="key" value="$item.value" }checked{/in} /> {$vo|htmlentities}</label>
{/foreach}
<span class="msg-box n-right" for="row[{$item.name|htmlentities}]"></span>
{/case}
{case value="select" break="0"}{/case}
{case value="selects"}
<select {$item.extend} name="row[{$item.name|htmlentities}]{$item.type=='selects'?'[]':''}" class="form-control selectpicker" data-tip="{$item.tip|htmlentities}" {$item.type=='selects'?'multiple':''}>
{foreach name="item.content" item="vo"}
<option value="{$key|htmlentities}" {in name="key" value="$item.value" }selected{/in}>{$vo|htmlentities}</option>
{/foreach}
</select>
{/case}
{case value="image" break="0"}{/case}
{case value="images"}
<div class="form-inline">
<input id="c-{$item.name|htmlentities}" class="form-control" size="28" name="row[{$item.name|htmlentities}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip|htmlentities}">
<span><button type="button" id="plupload-{$item.name|htmlentities}" class="btn btn-danger plupload" data-input-id="c-{$item.name|htmlentities}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}" data-preview-id="p-{$item.name|htmlentities}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-{$item.name|htmlentities}" class="btn btn-primary fachoose" data-input-id="c-{$item.name|htmlentities}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
<ul class="row list-inline plupload-preview" id="p-{$item.name|htmlentities}"></ul>
<span class="msg-box n-right" for="c-{$item.name|htmlentities}"></span>
</div>
{/case}
{case value="file" break="0"}{/case}
{case value="files"}
<div class="form-inline">
<input id="c-{$item.name|htmlentities}" class="form-control" size="28" name="row[{$item.name|htmlentities}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip|htmlentities}">
<span><button type="button" id="plupload-{$item.name|htmlentities}" class="btn btn-danger plupload" data-input-id="c-{$item.name|htmlentities}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-{$item.name|htmlentities}" class="btn btn-primary fachoose" data-input-id="c-{$item.name|htmlentities}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
<span class="msg-box n-right" for="c-{$item.name|htmlentities}"></span>
</div>
{/case}
{case switch}
<input id="c-{$item.name|htmlentities}" name="row[{$item.name|htmlentities}]" type="hidden" value="{:$item.value?1:0}">
<a href="javascript:;" data-toggle="switcher" class="btn-switcher" data-input-id="c-{$item.name|htmlentities}" data-yes="1" data-no="0">
<i class="fa fa-toggle-on text-success {if !$item.value}fa-flip-horizontal text-gray{/if} fa-2x"></i>
</a>
{/case}
{case bool}
<label for="row[{$item.name|htmlentities}]-yes"><input id="row[{$item.name|htmlentities}]-yes" name="row[{$item.name|htmlentities}]" type="radio" value="1" {$item.value?'checked':''} data-tip="{$item.tip|htmlentities}" /> {:__('Yes')}</label>
<label for="row[{$item.name|htmlentities}]-no"><input id="row[{$item.name|htmlentities}]-no" name="row[{$item.name|htmlentities}]" type="radio" value="0" {$item.value?'':'checked'} data-tip="{$item.tip|htmlentities}" /> {:__('No')}</label>
{/case}
{default /}{$item.value|htmlentities}
{/switch}
</div>
<div class="col-sm-4"></div>
</div>
</td>
</tr>
{/if}
{/foreach}
</tbody>
</table>
</div>
{/foreach}
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2" style="width:15%;"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</div>
</div>
</div>
</form>

View File

@@ -0,0 +1,268 @@
<style type="text/css">
.layui-layer-pay .layui-layer-content {
padding: 0;
height: 600px !important;
}
.layui-layer-pay {
border: none;
}
.payimg {
position: relative;
width: 800px;
height: 600px;
}
.payimg .alipaycode {
position: absolute;
left: 265px;
top: 442px;
}
.payimg .wechatcode {
position: absolute;
left: 660px;
top: 442px;
}
.thumbnail img {
width: 100%;
}
.fixed-table-toolbar .pull-right.search {
min-width: 300px;
}
a.title {
color: #444;
}
.releasetips {
position: relative;
}
.releasetips i {
display: block;
background: #f00;
border-radius: 50%;
width: 0.3em;
height: 0.3em;
top: 0px;
right: -8px;
position: absolute;
box-shadow: 0px 0px 2px #f11414;
}
.form-userinfo .breadcrumb {
margin-bottom: 10px;
}
.btn-toggle {
padding: 0;
}
.operate .dropup .dropdown-menu, .navbar-fixed-bottom .dropdown .dropdown-menu {
bottom: inherit;
}
</style>
<div class="panel panel-default panel-intro">
<div class="panel-heading">
{:build_heading(null,FALSE)}
{if $Think.config.fastadmin.api_url}
<ul class="nav nav-tabs nav-category">
<li class="active"><a href="javascript:;" data-id="">{:__('All')}</a></li>
<li><a href="javascript:;" data-id="0">{:__('Uncategoried')}</a></li>
</ul>
{/if}
</div>
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
<a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" data-force-refresh="false"><i class="fa fa-refresh"></i> </a>
{if $Think.config.fastadmin.api_url}
<button type="button" id="faupload-addon" class="btn btn-danger faupload btn-mini-xs" data-url="addon/local" data-chunking="false" data-mimetype="zip,fastaddon" data-multiple="false"><i class="fa fa-upload"></i>
{:__('Local install')}
</button>
<div class="btn-group">
<a href="#" class="btn btn-info btn-switch active btn-mini-xs" data-type="all"><i class="fa fa-list"></i> {:__('All')}</a>
<a href="#" class="btn btn-info btn-switch btn-mini-xs" data-type="free"><i class="fa fa-gift"></i> {:__('Free')}</a>
<a href="#" class="btn btn-info btn-switch btn-mini-xs" data-type="price"><i class="fa fa-rmb"></i> {:__('Paying')}</a>
<a href="#" class="btn btn-info btn-switch btn-mini-xs" data-type="local" data-url="addon/downloaded"><i class="fa fa-laptop"></i> {:__('Local addon')}</a>
</div>
<a class="btn btn-primary btn-userinfo btn-mini-xs" href="javascript:;"><i class="fa fa-user"></i> {:__('Userinfo')}</a>
{/if}
</div>
<table id="table" class="table table-striped table-bordered table-hover" width="100%">
</table>
</div>
</div>
</div>
</div>
</div>
<script id="searchformtpl" type="text/html">
<form action="" class="form-commonsearch hide">
<div class="well" style="box-shadow:none;border-radius:2px;margin-bottom:10px;">
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-3">
<div class="form-group">
<label class="control-label">{:__('Title')}</label>
<input class="operate" type="hidden" data-name="title" value="like"/>
<input class="form-control" type="text" name="title" placeholder="" value=""/>
</div>
</div>
<div class="col-xs-12 col-sm-6 col-md-3">
<div class="form-group">
<label class="control-label">{:__('Type')}</label>
<input class="operate" type="hidden" data-name="type" value="="/>
<input class="form-control" type="text" name="type" placeholder="all" value=""/>
</div>
</div>
<div class="col-xs-12 col-sm-6 col-md-3">
<div class="form-group">
<label class="control-label">{:__('Category')}</label>
<input type="hidden" class="operate" data-name="category_id" value="="/>
<input class="form-control" name="category_id" type="text" value="">
</div>
</div>
<div class="col-xs-12 col-sm-6 col-md-3">
<div class="form-group">
<label class="control-label">{:__('Version')}</label>
<input type="hidden" class="operate" data-name="faversion" value="="/>
<input class="form-control" name="faversion" type="text" value="{$Think.config.fastadmin.version|htmlentities}">
</div>
</div>
<div class="col-xs-12 col-sm-6 col-md-3">
<div class="form-group">
<label class="control-label"></label>
<div class="row">
<div class="col-xs-6">
<input type="submit" class="btn btn-success btn-block" value="{:__('Submit')}"/>
</div>
<div class="col-xs-6">
<input type="reset" class="btn btn-primary btn-block" value="{:__('Reset')}"/>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
</script>
<script id="uninstalltpl" type="text/html">
<div class="">
<div class=""><%=#__("Are you sure you want to unstall %s?", addon['title'])%>
<p class="text-danger">{:__('Delete all the addon file and cannot be recovered!')} </p>
{if config('app_debug')}
<p class="text-danger"><input type="checkbox" name="droptables" id="droptables" data-name="<%=addon['name']%>"/> {:__('Delete all the addon database and cannot be recovered!')} </p>
{/if}
<p class="text-danger">{:__('Please backup important data manually before uninstall!')}</p>
</div>
</div>
</script>
<script id="upgradetpl" type="text/html">
<div class="">
<div class=""><%=#__("Upgrade tips", addon['title'])%></div>
</div>
</script>
<script id="conflicttpl" type="text/html">
<div class="alert alert-dismissable alert-danger">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong>{:__('Warning')}</strong> {:__('Conflict tips')}
</div>
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>{:__('File')}</th>
</tr>
</thead>
<tbody>
<%for(var i=0;i < conflictlist.length;i++){%>
<tr>
<th scope="row"><%=i+1%></th>
<td><%=conflictlist[i]%></td>
</tr>
<%}%>
</tbody>
</table>
</script>
<!--@formatter:off-->
<script id="operatetpl" type="text/html">
<% var labelarr = ['primary', 'success', 'info', 'danger', 'warning']; %>
<% var label = labelarr[item.id % 5]; %>
<% var addon = item.addon; %>
<span class="operate" data-id="<%=item.id%>" data-name="<%=item.name%>">
<% if(!addon){ %>
<% if(typeof item.releaselist !="undefined" && item.releaselist.length>1){%>
<span class="btn-group">
<a href="javascript:;" class="btn btn-xs btn-primary btn-success btn-install"
data-type="<%=item.price<=0?'free':'price';%>"
data-version="<%=item.version%>"><i class="fa fa-cloud-download"></i> {:__('Install')}</a>
<a class="btn btn-xs btn-success dropdown-toggle" data-toggle="dropdown" href="javascript:;">
<span class="fa fa-caret-down"></span>
</a>
<ul class="dropdown-menu">
<% for(var j=0;j< item.releaselist.length;j++){ %>
<li><a href="javascript:;" class="btn-install" data-type="<%=item.price<=0?'free':'price';%>"
data-version="<%=item.releaselist[j].version%>"><%=item.releaselist[j].version%></a></li>
<% } %>
</ul>
</span>
<% }else if(typeof item.releaselist !="undefined" && item.releaselist.length>0){%>
<a href="javascript:;" class="btn btn-xs btn-primary btn-success btn-install"
data-type="<%=item.price<=0?'free':'price';%>"
data-version="<%=item.version%>"><i class="fa fa-cloud-download"></i> {:__('Install')}</a>
<% } %>
<% if(item.demourl){ %>
<a href="<%=item.demourl%>" class="btn btn-xs btn-primary btn-info btn-demo" target="_blank">
<i class="fa fa-flash"></i> {:__('Demo')}
</a>
<% } %>
<% if(item.button){ %>
<a href="<%=item.url%>" class="btn btn-xs btn-primary btn-info" target="_blank">
<%=item.button%>
</a>
<% } %>
<% } else {%>
<% if(addon.version!=item.version){%>
<% if(typeof item.releaselist !="undefined" && item.releaselist.length>1){%>
<span class="btn-group">
<a href="javascript:;" class="btn btn-xs btn-info btn-success btn-upgrade"
data-version="<%=item.version%>"><i class="fa fa-cloud"></i> {:__('Upgrade')}</a>
<a class="btn btn-xs btn-info dropdown-toggle" data-toggle="dropdown"
href="javascript:;">
<span class="fa fa-caret-down"></span>
</a>
<ul class="dropdown-menu">
<% for(var j=0;j< item.releaselist.length;j++){ %>
<li><a href="javascript:;" class="btn-upgrade"
data-version="<%=item.releaselist[j].version%>"><%=item.releaselist[j].version%></a></li>
<% } %>
</ul>
</span>
<% }else{%>
<a href="javascript:;" class="btn btn-xs btn-info btn-upgrade" title="{:__('Upgrade')}" data-version="<%=item.version%>"><i
class="fa fa-cloud"></i> {:__('Upgrade')}</a>
<% }%>
<% }%>
<% if(addon.config){ %>
<a href="javascript:;" class="btn btn-xs btn-primary btn-config" title="{:__('Setting')}"><i class="fa fa-pencil"></i>
{:__('Setting')}</a>
<% } %>
<a href="javascript:;" class="btn btn-xs btn-danger btn-uninstall" title="{:__('Uninstall')}"><i class="fa fa-times"></i>
{:__('Uninstall')}</a>
<% } %>
</span>
</script>
<!--@formatter:on-->

View File

@@ -0,0 +1,52 @@
<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
{:token()}
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Group')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('group[]', $groupdata, null, ['class'=>'form-control selectpicker', 'multiple'=>'', 'data-rule'=>'required'])}
</div>
</div>
<div class="form-group">
<label for="username" class="control-label col-xs-12 col-sm-2">{:__('Username')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="username" name="row[username]" value="" data-rule="required;username" />
</div>
</div>
<div class="form-group">
<label for="email" class="control-label col-xs-12 col-sm-2">{:__('Email')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="email" class="form-control" id="email" name="row[email]" value="" data-rule="required;email" />
</div>
</div>
<div class="form-group">
<label for="mobile" class="control-label col-xs-12 col-sm-2">{:__('Mobile')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="mobile" name="row[mobile]" value="" data-rule="mobile" />
</div>
</div>
<div class="form-group">
<label for="nickname" class="control-label col-xs-12 col-sm-2">{:__('Nickname')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="nickname" name="row[nickname]" autocomplete="off" value="" data-rule="required" />
</div>
</div>
<div class="form-group">
<label for="password" class="control-label col-xs-12 col-sm-2">{:__('Password')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="password" class="form-control" id="password" name="row[password]" autocomplete="new-password" value="" data-rule="required;password" />
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])}
</div>
</div>
<div class="form-group hidden layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>

View File

@@ -0,0 +1,58 @@
<form id="edit-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
{:token()}
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Group')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('group[]', $groupdata, $groupids, ['class'=>'form-control selectpicker', 'multiple'=>'', 'data-rule'=>'required'])}
</div>
</div>
<div class="form-group">
<label for="username" class="control-label col-xs-12 col-sm-2">{:__('Username')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="username" name="row[username]" value="{$row.username|htmlentities}" data-rule="required;username" />
</div>
</div>
<div class="form-group">
<label for="email" class="control-label col-xs-12 col-sm-2">{:__('Email')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="email" class="form-control" id="email" name="row[email]" value="{$row.email|htmlentities}" data-rule="required;email" />
</div>
</div>
<div class="form-group">
<label for="mobile" class="control-label col-xs-12 col-sm-2">{:__('Mobile')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="mobile" name="row[mobile]" value="{$row.mobile|default=''|htmlentities}" data-rule="mobile" />
</div>
</div>
<div class="form-group">
<label for="nickname" class="control-label col-xs-12 col-sm-2">{:__('Nickname')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="nickname" name="row[nickname]" autocomplete="off" value="{$row.nickname|htmlentities}" data-rule="required" />
</div>
</div>
<div class="form-group">
<label for="password" class="control-label col-xs-12 col-sm-2">{:__('Password')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="password" class="form-control" id="password" name="row[password]" autocomplete="new-password" value="" data-rule="password" />
</div>
</div>
<div class="form-group">
<label for="loginfailure" class="control-label col-xs-12 col-sm-2">{:__('Loginfailure')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="number" class="form-control" id="loginfailure" name="row[loginfailure]" value="{$row.loginfailure|htmlentities}" data-rule="required" />
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])}
</div>
</div>
<div class="form-group hidden layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>

View File

@@ -0,0 +1,21 @@
<div class="panel panel-default panel-intro">
{:build_heading()}
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
{:build_toolbar('refresh,add,delete')}
</div>
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
data-operate-edit="{:$auth->check('auth/admin/edit')}"
data-operate-del="{:$auth->check('auth/admin/del')}"
width="100%">
</table>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,27 @@
<style>
.table-adminlog tr td {
word-break: break-all;
}
</style>
<table class="table table-striped table-adminlog">
<thead>
<tr>
<th width="100">{:__('Title')}</th>
<th>{:__('Content')}</th>
</tr>
</thead>
<tbody>
{volist name="row" id="vo" }
<tr>
<td>{:__($key)}</td>
<td>{if $key=='createtime'}{$vo|datetime}{else/}{$vo|htmlentities}{/if}</td>
</tr>
{/volist}
</tbody>
</table>
<div class="hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="reset" class="btn btn-primary btn-embossed btn-close" onclick="Layer.closeAll();">{:__('Close')}</button>
</div>
</div>

View File

@@ -0,0 +1,21 @@
<div class="panel panel-default panel-intro">
{:build_heading()}
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
{:build_toolbar('refresh,delete')}
</div>
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
data-operate-detail="{:$auth->check('auth/adminlog/index')}"
data-operate-del="{:$auth->check('auth/adminlog/del')}"
width="100%">
</table>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,38 @@
<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
{:token()}
<input type="hidden" name="row[rules]" value="" />
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Parent')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('row[pid]', $groupdata, null, ['class'=>'form-control selectpicker', 'data-rule'=>'required'])}
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="name" name="row[name]" value="" data-rule="required" />
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Permission')}:</label>
<div class="col-xs-12 col-sm-8">
<span class="text-muted"><input type="checkbox" name="" id="checkall" /> <label for="checkall"><span>{:__('Check all')}</span></label></span>
<span class="text-muted"><input type="checkbox" name="" id="expandall" /> <label for="expandall"><span>{:__('Expand all')}</span></label></span>
<div id="treeview"></div>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])}
</div>
</div>
<div class="form-group hidden layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>

View File

@@ -0,0 +1,38 @@
<form id="edit-form" class="form-horizontal form-ajax" role="form" method="POST" action="">
{:token()}
<input type="hidden" name="row[rules]" value="" />
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Parent')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('row[pid]', $groupdata, $row['pid'], ['class'=>'form-control selectpicker', 'data-rule'=>'required', 'data-id'=>$row['id'], 'data-pid'=>$row['pid']])}
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="name" name="row[name]" value="{$row.name|htmlentities}" data-rule="required" />
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Permission')}:</label>
<div class="col-xs-12 col-sm-8">
<span class="text-muted"><input type="checkbox" name="" id="checkall" /> <label for="checkall"><span>{:__('Check all')}</span></label></span>
<span class="text-muted"><input type="checkbox" name="" id="expandall" /> <label for="expandall"><span>{:__('Expand all')}</span></label></span>
<div id="treeview"></div>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])}
</div>
</div>
<div class="form-group hidden layer-footer">
<label class="control-label col-xs-12 col-sm-2 col-xs-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>

View File

@@ -0,0 +1,21 @@
<div class="panel panel-default panel-intro">
{:build_heading()}
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
{:build_toolbar('refresh,add,delete')}
</div>
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
data-operate-edit="{:$auth->check('auth/group/edit')}"
data-operate-del="{:$auth->check('auth/group/del')}"
width="100%">
</table>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,87 @@
<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
{:token()}
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Ismenu')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_radios('row[ismenu]', ['1'=>__('Yes'), '0'=>__('No')])}
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Parent')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('row[pid]', $ruledata, null, ['class'=>'form-control', 'required'=>''])}
</div>
</div>
<div class="form-group">
<label for="name" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="name" name="row[name]" data-placeholder-node="{:__('Node tips')}" data-placeholder-menu="{:__('Menu tips')}" value="" data-rule="required" />
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="title" name="row[title]" value="" data-rule="required" />
</div>
</div>
<div class="form-group" data-type="menu">
<label class="control-label col-xs-12 col-sm-2">{:__('Url')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="url" name="row[url]" value="" data-rule="" placeholder="{:__('Url tips')}" />
</div>
</div>
<div class="form-group">
<label for="icon" class="control-label col-xs-12 col-sm-2">{:__('Icon')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group input-groupp-md">
<span class="input-group-addon"><i class="fa fa-circle-o" id="icon-style"></i></span>
<input type="text" class="form-control" id="icon" name="row[icon]" value="fa fa-circle-o" />
<a href="javascript:;" class="btn-search-icon input-group-addon">{:__('Search icon')}</a>
</div>
</div>
</div>
<div class="form-group">
<label for="remark" class="control-label col-xs-12 col-sm-2">{:__('Condition')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea class="form-control" id="condition" name="row[condition]"></textarea>
</div>
</div>
<div class="form-group" data-type="menu">
<label for="remark" class="control-label col-xs-12 col-sm-2">{:__('Menutype')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_radios('row[menutype]', $menutypeList)}
</div>
</div>
<div class="form-group" data-type="menu">
<label for="remark" class="control-label col-xs-12 col-sm-2">{:__('Extend')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea class="form-control" id="extend" name="row[extend]"></textarea>
</div>
</div>
<div class="form-group">
<label for="remark" class="control-label col-xs-12 col-sm-2">{:__('Remark')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea class="form-control" id="remark" name="row[remark]"></textarea>
</div>
</div>
<div class="form-group">
<label for="weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="weigh" name="row[weigh]" value="0" data-rule="required" />
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])}
</div>
</div>
<div class="form-group hidden layer-footer">
<div class="col-xs-2"></div>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>
{include file="auth/rule/tpl" /}

View File

@@ -0,0 +1,87 @@
<form id="edit-form" class="form-horizontal form-ajax" role="form" method="POST" action="">
{:token()}
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Ismenu')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_radios('row[ismenu]', ['1'=>__('Yes'), '0'=>__('No')], $row['ismenu'])}
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Parent')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_select('row[pid]', $ruledata, $row['pid'], ['class'=>'form-control', 'required'=>''])}
</div>
</div>
<div class="form-group">
<label for="name" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="name" name="row[name]" data-placeholder-node="{:__('Node tips')}" data-placeholder-menu="{:__('Menu tips')}" value="{$row.name|htmlentities}" data-rule="required" />
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="title" name="row[title]" value="{$row.title|htmlentities}" data-rule="required" />
</div>
</div>
<div class="form-group" data-type="menu">
<label class="control-label col-xs-12 col-sm-2">{:__('Url')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="url" name="row[url]" value="{$row.url|htmlentities}" data-rule="" placeholder="{:__('Url tips')}" />
</div>
</div>
<div class="form-group">
<label for="icon" class="control-label col-xs-12 col-sm-2">{:__('Icon')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group input-groupp-md">
<span class="input-group-addon"><i class="{$row.icon|htmlentities}" id="icon-style"></i></span>
<input type="text" class="form-control" id="icon" name="row[icon]" value="{$row.icon|htmlentities}" />
<a href="javascript:;" class="btn-search-icon input-group-addon">{:__('Search icon')}</a>
</div>
</div>
</div>
<div class="form-group">
<label for="remark" class="control-label col-xs-12 col-sm-2">{:__('Condition')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea class="form-control" id="condition" name="row[condition]">{$row.condition|htmlentities}</textarea>
</div>
</div>
<div class="form-group" data-type="menu">
<label for="remark" class="control-label col-xs-12 col-sm-2">{:__('Menutype')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_radios('row[menutype]', $menutypeList, $row['menutype'])}
</div>
</div>
<div class="form-group" data-type="menu">
<label for="remark" class="control-label col-xs-12 col-sm-2">{:__('Extend')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea class="form-control" id="extend" name="row[extend]">{$row.extend|htmlentities}</textarea>
</div>
</div>
<div class="form-group">
<label for="remark" class="control-label col-xs-12 col-sm-2">{:__('Remark')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea class="form-control" id="remark" name="row[remark]">{$row.remark|__|htmlentities}</textarea>
</div>
</div>
<div class="form-group">
<label for="weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" class="form-control" id="weigh" name="row[weigh]" value="{$row.weigh|htmlentities}" data-rule="required" />
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])}
</div>
</div>
<div class="form-group hidden layer-footer">
<div class="col-xs-2"></div>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>
{include file="auth/rule/tpl" /}

View File

@@ -0,0 +1,35 @@
<style>
.bootstrap-table tr td .text-muted {color:#888;}
</style>
<div class="panel panel-default panel-intro">
{:build_heading()}
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
<a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" data-force-refresh="false"><i class="fa fa-refresh"></i> </a>
<a href="javascript:;" class="btn btn-success btn-add {:$auth->check('auth/rule/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>
<a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('auth/rule/edit')?'':'hide'}" title="{:__('Edit')}" ><i class="fa fa-pencil"></i> {:__('Edit')}</a>
<a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('auth/rule/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
<div class="dropdown btn-group {:$auth->check('auth/rule/multi')?'':'hide'}">
<a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
<ul class="dropdown-menu text-left" role="menu">
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> {:__('Set to normal')}</a></li>
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> {:__('Set to hidden')}</a></li>
</ul>
</div>
<a href="javascript:;" class="btn btn-danger btn-toggle-all"><i class="fa fa-plus"></i> {:__('Toggle all')}</a>
</div>
<table id="table" class="table table-bordered table-hover"
data-operate-edit="{:$auth->check('auth/rule/edit')}"
data-operate-del="{:$auth->check('auth/rule/del')}"
width="100%">
</table>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,43 @@
<style>
#chooseicon {
margin:10px;
}
#chooseicon ul {
margin:5px 0 0 0;
}
#chooseicon ul li{
width:41px;height:42px;
line-height:42px;
border:1px solid #efefef;
padding:1px;
margin:1px;
text-align: center;
font-size:18px;
}
#chooseicon ul li:hover{
border:1px solid #2c3e50;
cursor:pointer;
}
</style>
<script id="chooseicontpl" type="text/html">
<div id="chooseicon">
<div>
<form onsubmit="return false;">
<div class="input-group input-groupp-md">
<div class="input-group-addon">{:__('Search icon')}</div>
<input class="js-icon-search form-control" type="text" placeholder="">
</div>
</form>
</div>
<div>
<ul class="list-inline">
<% for(var i=0; i<iconlist.length; i++){ %>
<li data-font="<%=iconlist[i]%>" data-toggle="tooltip" title="<%=iconlist[i]%>">
<i class="fa fa-<%=iconlist[i]%>"></i>
</li>
<% } %>
</ul>
</div>
</div>
</script>

View File

@@ -0,0 +1,100 @@
<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
{:token()}
<div class="alert alert-warning-light">
{:__('Category warmtips')}
</div>
<div class="form-group">
<label for="c-type" class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
<div class="col-xs-12 col-sm-8">
<select id="c-type" data-rule="required" class="form-control selectpicker" name="row[type]">
{foreach name="typeList" item="vo"}
<option value="{$key|htmlentities}" {in name="key" value=""}selected{/in}>{$vo|htmlentities}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label for="c-pid" class="control-label col-xs-12 col-sm-2">{:__('Pid')}:</label>
<div class="col-xs-12 col-sm-8">
<select id="c-pid" data-rule="required" class="form-control selectpicker" name="row[pid]">
{foreach name="parentList" item="vo"}
<option data-type="{$vo.type|htmlentities}" value="{$key|htmlentities}" {in name="key" value=""}selected{/in}>{$vo.name|htmlentities}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label for="c-name" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text" value="">
</div>
</div>
<div class="form-group">
<label for="c-nickname" class="control-label col-xs-12 col-sm-2">{:__('Nickname')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-nickname" data-rule="required" class="form-control" name="row[nickname]" type="text" value="">
</div>
</div>
<div class="form-group">
<label for="c-flag" class="control-label col-xs-12 col-sm-2">{:__('Flag')}:</label>
<div class="col-xs-12 col-sm-8">
<select id="c-flag" class="form-control selectpicker" multiple="" name="row[flag][]">
{foreach name="flagList" item="vo"}
<option value="{$key|htmlentities}" {in name="key" value=""}selected{/in}>{$vo|htmlentities}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label for="c-image" class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group">
<input id="c-image" class="form-control" size="35" name="row[image]" type="text" value="">
<div class="input-group-addon no-border no-padding">
<span><button type="button" id="faupload-image" class="btn btn-danger faupload" data-input-id="c-image" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp" data-multiple="false" data-preview-id="p-image"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-input-id="c-image" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
</div>
<span class="msg-box n-right"></span>
</div>
<ul class="row list-inline faupload-preview" id="p-image"></ul>
</div>
</div>
<div class="form-group">
<label for="c-keywords" class="control-label col-xs-12 col-sm-2">{:__('Keywords')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-keywords" class="form-control" name="row[keywords]" type="text" value="">
</div>
</div>
<div class="form-group">
<label for="c-description" class="control-label col-xs-12 col-sm-2">{:__('Description')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea id="c-description" class="form-control" name="row[description]"></textarea>
</div>
</div>
<div class="form-group">
<label for="c-weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-weigh" class="form-control" name="row[weigh]" type="number" value="0">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')])}
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>

View File

@@ -0,0 +1,96 @@
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
{:token()}
<div class="form-group">
<label for="c-type" class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
<div class="col-xs-12 col-sm-8">
<select id="c-type" data-rule="required" class="form-control selectpicker" name="row[type]">
{foreach name="typeList" item="vo"}
<option value="{$key|htmlentities}" {in name="key" value="$row.type"}selected{/in}>{$vo|htmlentities}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label for="c-pid" class="control-label col-xs-12 col-sm-2">{:__('Pid')}:</label>
<div class="col-xs-12 col-sm-8">
<select id="c-pid" data-rule="required" class="form-control selectpicker" name="row[pid]">
{foreach name="parentList" item="vo"}
<option data-type="{$vo.type|htmlentities}" class="{:$vo.type==$row.type||$vo.type=='all'?'':'hide'}" value="{$key|htmlentities}" {in name="key" value="$row.pid"}selected{/in}>{$vo.name|htmlentities}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label for="c-name" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-name" data-rule="required" class="form-control" name="row[name]" type="text" value="{$row.name|htmlentities}">
</div>
</div>
<div class="form-group">
<label for="c-nickname" class="control-label col-xs-12 col-sm-2">{:__('Nickname')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-nickname" data-rule="required" class="form-control" name="row[nickname]" type="text" value="{$row.nickname|htmlentities}">
</div>
</div>
<div class="form-group">
<label for="c-flag" class="control-label col-xs-12 col-sm-2">{:__('Flag')}:</label>
<div class="col-xs-12 col-sm-8">
<select id="c-flag" class="form-control selectpicker" multiple="" name="row[flag][]">
{foreach name="flagList" item="vo"}
<option value="{$key|htmlentities}" {in name="key" value="$row.flag"}selected{/in}>{$vo|htmlentities}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label for="c-image" class="control-label col-xs-12 col-sm-2">{:__('Image')}:</label>
<div class="col-xs-12 col-sm-8">
<div class="input-group">
<input id="c-image" class="form-control" size="35" name="row[image]" type="text" value="{$row.image|htmlentities}">
<div class="input-group-addon no-border no-padding">
<span><button type="button" id="faupload-image" class="btn btn-danger faupload" data-input-id="c-image" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp" data-multiple="false" data-preview-id="p-image"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-image" class="btn btn-primary fachoose" data-input-id="c-image" data-mimetype="image/*" data-multiple="false"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
</div>
<span class="msg-box n-right"></span>
</div>
<ul class="row list-inline faupload-preview" id="p-image"></ul>
</div>
</div>
<div class="form-group">
<label for="c-keywords" class="control-label col-xs-12 col-sm-2">{:__('Keywords')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-keywords" class="form-control" name="row[keywords]" type="text" value="{$row.keywords|htmlentities}">
</div>
</div>
<div class="form-group">
<label for="c-description" class="control-label col-xs-12 col-sm-2">{:__('Description')}:</label>
<div class="col-xs-12 col-sm-8">
<textarea id="c-description" class="form-control" name="row[description]">{$row.description|htmlentities}</textarea>
</div>
</div>
<div class="form-group">
<label for="c-weigh" class="control-label col-xs-12 col-sm-2">{:__('Weigh')}:</label>
<div class="col-xs-12 col-sm-8">
<input id="c-weigh" class="form-control" name="row[weigh]" type="number" value="{$row.weigh|htmlentities}">
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Status')}:</label>
<div class="col-xs-12 col-sm-8">
{:build_radios('row[status]', ['normal'=>__('Normal'), 'hidden'=>__('Hidden')], $row['status'])}
</div>
</div>
<div class="form-group layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>

View File

@@ -0,0 +1,36 @@
<div class="panel panel-default panel-intro">
<div class="panel-heading">
{:build_heading(null,FALSE)}
<ul class="nav nav-tabs">
<li class="active"><a href="#all" data-toggle="tab">{:__('All')}</a></li>
{foreach name="typeList" item="vo"}
<li><a href="#{$key|htmlentities}" data-toggle="tab">{$vo|htmlentities}</a></li>
{/foreach}
</ul>
</div>
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
{:build_toolbar('refresh,add,edit,del')}
<div class="dropdown btn-group {:$auth->check('category/multi')?'':'hide'}">
<a class="btn btn-primary btn-more dropdown-toggle btn-disabled disabled" data-toggle="dropdown"><i class="fa fa-cog"></i> {:__('More')}</a>
<ul class="dropdown-menu text-left" role="menu">
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=normal"><i class="fa fa-eye"></i> {:__('Set to normal')}</a></li>
<li><a class="btn btn-link btn-multi btn-disabled disabled" href="javascript:;" data-params="status=hidden"><i class="fa fa-eye-slash"></i> {:__('Set to hidden')}</a></li>
</ul>
</div>
</div>
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
data-operate-edit="{:$auth->check('category/edit')}"
data-operate-del="{:$auth->check('category/del')}"
width="100%">
</table>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,420 @@
<style>
.relation-item {margin-top:10px;}
legend {padding-bottom:5px;font-size:14px;font-weight:600;}
label {font-weight:normal;}
.form-control{padding:6px 8px;}
#extend-zone .col-xs-2 {margin-top:10px;padding-right:0;}
#extend-zone .col-xs-2:nth-child(6n+0) {padding-right:15px;}
</style>
<div class="panel panel-default panel-intro">
<div class="panel-heading">
<ul class="nav nav-tabs">
<li class="active"><a href="#crud" data-toggle="tab">{:__('一键生成CRUD')}</a></li>
<li><a href="#menu" data-toggle="tab">{:__('一键生成菜单')}</a></li>
<li><a href="#min" data-toggle="tab">{:__('一键压缩打包')}</a></li>
<li><a href="#api" data-toggle="tab">{:__('一键生成API文档')}</a></li>
</ul>
</div>
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="crud">
<div class="row">
<div class="col-xs-12">
<form role="form">
<input type="hidden" name="commandtype" value="crud" />
<div class="form-group">
<div class="row">
<div class="col-xs-3">
<input checked="" name="isrelation" type="hidden" value="0">
<label class="control-label" data-toggle="tooltip" title="当前只支持生成1对1关联模型,选中后请配置关联表和字段">
<input name="isrelation" type="checkbox" value="1">
关联模型
</label>
</div>
<div class="col-xs-3">
<input checked="" name="local" type="hidden" value="1">
<label class="control-label" data-toggle="tooltip" title="默认模型生成在application/admin/model目录下,选中后将生成在application/common/model目录下">
<input name="local" type="checkbox" value="0"> 全局模型类
</label>
</div>
<div class="col-xs-3">
<input checked="" name="delete" type="hidden" value="0">
<label class="control-label" data-toggle="tooltip" title="删除CRUD生成的相关文件">
<input name="delete" type="checkbox" value="1"> 删除模式
</label>
</div>
<div class="col-xs-3">
<input checked="" name="force" type="hidden" value="0">
<label class="control-label" data-toggle="tooltip" title="选中后,如果已经存在同名文件将被覆盖。如果是删除将不再提醒">
<input name="force" type="checkbox" value="1">
强制覆盖模式
</label>
</div>
<!--
<div class="col-xs-3">
<input checked="" name="menu" type="hidden" value="0">
<label class="control-label" data-toggle="tooltip" title="选中后,将同时生成后台菜单规则">
<input name="menu" type="checkbox" value="1">
生成菜单
</label>
</div>
-->
</div>
</div>
<div class="form-group">
<legend>主表设置</legend>
<div class="row">
<div class="col-xs-3">
<label>请选择主表</label>
{:build_select('table',$tableList,null,['class'=>'form-control selectpicker', 'data-live-search'=>'true']);}
</div>
<div class="col-xs-3">
<label>自定义控制器名</label>
<input type="text" class="form-control" name="controller" data-toggle="tooltip" title="默认根据表名自动生成,如果需要放在二级目录请手动填写" placeholder="支持目录层级,以/分隔">
</div>
<div class="col-xs-3">
<label>自定义模型名</label>
<input type="text" class="form-control" name="model" data-toggle="tooltip" title="默认根据表名自动生成" placeholder="不支持目录层级">
</div>
<div class="col-xs-3">
<label>显示字段(默认全部)</label>
<select name="fields[]" id="fields" multiple style="height:30px;" class="form-control selectpicker"></select>
</div>
</div>
</div>
<div class="form-group hide" id="relation-zone">
<legend>关联表设置</legend>
<div class="row" style="margin-top:15px;">
<div class="col-xs-12">
<a href="javascript:;" class="btn btn-primary btn-sm btn-newrelation" data-index="1">追加关联模型</a>
</div>
</div>
</div>
<hr>
<div class="form-group" id="extend-zone">
<legend>字段识别设置 <span style="font-size:12px;font-weight: normal;">(与之匹配的字段都将生成相应组件)</span></legend>
<div class="row">
<div class="col-xs-2">
<label>复选框后缀</label>
<input type="text" class="form-control" name="setcheckboxsuffix" placeholder="默认为set类型" />
</div>
<div class="col-xs-2">
<label>单选框后缀</label>
<input type="text" class="form-control" name="enumradiosuffix" placeholder="默认为enum类型" />
</div>
<div class="col-xs-2">
<label>图片类型后缀</label>
<input type="text" class="form-control" name="imagefield" placeholder="默认为image,images,avatar,avatars" />
</div>
<div class="col-xs-2">
<label>文件类型后缀</label>
<input type="text" class="form-control" name="filefield" placeholder="默认为file,files" />
</div>
<div class="col-xs-2">
<label>日期时间后缀</label>
<input type="text" class="form-control" name="intdatesuffix" placeholder="默认为time" />
</div>
<div class="col-xs-2">
<label>开关后缀</label>
<input type="text" class="form-control" name="switchsuffix" placeholder="默认为switch" />
</div>
<div class="col-xs-2">
<label>城市选择后缀</label>
<input type="text" class="form-control" name="citysuffix" placeholder="默认为city" />
</div>
<div class="col-xs-2">
<label>动态下拉后缀(单)</label>
<input type="text" class="form-control" name="selectpagesuffix" placeholder="默认为_id" />
</div>
<div class="col-xs-2">
<label>动态下拉后缀(多)</label>
<input type="text" class="form-control" name="selectpagessuffix" placeholder="默认为_ids" />
</div>
<div class="col-xs-2">
<label>忽略的字段</label>
<input type="text" class="form-control" name="ignorefields" placeholder="默认无" />
</div>
<div class="col-xs-2">
<label>排序字段</label>
<input type="text" class="form-control" name="sortfield" placeholder="默认为weigh" />
</div>
<div class="col-xs-2">
<label>富文本编辑器</label>
<input type="text" class="form-control" name="editorsuffix" placeholder="默认为content" />
</div>
<div class="col-xs-2">
<label>选项卡过滤字段</label>
<input type="text" class="form-control" name="headingfilterfield" placeholder="默认为status" />
</div>
<div class="col-xs-2">
<label>标签后缀 <i class="fa fa-info-circle" data-toggle="tooltip" data-title="只支持1.3.0+版本"></i></label>
<input type="text" class="form-control" name="tagsuffix" placeholder="默认为tag,tags" />
</div>
<div class="col-xs-2">
<label>JSON后缀 <i class="fa fa-info-circle" data-toggle="tooltip" data-title="只支持1.3.0+版本"></i></label>
<input type="text" class="form-control" name="jsonsuffix" placeholder="默认为json" />
</div>
<div class="col-xs-2">
<label>固定列数量 <i class="fa fa-info-circle" data-toggle="tooltip" data-title="只支持1.3.0+版本大于0时为右侧固定列数量小于0时为左侧固定列数量"></i></label>
<input type="text" class="form-control" name="fixedcolumns" placeholder="默认不启用" />
</div>
</div>
</div>
<div class="form-group">
<legend>生成命令行</legend>
<textarea class="form-control" data-toggle="tooltip" title="如果在线执行命令失败,可以将命令复制到命令行进行执行" rel="command" rows="1" placeholder="请点击生成命令行"></textarea>
</div>
<div class="form-group">
<legend>返回结果</legend>
<textarea class="form-control" rel="result" rows="5" placeholder="请点击立即执行"></textarea>
</div>
<div class="form-group">
<button type="button" class="btn btn-info btn-embossed btn-command">{:__('生成命令行')}</button>
<button type="button" class="btn btn-success btn-embossed btn-execute">{:__('立即执行')}</button>
</div>
</form>
</div>
</div>
</div>
<div class="tab-pane fade" id="menu">
<div class="row">
<div class="col-xs-12">
<form role="form">
<input type="hidden" name="commandtype" value="menu" />
<div class="form-group">
<div class="row">
<div class="col-xs-3">
<input checked="" name="allcontroller" type="hidden" value="0">
<label class="control-label" data-toggle="tooltip" title="将删除全部的菜单规则,重新按控制器进行生成,请做好备份,谨慎选择">
<input name="allcontroller" data-toggle="collapse" data-target="#controller" type="checkbox" value="1"> 一键生成全部控制器
</label>
</div>
<div class="col-xs-3">
<input checked="" name="delete" type="hidden" value="0">
<label class="control-label" data-toggle="tooltip" title="删除控制器菜单规则">
<input name="delete" type="checkbox" value="1"> 删除模式
</label>
</div>
<div class="col-xs-3">
<input checked="" name="force" type="hidden" value="0">
<label class="control-label" data-toggle="tooltip" title="如果菜单规则已经存在则覆盖">
<input name="force" type="checkbox" value="1"> 强制覆盖模式
</label>
</div>
</div>
</div>
<div class="form-group in" id="controller">
<legend>控制器设置</legend>
<div class="row" style="margin-top:15px;">
<div class="col-xs-12">
<input type="text" name="controllerfile" class="form-control selectpage" style="width:720px;" data-source="command/get_controller_list" data-multiple="true" name="controller" placeholder="请选择控制器" />
</div>
</div>
</div>
<div class="form-group">
<legend>生成命令行</legend>
<textarea class="form-control" rel="command" rows="1" placeholder="请点击生成命令行"></textarea>
</div>
<div class="form-group">
<legend>返回结果</legend>
<textarea class="form-control" rel="result" rows="5" placeholder="请点击立即执行"></textarea>
</div>
<div class="form-group">
<button type="button" class="btn btn-info btn-embossed btn-command">{:__('生成命令行')}</button>
<button type="button" class="btn btn-success btn-embossed btn-execute">{:__('立即执行')}</button>
</div>
</form>
</div>
</div>
</div>
<div class="tab-pane fade" id="min">
<div class="row">
<div class="col-xs-12">
<form role="form">
<input type="hidden" name="commandtype" value="min" />
<div class="form-group">
<legend>基础设置</legend>
<div class="row">
<div class="col-xs-3">
<label>请选择压缩模块</label>
<select name="module" class="form-control selectpicker">
<option value="all" selected>全部</option>
<option value="backend">后台Backend</option>
<option value="frontend">前台Frontend</option>
</select>
</div>
<div class="col-xs-3">
<label>请选择压缩资源</label>
<select name="resource" class="form-control selectpicker">
<option value="all" selected>全部</option>
<option value="js">JS</option>
<option value="css">CSS</option>
</select>
</div>
<div class="col-xs-3">
<label>请选择压缩模式</label>
<select name="optimize" class="form-control selectpicker">
<option value=""></option>
<option value="uglify">uglify</option>
<option value="closure">closure</option>
</select>
</div>
</div>
</div>
<div class="form-group">
<legend>生成命令行</legend>
<textarea class="form-control" rel="command" rows="1" placeholder="请点击生成命令行"></textarea>
</div>
<div class="form-group">
<legend>返回结果</legend>
<textarea class="form-control" rel="result" rows="5" placeholder="请点击立即执行"></textarea>
</div>
<div class="form-group">
<button type="button" class="btn btn-info btn-embossed btn-command">{:__('生成命令行')}</button>
<button type="button" class="btn btn-success btn-embossed btn-execute">{:__('立即执行')}</button>
</div>
</form>
</div>
</div>
</div>
<div class="tab-pane fade" id="api">
<div class="row">
<div class="col-xs-12">
<form role="form">
<input type="hidden" name="commandtype" value="api" />
<div class="form-group">
<div class="row">
<div class="col-xs-3">
<input checked="" name="force" type="hidden" value="0">
<label class="control-label" data-toggle="tooltip" title="如果已经存在则覆盖">
<input name="force" type="checkbox" value="1">
覆盖模式
</label>
</div>
</div>
</div>
<div class="form-group">
<legend>文档设置</legend>
<div class="row">
<div class="col-xs-3">
<label>请输入接口URL</label>
<input type="text" name="url" class="form-control" placeholder="API URL,可留空" />
</div>
<div class="col-xs-3">
<label>接口生成文件</label>
<input type="text" name="output" class="form-control" placeholder="留空则使用api.html" />
</div>
<div class="col-xs-3">
<label>模板文件</label>
<input type="text" name="template" class="form-control" placeholder="如果不清楚请留空" />
</div>
<div class="col-xs-3">
<label>文档语言</label>
<select name="language" class="form-control">
<option value="" selected>请选择语言</option>
<option value="zh-cn">中文</option>
<option value="en">英文</option>
</select>
</div>
</div>
<div class="row" style="margin-top:10px;">
<div class="col-xs-3">
<label>文档标题</label>
<input type="text" name="title" class="form-control" placeholder="默认为{$site.name}" />
</div>
<div class="col-xs-3">
<label>文档作者</label>
<input type="text" name="author" class="form-control" placeholder="默认为{$site.name}" />
</div>
<div class="col-xs-3">
<label>生成模块</label>
<select name="module" class="form-control selectpicker">
<option value="" selected>请选择模块</option>
<option value="api">API</option>
<option value="backend">后台</option>
<option value="frontend">前台</option>
</select>
</div>
<div class="col-xs-3">
<label>生成插件文档</label>
<select name="addon" class="form-control selectpicker" data-live-search="true">
<option value="" selected>请选择插件</option>
{foreach name=":get_addon_list()" id="item"}
<option value="{$item.name}">{$item.title}</option>
{/foreach}
</select>
</div>
</div>
</div>
<div class="form-group">
<legend>生成命令行</legend>
<textarea class="form-control" rel="command" rows="1" placeholder="请点击生成命令行"></textarea>
</div>
<div class="form-group">
<legend>返回结果</legend>
<textarea class="form-control" rel="result" rows="5" placeholder="请点击立即执行"></textarea>
</div>
<div class="form-group">
<button type="button" class="btn btn-info btn-embossed btn-command">{:__('生成命令行')}</button>
<button type="button" class="btn btn-success btn-embossed btn-execute">{:__('立即执行')}</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<script id="relationtpl" type="text/html">
<div class="row relation-item">
<div class="col-xs-2">
<label>请选择关联表</label>
<select name="relation[<%=index%>][relation]" class="form-control relationtable" data-live-search="true"></select>
</div>
<div class="col-xs-2">
<label>请选择关联类型</label>
<select name="relation[<%=index%>][relationmode]" class="form-control relationmode"></select>
</div>
<div class="col-xs-2">
<label>关联外键</label>
<select name="relation[<%=index%>][relationforeignkey]" class="form-control relationforeignkey"></select>
</div>
<div class="col-xs-2">
<label>关联主键</label>
<select name="relation[<%=index%>][relationprimarykey]" class="form-control relationprimarykey"></select>
</div>
<div class="col-xs-2">
<label>请选择显示字段</label>
<select name="relation[<%=index%>][relationfields][]" multiple class="form-control relationfields"></select>
</div>
<div class="col-xs-2">
<label>&nbsp;</label>
<a href="javascript:;" class="btn btn-danger btn-block btn-removerelation">移除</a>
</div>
</div>
</script>

View File

@@ -0,0 +1,42 @@
<table class="table table-striped">
<thead>
<tr>
<th>{:__('Title')}</th>
<th>{:__('Content')}</th>
</tr>
</thead>
<tbody>
<tr>
<td>{:__('Type')}</td>
<td>{$row.type}({$row.type_text})</td>
</tr>
<tr>
<td>{:__('Params')}</td>
<td>{$row.params|htmlentities}</td>
</tr>
<tr>
<td>{:__('Command')}</td>
<td>{$row.command|htmlentities}</td>
</tr>
<tr>
<td>{:__('Content')}</td>
<td>
<textarea class="form-control" name="" id="" cols="60" rows="10">{$row.content|htmlentities}</textarea>
</td>
</tr>
<tr>
<td>{:__('Executetime')}</td>
<td>{$row.executetime|datetime}</td>
</tr>
<tr>
<td>{:__('Status')}</td>
<td>{$row.status_text}</td>
</tr>
</tbody>
</table>
<div class="hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="reset" class="btn btn-primary btn-embossed btn-close" onclick="Layer.closeAll();">{:__('Close')}</button>
</div>
</div>

View File

@@ -0,0 +1,25 @@
<div class="panel panel-default panel-intro">
{:build_heading()}
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
<a href="javascript:;" class="btn btn-primary btn-refresh" title="{:__('Refresh')}" ><i class="fa fa-refresh"></i> </a>
<a href="javascript:;" class="btn btn-success btn-add {:$auth->check('command/add')?'':'hide'}" title="{:__('Add')}" ><i class="fa fa-plus"></i> {:__('Add')}</a>
<a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('command/del')?'':'hide'}" title="{:__('Delete')}" ><i class="fa fa-trash"></i> {:__('Delete')}</a>
</div>
<table id="table" class="table table-striped table-bordered table-hover"
data-operate-detail="{:$auth->check('command/detail')}"
data-operate-execute="{:$auth->check('command/execute')}"
data-operate-del="{:$auth->check('command/del')}"
width="100%">
</table>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,77 @@
<style>
.skin-list li{
float:left; width: 33.33333%; padding: 5px;
}
.skin-list li a{
display: block; box-shadow: 0 0 3px rgba(0,0,0,0.4);
}
.skin-list li a span{
display: block;
float:left;
}
.skin-list li.active a {
opacity: 1;
filter: alpha(opacity=100);
}
.skin-list li.active p {
color: #fff;
}
</style>
<!-- Control Sidebar -->
<aside class="control-sidebar control-sidebar-dark">
<!-- Create the tabs -->
<ul class="nav nav-tabs nav-justified control-sidebar-tabs">
<li class="active"><a href="#control-sidebar-setting-tab" data-toggle="tab" aria-expanded="true"><i class="fa fa-wrench"></i></a></li>
<li><a href="#control-sidebar-home-tab" data-toggle="tab"><i class="fa fa-home"></i></a></li>
<li><a href="#control-sidebar-settings-tab" data-toggle="tab"><i class="fa fa-gears"></i></a></li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<!-- Home tab content -->
<div class="tab-pane active" id="control-sidebar-setting-tab">
<h4 class="control-sidebar-heading">{:__('Layout Options')}</h4>
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-config="multiplenav" {if $Think.config.fastadmin.multiplenav}checked{/if} class="pull-right"> {:__('Multiple Nav')}</label><p>{:__("Toggle the top menu state (multiple or single)")}</p></div>
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-config="multipletab" {if $Think.config.fastadmin.multipletab}checked{/if} class="pull-right"> {:__('Multiple Tab')}</label><p>{:__("Always show multiple tab when multiple nav is set")}</p></div>
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-layout="sidebar-collapse" class="pull-right"> {:__('Toggle Sidebar')}</label><p>{:__("Toggle the left sidebar's state (open or collapse)")}</p></div>
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-enable="expandOnHover" class="pull-right"> {:__('Sidebar Expand on Hover')}</label><p>{:__('Let the sidebar mini expand on hover')}</p></div>
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-menu="show-submenu" class="pull-right"> {:__('Show sub menu')}</label><p>{:__('Always show sub menu')}</p></div>
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-controlsidebar="control-sidebar-open" class="pull-right"> {:__('Toggle Right Sidebar Slide')}</label><p>{:__('Toggle between slide over content and push content effects')}</p></div>
<div class="form-group"><label class="control-sidebar-subheading"><input type="checkbox" data-sidebarskin="toggle" class="pull-right"> {:__('Toggle Right Sidebar Skin')}</label><p>{:__('Toggle between dark and light skins for the right sidebar')}</p></div>
<h4 class="control-sidebar-heading">{:__('Skins')}</h4>
<ul class="list-unstyled clearfix skin-list">
<li><a href="javascript:;" data-skin="skin-blue" class="clearfix full-opacity-hover"><div><span style="width: 20%; height: 27px; background: #4e73df;"></span><span style="width: 80%; height: 27px; background: #f4f5f7;"></span></div></a><p class="text-center no-margin">Blue</p></li>
<li><a href="javascript:;" data-skin="skin-black" class="clearfix full-opacity-hover"><div><span style="width: 20%; height: 27px; background: #000;"></span><span style="width: 80%; height: 27px; background: #f4f5f7;"></span></div></a><p class="text-center no-margin">Black</p></li>
<li><a href="javascript:;" data-skin="skin-purple" class="clearfix full-opacity-hover"><div><span style="width: 20%; height: 27px; background: #605ca8;"></span><span style="width: 80%; height: 27px; background: #f4f5f7;"></span></div></a><p class="text-center no-margin">Purple</p></li>
<li><a href="javascript:;" data-skin="skin-green" class="clearfix full-opacity-hover"><div><span style="width: 20%; height: 7px;" class="bg-green-active"></span><span class="bg-green" style="width: 80%; height: 7px;"></span></div><div><span style="width: 20%; height: 20px; background: #000;"></span><span style="width: 80%; height: 20px; background: #f4f5f7;"></span></div></a><p class="text-center no-margin">Green</p></li>
<li><a href="javascript:;" data-skin="skin-red" class="clearfix full-opacity-hover"><div><span style="width: 20%; height: 7px;" class="bg-red-active"></span><span class="bg-red" style="width: 80%; height: 7px;"></span></div><div><span style="width: 20%; height: 20px; background: #000;"></span><span style="width: 80%; height: 20px; background: #f4f5f7;"></span></div></a><p class="text-center no-margin">Red</p></li>
<li><a href="javascript:;" data-skin="skin-yellow" class="clearfix full-opacity-hover"><div><span style="width: 20%; height: 7px;" class="bg-yellow-active"></span><span class="bg-yellow" style="width: 80%; height: 7px;"></span></div><div><span style="width: 20%; height: 20px; background: #000;"></span><span style="width: 80%; height: 20px; background: #f4f5f7;"></span></div></a><p class="text-center no-margin">Yellow</p></li>
<li><a href="javascript:;" data-skin="skin-blue-light" class="clearfix full-opacity-hover"><div><span style="width: 100%; height: 7px; background: #4e73df;"></span></div><div><span style="width: 100%; height: 20px; background: #f9fafc;"></span></div></a><p class="text-center no-margin" style="font-size: 12px">Blue Light</p></li>
<li><a href="javascript:;" data-skin="skin-black-light" class="clearfix full-opacity-hover"><div><span style="width: 100%; height: 7px; background: #000;"></span></div><div><span style="width: 100%; height: 20px; background: #f9fafc;"></span></div></a><p class="text-center no-margin" style="font-size: 12px">Black Light</p></li>
<li><a href="javascript:;" data-skin="skin-purple-light" class="clearfix full-opacity-hover"><div><span style="width: 100%; height: 7px; background: #605ca8;"></span></div><div><span style="width: 100%; height: 20px; background: #f9fafc;"></span></div></a><p class="text-center no-margin" style="font-size: 12px">Purple Light</p></li>
<li><a href="javascript:;" data-skin="skin-green-light" class="clearfix full-opacity-hover"><div><span style="width: 100%; height: 7px;" class="bg-green"></span></div><div><span style="width: 100%; height: 20px; background: #f9fafc;"></span></div></a><p class="text-center no-margin" style="font-size: 12px">Green Light</p></li>
<li><a href="javascript:;" data-skin="skin-red-light" class="clearfix full-opacity-hover"><div><span style="width: 100%; height: 7px;" class="bg-red"></span></div><div><span style="width: 100%; height: 20px; background: #f9fafc;"></span></div></a><p class="text-center no-margin" style="font-size: 12px">Red Light</p></li>
<li><a href="javascript:;" data-skin="skin-yellow-light" class="clearfix full-opacity-hover"><div><span style="width: 100%; height: 7px;" class="bg-yellow"></span></div><div><span style="width: 100%; height: 20px; background: #f9fafc;"></span></div></a><p class="text-center no-margin" style="font-size: 12px">Yellow Light</p></li>
<li><a href="javascript:;" data-skin="skin-black-blue" class="clearfix full-opacity-hover"><div><span style="width: 20%; height: 27px; background: #000;"><span style="width: 100%; height: 3px; margin-top:10px; background: #4e73df;"></span></span><span style="width: 80%; height: 27px; background: #f4f5f7;"></span></div></a><p class="text-center no-margin">Black Blue</p></li>
<li><a href="javascript:;" data-skin="skin-black-purple" class="clearfix full-opacity-hover"><div><span style="width: 20%; height: 27px; background: #000;"><span style="width: 100%; height: 3px; margin-top:10px; background: #605ca8;"></span></span><span style="width: 80%; height: 27px; background: #f4f5f7;"></span></div></a><p class="text-center no-margin">Black Purple</p></li>
<li><a href="javascript:;" data-skin="skin-black-green" class="clearfix full-opacity-hover"><div><span style="width: 20%; height: 27px; background: #000;"><span style="width: 100%; height: 3px; margin-top:10px;" class="bg-green"></span></span><span style="width: 80%; height: 27px; background: #f4f5f7;"></span></div></a><p class="text-center no-margin">Black Green</p></li>
<li><a href="javascript:;" data-skin="skin-black-red" class="clearfix full-opacity-hover"><div><span style="width: 20%; height: 27px; background: #000;"><span style="width: 100%; height: 3px; margin-top:10px;" class="bg-red"></span></span><span style="width: 80%; height: 27px; background: #f4f5f7;"></span></div></a><p class="text-center no-margin">Black Red</p></li>
<li><a href="javascript:;" data-skin="skin-black-yellow" class="clearfix full-opacity-hover"><div><span style="width: 20%; height: 27px; background: #000;"><span style="width: 100%; height: 3px; margin-top:10px;" class="bg-yellow"></span></span><span style="width: 80%; height: 27px; background: #f4f5f7;"></span></div></a><p class="text-center no-margin">Black Yellow</p></li>
<li><a href="javascript:;" data-skin="skin-black-pink" class="clearfix full-opacity-hover"><div><span style="width: 20%; height: 27px; background: #000;"><span style="width: 100%; height: 3px; margin-top:10px; background: #f5549f;"></span></span><span style="width: 80%; height: 27px; background: #f4f5f7;"></span></div></a><p class="text-center no-margin">Black Pink</p></li>
</ul>
</div>
<!-- /.tab-pane -->
<!-- Home tab content -->
<div class="tab-pane" id="control-sidebar-home-tab">
<h4 class="control-sidebar-heading">{:__('Home')}</h4>
</div>
<!-- /.tab-pane -->
<!-- Settings tab content -->
<div class="tab-pane" id="control-sidebar-settings-tab">
<h4 class="control-sidebar-heading">{:__('Setting')}</h4>
</div>
<!-- /.tab-pane -->
</div>
</aside>
<!-- /.control-sidebar -->

View File

@@ -0,0 +1,128 @@
<!-- Logo -->
<a href="javascript:;" class="logo">
<!-- 迷你模式下Logo的大小为50X50 -->
<span class="logo-mini">{$site.name|mb_substr=0,4,'utf-8'|mb_strtoupper='utf-8'|htmlentities}</span>
<!-- 普通模式下Logo -->
<span class="logo-lg">{$site.name|htmlentities}</span>
</a>
<!-- 顶部通栏样式 -->
<nav class="navbar navbar-static-top">
<!--第一级菜单-->
<div id="firstnav">
<!-- 边栏切换按钮-->
<a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
<span class="sr-only">{:__('Toggle navigation')}</span>
</a>
<!--如果不想在顶部显示角标,则给ul加上disable-top-badge类即可-->
<ul class="nav nav-tabs nav-addtabs disable-top-badge hidden-xs" role="tablist">
{$navlist}
</ul>
<div class="navbar-custom-menu">
<ul class="nav navbar-nav">
<li class="hidden-xs">
<a href="__PUBLIC__" target="_blank"><i class="fa fa-home" style="font-size:14px;"></i> {:__('Home')}</a>
</li>
<!-- 清除缓存 -->
<li class="hidden-xs">
<a href="javascript:;" data-toggle="dropdown" title="{:__('Wipe cache')}">
<i class="fa fa-trash"></i> {:__('Wipe cache')}
</a>
<ul class="dropdown-menu wipecache">
<li><a href="javascript:;" data-type="all"><i class="fa fa-trash fa-fw"></i> {:__('Wipe all cache')}</a></li>
<li class="divider"></li>
<li><a href="javascript:;" data-type="content"><i class="fa fa-file-text fa-fw"></i> {:__('Wipe content cache')}</a></li>
<li><a href="javascript:;" data-type="template"><i class="fa fa-file-image-o fa-fw"></i> {:__('Wipe template cache')}</a></li>
<li><a href="javascript:;" data-type="addons"><i class="fa fa-rocket fa-fw"></i> {:__('Wipe addons cache')}</a></li>
<li><a href="javascript:;" data-type="browser"><i class="fa fa-chrome fa-fw"></i> {:__('Wipe browser cache')}
<span data-toggle="tooltip" data-title="{:__('Wipe browser cache tips')}"><i class="fa fa-info-circle"></i></span>
</a></li>
</ul>
</li>
<!-- 多语言列表 -->
{if $Think.config.lang_switch_on}
<li class="hidden-xs">
<a href="javascript:;" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-language"></i></a>
<ul class="dropdown-menu">
<li class="{$config['language']=='zh-cn'?'active':''}">
<a href="?ref=addtabs&lang=zh-cn">简体中文</a>
</li>
<li class="{$config['language']=='en'?'active':''}">
<a href="?ref=addtabs&lang=en">English</a>
</li>
</ul>
</li>
{/if}
<!-- 全屏按钮 -->
<li class="hidden-xs">
<a href="#" data-toggle="fullscreen"><i class="fa fa-arrows-alt"></i></a>
</li>
<!-- 账号信息下拉框 -->
<li class="dropdown user user-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<img src="{$admin.avatar|cdnurl|htmlentities}" class="user-image" alt="">
<span class="hidden-xs">{$admin.nickname|htmlentities}</span>
</a>
<ul class="dropdown-menu">
<!-- User image -->
<li class="user-header">
<img src="{$admin.avatar|cdnurl|htmlentities}" class="img-circle" alt="">
<p>
{$admin.nickname|htmlentities}
<small>{$admin.logintime|date="Y-m-d H:i:s",###}</small>
</p>
</li>
<li class="user-body">
<div class="visible-xs">
<div class="pull-left">
<a href="__PUBLIC__" target="_blank"><i class="fa fa-home" style="font-size:14px;"></i> {:__('Home')}</a>
</div>
<div class="pull-right">
<a href="javascript:;" data-type="all" class="wipecache"><i class="fa fa-trash fa-fw"></i> {:__('Wipe all cache')}</a>
</div>
</div>
</li>
<!-- Menu Footer-->
<li class="user-footer">
<div class="pull-left">
<a href="general/profile" class="btn btn-primary addtabsit"><i class="fa fa-user"></i>
{:__('Profile')}</a>
</div>
<div class="pull-right">
<a href="{:url('index/logout')}" class="btn btn-danger"><i class="fa fa-sign-out"></i>
{:__('Logout')}</a>
</div>
</li>
</ul>
</li>
<!-- 控制栏切换按钮 -->
<li class="hidden-xs">
<a href="javascript:;" data-toggle="control-sidebar"><i class="fa fa-gears"></i></a>
</li>
</ul>
</div>
</div>
{if $Think.config.fastadmin.multiplenav}
<!--第二级菜单,只有在multiplenav开启时才显示-->
<div id="secondnav">
<ul class="nav nav-tabs nav-addtabs disable-top-badge" role="tablist">
{if $fixedmenu}
<li role="presentation" id="tab_{$fixedmenu.id|htmlentities}" class="{:$referermenu?'':'active'}"><a href="#con_{$fixedmenu.id|htmlentities}" node-id="{$fixedmenu.id|htmlentities}" aria-controls="{$fixedmenu.id|htmlentities}" role="tab" data-toggle="tab"><i class="fa fa-dashboard fa-fw"></i> <span>{$fixedmenu.title|htmlentities}</span> <span class="pull-right-container"> </span></a></li>
{/if}
{if $referermenu}
<li role="presentation" id="tab_{$referermenu.id|htmlentities}" class="active"><a href="#con_{$referermenu.id|htmlentities}" node-id="{$referermenu.id|htmlentities}" aria-controls="{$referermenu.id|htmlentities}" role="tab" data-toggle="tab"><i class="fa fa-list fa-fw"></i> <span>{$referermenu.title|htmlentities}</span> <span class="pull-right-container"> </span></a> <i class="close-tab fa fa-remove"></i></li>
{/if}
</ul>
</div>
{/if}
</nav>

View File

@@ -0,0 +1,39 @@
<!-- 左侧菜单栏 -->
<section class="sidebar">
<!-- 管理员信息 -->
<div class="user-panel hidden-xs">
<div class="pull-left image">
<a href="general/profile" class="addtabsit"><img src="{$admin.avatar|cdnurl|htmlentities}" class="img-circle" /></a>
</div>
<div class="pull-left info">
<p>{$admin.nickname|htmlentities}</p>
<i class="fa fa-circle text-success"></i> {:__('Online')}
</div>
</div>
<!-- 菜单搜索 -->
<form action="" method="get" class="sidebar-form" onsubmit="return false;">
<div class="input-group">
<input type="text" name="q" class="form-control" placeholder="{:__('Search menu')}">
<span class="input-group-btn">
<button type="submit" name="search" id="search-btn" class="btn btn-flat"><i class="fa fa-search"></i>
</button>
</span>
<div class="menuresult list-group sidebar-form hide">
</div>
</div>
</form>
<!-- 移动端一级菜单 -->
<div class="mobilenav visible-xs">
</div>
<!-- 左侧菜单栏 -->
<ul class="sidebar-menu {if $Think.config.fastadmin.show_submenu}show-submenu{/if}">
<!-- 菜单可以在 后台管理->权限管理->菜单规则 中进行增删改排序 -->
{$menulist}
</ul>
</section>

View File

@@ -0,0 +1,25 @@
<meta charset="utf-8">
<title>{$title|default=''}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta name="renderer" content="webkit">
<meta name="referrer" content="never">
<meta name="robots" content="noindex, nofollow">
<link rel="shortcut icon" href="__CDN__/assets/img/favicon.ico" />
<!-- Loading Bootstrap -->
<link href="__CDN__/assets/css/backend{$Think.config.app_debug?'':'.min'}.css?v={$Think.config.site.version|htmlentities}" rel="stylesheet">
{if $Think.config.fastadmin.adminskin}
<link href="__CDN__/assets/css/skins/{$Think.config.fastadmin.adminskin|htmlentities}.css?v={$Think.config.site.version|htmlentities}" rel="stylesheet">
{/if}
<!-- HTML5 shim, for IE6-8 support of HTML5 elements. All other JS at the end of file. -->
<!--[if lt IE 9]>
<script src="__CDN__/assets/js/html5shiv.js"></script>
<script src="__CDN__/assets/js/respond.min.js"></script>
<![endif]-->
<script type="text/javascript">
var require = {
config: {$config|json_encode}
};
</script>

View File

@@ -0,0 +1 @@
<script src="__CDN__/assets/js/require.min.js" data-main="__CDN__/assets/js/require-backend{$Think.config.app_debug?'':'.min'}.js?v={$site.version|htmlentities}"></script>

View File

@@ -0,0 +1,403 @@
<style type="text/css">
.sm-st {
background: #fff;
padding: 20px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
margin-bottom: 20px;
}
.sm-st-icon {
width: 60px;
height: 60px;
display: inline-block;
line-height: 60px;
text-align: center;
font-size: 30px;
background: #eee;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
float: left;
margin-right: 10px;
color: #fff;
}
.sm-st-info {
padding-top: 2px;
}
.sm-st-info span {
display: block;
font-size: 24px;
font-weight: 600;
}
.orange {
background: #fa8564 !important;
}
.tar {
background: #45cf95 !important;
}
.sm-st .green {
background: #86ba41 !important;
}
.pink {
background: #AC75F0 !important;
}
.yellow-b {
background: #fdd752 !important;
}
.stat-elem {
background-color: #fff;
padding: 18px;
border-radius: 40px;
}
.stat-info {
text-align: center;
background-color: #fff;
border-radius: 5px;
margin-top: -5px;
padding: 8px;
-webkit-box-shadow: 0 1px 0px rgba(0, 0, 0, 0.05);
box-shadow: 0 1px 0px rgba(0, 0, 0, 0.05);
font-style: italic;
}
.stat-icon {
text-align: center;
margin-bottom: 5px;
}
.st-red {
background-color: #F05050;
}
.st-green {
background-color: #27C24C;
}
.st-violet {
background-color: #7266ba;
}
.st-blue {
background-color: #23b7e5;
}
.stats .stat-icon {
color: #28bb9c;
display: inline-block;
font-size: 26px;
text-align: center;
vertical-align: middle;
width: 50px;
float: left;
}
.stat {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
}
.stat .value {
font-size: 20px;
line-height: 24px;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 500;
}
.stat .name {
overflow: hidden;
text-overflow: ellipsis;
margin: 5px 0;
}
.stat.lg .value {
font-size: 26px;
line-height: 28px;
}
.stat-col {
margin:0 0 10px 0;
}
.stat.lg .name {
font-size: 16px;
}
.stat-col .progress {
height: 2px;
}
.stat-col .progress-bar {
line-height: 2px;
height: 2px;
}
.item {
padding: 30px 0;
}
#statistics .panel {
min-height: 150px;
}
#statistics .panel h5 {
font-size: 14px;
}
</style>
<div class="panel panel-default panel-intro">
<div class="panel-heading">
{:build_heading(null, false)}
<ul class="nav nav-tabs">
<li class="active"><a href="#one" data-toggle="tab">{:__('Dashboard')}</a></li>
<li><a href="#two" data-toggle="tab">{:__('Custom')}</a></li>
</ul>
</div>
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="row">
<div class="col-sm-3 col-xs-6">
<div class="sm-st clearfix">
<span class="sm-st-icon st-red"><i class="fa fa-users"></i></span>
<div class="sm-st-info">
<span>{$totaluser|htmlentities}</span>
{:__('Total user')}
</div>
</div>
</div>
<div class="col-sm-3 col-xs-6">
<div class="sm-st clearfix">
<span class="sm-st-icon st-violet"><i class="fa fa-magic"></i></span>
<div class="sm-st-info">
<span>{$totaladdon|htmlentities}</span>
{:__('Total addon')}
</div>
</div>
</div>
<div class="col-sm-3 col-xs-6">
<div class="sm-st clearfix">
<span class="sm-st-icon st-blue"><i class="fa fa-leaf"></i></span>
<div class="sm-st-info">
<span>{$attachmentnums|htmlentities}</span>
{:__('Total attachment')}
</div>
</div>
</div>
<div class="col-sm-3 col-xs-6">
<div class="sm-st clearfix">
<span class="sm-st-icon st-green"><i class="fa fa-user"></i></span>
<div class="sm-st-info">
<span>{$totaladmin|htmlentities}</span>
{:__('Total admin')}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-8">
<div id="echart" class="btn-refresh" style="height:300px;width:100%;"></div>
</div>
<div class="col-lg-4">
<div class="card sameheight-item stats">
<div class="card-block">
<div class="row row-sm stats-container">
<div class="col-xs-6 stat-col">
<div class="stat-icon"><i class="fa fa-rocket"></i></div>
<div class="stat">
<div class="value"> {$todayusersignup|htmlentities}</div>
<div class="name"> {:__('Today user signup')}</div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-success" style="width: 20%"></div>
</div>
</div>
<div class="col-xs-6 stat-col">
<div class="stat-icon"><i class="fa fa-vcard"></i></div>
<div class="stat">
<div class="value"> {$todayuserlogin|htmlentities}</div>
<div class="name"> {:__('Today user login')}</div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-success" style="width: 20%"></div>
</div>
</div>
<div class="col-xs-6 stat-col">
<div class="stat-icon"><i class="fa fa-calendar"></i></div>
<div class="stat">
<div class="value"> {$threednu|htmlentities}</div>
<div class="name"> {:__('Three dnu')}</div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-success" style="width: 20%"></div>
</div>
</div>
<div class="col-xs-6 stat-col">
<div class="stat-icon"><i class="fa fa-calendar-plus-o"></i></div>
<div class="stat">
<div class="value"> {$sevendnu|htmlentities}</div>
<div class="name"> {:__('Seven dnu')}</div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-success" style="width: 20%"></div>
</div>
</div>
<div class="col-xs-6 stat-col">
<div class="stat-icon"><i class="fa fa-user-circle"></i></div>
<div class="stat">
<div class="value"> {$sevendau|htmlentities}</div>
<div class="name"> {:__('Seven dau')}</div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-success" style="width: 20%"></div>
</div>
</div>
<div class="col-xs-6 stat-col">
<div class="stat-icon"><i class="fa fa-user-circle-o"></i></div>
<div class="stat">
<div class="value"> {$thirtydau|htmlentities}</div>
<div class="name"> {:__('Thirty dau')}</div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-success" style="width: 20%"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row" style="margin-top:15px;" id="statistics">
<div class="col-lg-12">
</div>
<div class="col-xs-6 col-md-3">
<div class="panel bg-blue-gradient no-border">
<div class="panel-body">
<div class="panel-title">
<span class="label label-primary pull-right">{:__('Real time')}</span>
<h5>{:__('Working addon count')}</h5>
</div>
<div class="panel-content">
<div class="row">
<div class="col-md-12">
<h1 class="no-margins">{$totalworkingaddon|htmlentities}</h1>
<div class="font-bold"><i class="fa fa-magic"></i>
<small>{:__('Working addon count tips')}</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-xs-6 col-md-3">
<div class="panel bg-teal-gradient no-border">
<div class="panel-body">
<div class="ibox-title">
<span class="label label-primary pull-right">{:__('Real time')}</span>
<h5>{:__('Database count')}</h5>
</div>
<div class="ibox-content">
<div class="row">
<div class="col-md-6">
<h1 class="no-margins">{$dbtablenums|htmlentities}</h1>
<div class="font-bold"><i class="fa fa-database"></i>
<small>{:__('Database table nums')}</small>
</div>
</div>
<div class="col-md-6">
<h1 class="no-margins">{$dbsize|format_bytes=###,'',0}</h1>
<div class="font-bold"><i class="fa fa-filter"></i>
<small>{:__('Database size')}</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-xs-6 col-md-3">
<div class="panel bg-purple-gradient no-border">
<div class="panel-body">
<div class="ibox-title">
<span class="label label-primary pull-right">{:__('Real time')}</span>
<h5>{:__('Attachment count')}</h5>
</div>
<div class="ibox-content">
<div class="row">
<div class="col-md-6">
<h1 class="no-margins">{$attachmentnums|htmlentities}</h1>
<div class="font-bold"><i class="fa fa-files-o"></i>
<small>{:__('Attachment nums')}</small>
</div>
</div>
<div class="col-md-6">
<h1 class="no-margins">{$attachmentsize|format_bytes=###,'',0}</h1>
<div class="font-bold"><i class="fa fa-filter"></i>
<small>{:__('Attachment size')}</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-xs-6 col-md-3">
<div class="panel bg-green-gradient no-border">
<div class="panel-body">
<div class="ibox-title">
<span class="label label-primary pull-right">{:__('Real time')}</span>
<h5>{:__('Picture count')}</h5>
</div>
<div class="ibox-content">
<div class="row">
<div class="col-md-6">
<h1 class="no-margins">{$picturenums|htmlentities}</h1>
<div class="font-bold"><i class="fa fa-picture-o"></i>
<small>{:__('Picture nums')}</small>
</div>
</div>
<div class="col-md-6">
<h1 class="no-margins">{$picturesize|format_bytes=###,'',0}</h1>
<div class="font-bold"><i class="fa fa-filter"></i>
<small>{:__('Picture size')}</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="two">
<div class="row">
<div class="col-xs-12">
{:__('Custom zone')}
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,62 @@
<form id="add-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
{if $config.upload.cdnurl}
<div class="form-group">
<label for="c-third" class="control-label col-xs-12 col-sm-2">{:__('Upload to third')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" name="row[third]" id="c-third" class="form-control"/>
<ul class="row list-inline faupload-preview" id="p-third"></ul>
</div>
</div>
<div class="form-group">
<label for="c-third" class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<div style="width:180px;display:inline-block;">
<select name="category-third" id="category-third" class="form-control selectpicker">
<option value="">{:__('Please select category')}</option>
{foreach name="categoryList" id="item"}
<option value="{$key|htmlentities}">{$item|htmlentities}</option>
{/foreach}
</select>
</div>
<button type="button" id="faupload-third" class="btn btn-danger faupload" data-multiple="true" data-input-id="c-third" data-preview-id="p-third"><i class="fa fa-upload"></i> {:__("Upload to third")}</button>
{if $config.upload.chunking}
<button type="button" id="faupload-third-chunking" class="btn btn-danger faupload" data-chunking="true" data-maxsize="1gb" data-multiple="true" data-input-id="c-third" data-preview-id="p-third"><i class="fa fa-upload"></i> {:__("Upload to third by chunk")}</button>
{/if}
</div>
</div>
{/if}
<div class="form-group">
<label for="c-local" class="control-label col-xs-12 col-sm-2">{:__('Upload to local')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" name="row[local]" id="c-local" class="form-control"/>
<ul class="row list-inline faupload-preview" id="p-local"></ul>
</div>
</div>
<div class="form-group">
<label for="c-local" class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<div style="width:180px;display:inline-block;">
<select name="category-local" id="category-local" class="form-control selectpicker">
<option value="">{:__('Please select category')}</option>
{foreach name="categoryList" id="item"}
<option value="{$key|htmlentities}">{$item|htmlentities}</option>
{/foreach}
</select>
</div>
<button type="button" id="faupload-local" class="btn btn-primary faupload" data-input-id="c-local" data-multiple="true" data-preview-id="p-local" data-url="{:url('ajax/upload')}" data-cdnurl=""><i class="fa fa-upload"></i> {:__("Upload to local")}</button>
{if $config.upload.chunking}
<button type="button" id="faupload-local-chunking" class="btn btn-primary faupload" data-chunking="true" data-maxsize="1gb" data-input-id="c-local" data-multiple="true" data-preview-id="p-local" data-url="{:url('ajax/upload')}" data-cdnurl=""><i class="fa fa-upload"></i> {:__("Upload to local by chunk")}</button>
{/if}
</div>
</div>
<div class="form-group hidden layer-footer">
<div class="col-xs-2"></div>
<div class="col-xs-12 col-sm-8">
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>

View File

@@ -0,0 +1,89 @@
<form id="edit-form" class="form-horizontal form-ajax" role="form" data-toggle="validator" method="POST" action="">
<div class="form-group">
<label for="c-url" class="control-label col-xs-12 col-sm-2">{:__('Category')}:</label>
<div class="col-xs-12 col-sm-8">
<select name="row[category]" class="form-control">
<option value="">{:__('Please select category')}</option>
{foreach name="categoryList" id="item"}
<option value="{$key|htmlentities}" {if $key==$row.category}selected{/if}>{$item|htmlentities}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label for="c-url" class="control-label col-xs-12 col-sm-2">{:__('Url')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" name="row[url]" value="{$row.url|htmlentities}" id="c-url" class="form-control" required />
</div>
</div>
<div class="form-group">
<label for="c-imagewidth" class="control-label col-xs-12 col-sm-2">{:__('Imagewidth')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" name="row[imagewidth]" value="{$row.imagewidth|htmlentities}" id="c-imagewidth" class="form-control" required />
</div>
</div>
<div class="form-group">
<label for="c-imageheight" class="control-label col-xs-12 col-sm-2">{:__('Imageheight')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" name="row[imageheight]" value="{$row.imageheight|htmlentities}" id="c-imageheight" class="form-control" required />
</div>
</div>
<div class="form-group">
<label for="c-imagetype" class="control-label col-xs-12 col-sm-2">{:__('Imagetype')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" name="row[imagetype]" value="{$row.imagetype|htmlentities}" id="c-imagetype" class="form-control" required />
</div>
</div>
<div class="form-group">
<label for="c-imageframes" class="control-label col-xs-12 col-sm-2">{:__('Imageframes')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="number" name="row[imageframes]" value="{$row.imageframes|htmlentities}" id="c-imageframes" class="form-control" />
</div>
</div>
<div class="form-group">
<label for="c-filename" class="control-label col-xs-12 col-sm-2">{:__('Filename')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" name="row[filename]" value="{$row.filename|htmlentities}" id="c-filename" class="form-control" />
</div>
</div>
<div class="form-group">
<label for="c-filesize" class="control-label col-xs-12 col-sm-2">{:__('Filesize')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="number" name="row[filesize]" value="{$row.filesize|htmlentities}" id="c-filesize" class="form-control" />
</div>
</div>
<div class="form-group">
<label for="c-mimetype" class="control-label col-xs-12 col-sm-2">{:__('Mimetype')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" name="row[mimetype]" value="{$row.mimetype|htmlentities}" id="c-mimetype" class="form-control" />
</div>
</div>
<div class="form-group">
<label for="c-extparam" class="control-label col-xs-12 col-sm-2">{:__('Extparam')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" name="row[extparam]" value="{$row.extparam|htmlentities}" id="c-extparam" class="form-control" />
</div>
</div>
<div class="form-group">
<label for="c-uploadtime" class="control-label col-xs-12 col-sm-2">{:__('Uploadtime')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="datetime" name="row[uploadtime]" value="{$row.uploadtime|datetime}" id="c-uploadtime" class="form-control datetimepicker" />
</div>
</div>
<div class="form-group">
<label for="c-storage" class="control-label col-xs-12 col-sm-2">{:__('Storage')}:</label>
<div class="col-xs-12 col-sm-8">
<input type="text" name="row[storage]" value="{$row.storage|htmlentities}" id="c-storage" class="form-control" />
</div>
</div>
<div class="form-group hide layer-footer">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-8">
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</div>
</form>

View File

@@ -0,0 +1,53 @@
<div class="panel panel-default panel-intro">
<div class="panel-heading">
{:build_heading(null,FALSE)}
<ul class="nav nav-tabs" data-field="category">
<li class="active"><a href="#t-all" data-value="" data-toggle="tab">{:__('All')}</a></li>
{foreach name="categoryList" item="vo"}
<li><a href="#t-{$key|htmlentities}" data-value="{$key|htmlentities}" data-toggle="tab">{$vo|htmlentities}</a></li>
{/foreach}
<li class="pull-right dropdown filter-type">
<a href="javascript:" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-filter"></i> {:__('Filter Type')}</a>
<ul class="dropdown-menu text-left" role="menu">
<li class="active"><a href="javascript:" data-value="">{:__('All')}</a></li>
{foreach name="mimetypeList" id="item"}
<li><a href="javascript:" data-value="{$key|htmlentities}">{$item|htmlentities}</a></li>
{/foreach}
</ul>
</li>
</ul>
</div>
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
{:build_toolbar('refresh,add,edit,del')}
<a class="btn btn-info btn-classify dropdown-toggle btn-disabled disabled {:$auth->check('general/attachment/edit')?'':'hide'}"><i class="fa fa-arrow-right"></i> {:__('Classify')}</a>
</div>
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"
data-operate-edit="{:$auth->check('general/attachment/edit')}"
data-operate-del="{:$auth->check('general/attachment/del')}"
width="100%">
</table>
</div>
</div>
</div>
</div>
</div>
<script id="typetpl" type="text/html">
<div class="row">
<div class="col-xs-12">
<select name="category" class="form-control">
<option value="">{:__('Please select category')}</option>
{foreach name="categoryList" id="item"}
<option value="{$key|htmlentities}">{$item|htmlentities}</option>
{/foreach}
</select>
</div>
</div>
</script>

View File

@@ -0,0 +1,47 @@
<style>
#one .commonsearch-table{
padding-top:15px!important;
}
</style>
<div class="panel panel-default panel-intro">
<div class="panel-heading">
{:build_heading(null,FALSE)}
<ul class="nav nav-tabs" data-field="category">
<li class="active"><a href="#t-all" data-value="" data-toggle="tab">{:__('All')}</a></li>
{foreach name="categoryList" item="vo"}
<li><a href="#t-{$key|htmlentities}" data-value="{$key|htmlentities}" data-toggle="tab">{$vo|htmlentities}</a></li>
{/foreach}
{if stripos(request()->get('mimetype'),'image/')===false}
<li class="pull-right dropdown filter-type">
<a href="javascript:" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-filter"></i> {:__('Filter Type')}</a>
<ul class="dropdown-menu text-left" role="menu">
<li class="active"><a href="javascript:" data-value="">{:__('All')}</a></li>
{foreach name="mimetypeList" id="item"}
<li><a href="javascript:" data-value="{$key|htmlentities}">{$item|htmlentities}</a></li>
{/foreach}
</ul>
</li>
{/if}
</ul>
</div>
<div class="panel-body no-padding">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
{:build_toolbar('refresh')}
<span><button type="button" id="faupload-image" class="btn btn-success faupload" data-mimetype="{$mimetype|default=''|htmlentities}" data-multiple="true"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
{if request()->get('multiple') == 'true'}
<a class="btn btn-danger btn-choose-multi"><i class="fa fa-check"></i> {:__('Choose')}</a>
{/if}
</div>
<table id="table" class="table table-bordered table-hover table-nowrap" width="100%">
</table>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,347 @@
<style type="text/css">
@media (max-width: 375px) {
.edit-form tr td input {
width: 100%;
}
.edit-form tr th:first-child, .edit-form tr td:first-child {
width: 20%;
}
.edit-form tr th:nth-last-of-type(-n+2), .edit-form tr td:nth-last-of-type(-n+2) {
display: none;
}
}
.edit-form table > tbody > tr td a.btn-delcfg {
visibility: hidden;
}
.edit-form table > tbody > tr:hover td a.btn-delcfg {
visibility: visible;
}
</style>
<div class="panel panel-default panel-intro">
<div class="panel-heading">
{:build_heading(null, false)}
<ul class="nav nav-tabs">
{foreach $siteList as $index=>$vo}
<li class="{$vo.active?'active':''}"><a href="#tab-{$vo.name|htmlentities}" data-toggle="tab">{:__(htmlentities($vo.title))}</a></li>
{/foreach}
{if $Think.config.app_debug}
<li data-toggle="tooltip" title="{:__('Add new config')}">
<a href="#addcfg" data-toggle="tab"><i class="fa fa-plus"></i></a>
</li>
{/if}
</ul>
</div>
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<!--@formatter:off-->
{foreach $siteList as $index=>$vo}
<div class="tab-pane fade {$vo.active ? 'active in' : ''}" id="tab-{$vo.name|htmlentities}">
<div class="widget-body no-padding">
<form id="{$vo.name|htmlentities}-form" class="edit-form form-horizontal" role="form" data-toggle="validator" method="POST" action="{:url('general.config/edit')}">
{:token()}
<table class="table table-striped">
<thead>
<tr>
<th width="15%">{:__('Title')}</th>
<th width="68%">{:__('Value')}</th>
{if $Think.config.app_debug}
<th width="15%">{:__('Name')}</th>
<th width="2%"></th>
{/if}
</tr>
</thead>
<tbody>
{foreach $vo.list as $item}
<tr data-favisible="{$item.visible|default=''|htmlentities}" data-name="{$item.name|htmlentities}" class="{if $item.visible??''}hidden{/if}">
<td>{$item.title|htmlentities}</td>
<td>
<div class="row">
<div class="col-sm-8 col-xs-12">
{switch $item.type}
{case string}
<input {$item.extend_html|htmlentities} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule|htmlentities}" data-tip="{$item.tip|htmlentities}"/>
{/case}
{case password}
<input {$item.extend_html|htmlentities} type="password" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule|htmlentities}" data-tip="{$item.tip|htmlentities}"/>
{/case}
{case text}
<textarea {$item.extend_html|htmlentities} name="row[{$item.name|htmlentities}]" class="form-control" data-rule="{$item.rule|htmlentities}" rows="5" data-tip="{$item.tip|htmlentities}">{$item.value|htmlentities}</textarea>
{/case}
{case editor}
<textarea {$item.extend_html|htmlentities} name="row[{$item.name|htmlentities}]" id="editor-{$item.name|htmlentities}" class="form-control editor" data-rule="{$item.rule|htmlentities}" rows="5" data-tip="{$item.tip|htmlentities}">{$item.value|htmlentities}</textarea>
{/case}
{case array}
<dl {$item.extend_html|htmlentities} class="fieldlist" data-name="row[{$item.name|htmlentities}]">
<dd>
<ins>{:isset($item["setting"]["key"])&&$item["setting"]["key"]?$item["setting"]["key"]:__('Array key')}</ins>
<ins>{:isset($item["setting"]["value"])&&$item["setting"]["value"]?$item["setting"]["value"]:__('Array value')}</ins>
</dd>
<dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
<textarea name="row[{$item.name|htmlentities}]" class="form-control hide" cols="30" rows="5">{$item.value|htmlentities}</textarea>
</dl>
{/case}
{case date}
<input {$item.extend_html|htmlentities} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/>
{/case}
{case time}
<input {$item.extend_html|htmlentities} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="HH:mm:ss" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/>
{/case}
{case datetime}
<input {$item.extend_html|htmlentities} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control datetimepicker" data-date-format="YYYY-MM-DD HH:mm:ss" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/>
{/case}
{case datetimerange}
<input {$item.extend_html|htmlentities} type="text" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control datetimerange" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/>
{/case}
{case number}
<input {$item.extend_html|htmlentities} type="number" name="row[{$item.name|htmlentities}]" value="{$item.value|htmlentities}" class="form-control" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}"/>
{/case}
{case checkbox}
<div class="checkbox">
{foreach name="item.content" item="vo"}
<label for="row[{$item.name|htmlentities}][]-{$key|htmlentities}"><input id="row[{$item.name|htmlentities}][]-{$key|htmlentities}" name="row[{$item.name|htmlentities}][]" type="checkbox" value="{$key|htmlentities}" data-tip="{$item.tip|htmlentities}" {in name="key" value="$item.value" }checked{/in} /> {$vo|htmlentities}</label>
{/foreach}
</div>
{/case}
{case radio}
<div class="radio">
{foreach name="item.content" item="vo"}
<label for="row[{$item.name|htmlentities}]-{$key|htmlentities}"><input id="row[{$item.name|htmlentities}]-{$key|htmlentities}" name="row[{$item.name|htmlentities}]" type="radio" value="{$key|htmlentities}" data-tip="{$item.tip|htmlentities}" {in name="key" value="$item.value" }checked{/in} /> {$vo|htmlentities}</label>
{/foreach}
</div>
{/case}
{case value="select" break="0"}{/case}
{case value="selects"}
<select {$item.extend_html|htmlentities} name="row[{$item.name|htmlentities}]{$item.type=='selects'?'[]':''}" class="form-control selectpicker" data-tip="{$item.tip|htmlentities}" {$item.type=='selects'?'multiple':''}>
{foreach name="item.content" item="vo"}
<option value="{$key|htmlentities}" {in name="key" value="$item.value" }selected{/in}>{$vo|htmlentities}</option>
{/foreach}
</select>
{/case}
{case value="image" break="0"}{/case}
{case value="images"}
<div class="form-inline">
<input id="c-{$item.name|htmlentities}" class="form-control" size="50" name="row[{$item.name|htmlentities}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip|htmlentities}">
<span><button type="button" id="faupload-{$item.name|htmlentities}" class="btn btn-danger faupload" data-input-id="c-{$item.name|htmlentities}" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="{$item.type=='image'?'false':'true'}" data-preview-id="p-{$item.name|htmlentities}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-{$item.name|htmlentities}" class="btn btn-primary fachoose" data-input-id="c-{$item.name|htmlentities}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
<span class="msg-box n-right" for="c-{$item.name|htmlentities}"></span>
<ul class="row list-inline faupload-preview" id="p-{$item.name|htmlentities}"></ul>
</div>
{/case}
{case value="file" break="0"}{/case}
{case value="files"}
<div class="form-inline">
<input id="c-{$item.name|htmlentities}" class="form-control" size="50" name="row[{$item.name|htmlentities}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip|htmlentities}">
<span><button type="button" id="faupload-{$item.name|htmlentities}" class="btn btn-danger faupload" data-input-id="c-{$item.name|htmlentities}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
<span><button type="button" id="fachoose-{$item.name|htmlentities}" class="btn btn-primary fachoose" data-input-id="c-{$item.name|htmlentities}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
<span class="msg-box n-right" for="c-{$item.name|htmlentities}"></span>
</div>
{/case}
{case switch}
<input id="c-{$item.name|htmlentities}" name="row[{$item.name|htmlentities}]" type="hidden" value="{:$item.value?1:0}">
<a href="javascript:;" data-toggle="switcher" class="btn-switcher" data-input-id="c-{$item.name|htmlentities}" data-yes="1" data-no="0">
<i class="fa fa-toggle-on text-success {if !$item.value}fa-flip-horizontal text-gray{/if} fa-2x"></i>
</a>
{/case}
{case bool}
<label for="row[{$item.name|htmlentities}]-yes"><input id="row[{$item.name|htmlentities}]-yes" name="row[{$item.name|htmlentities}]" type="radio" value="1" {$item.value?'checked':''} data-tip="{$item.tip|htmlentities}" /> {:__('Yes')}</label>
<label for="row[{$item.name|htmlentities}]-no"><input id="row[{$item.name|htmlentities}]-no" name="row[{$item.name|htmlentities}]" type="radio" value="0" {$item.value?'':'checked'} data-tip="{$item.tip|htmlentities}" /> {:__('No')}</label>
{/case}
{case city}
<div style="position:relative">
<input {$item.extend_html|htmlentities} type="text" name="row[{$item.name|htmlentities}]" id="c-{$item.name|htmlentities}" value="{$item.value|htmlentities}" class="form-control" data-toggle="city-picker" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}" />
</div>
{/case}
{case value="selectpage" break="0"}{/case}
{case value="selectpages"}
<input {$item.extend_html|htmlentities} type="text" name="row[{$item.name|htmlentities}]" id="c-{$item.name|htmlentities}" value="{$item.value|htmlentities}" class="form-control selectpage" data-source="{:url('general.config/selectpage')}?id={$item.id|htmlentities}" data-primary-key="{$item.setting.primarykey|htmlentities}" data-field="{$item.setting.field|htmlentities}" data-multiple="{$item.type=='selectpage'?'false':'true'}" data-tip="{$item.tip|htmlentities}" data-rule="{$item.rule|htmlentities}" />
{/case}
{case custom}
{$item.extend_html|htmlentities}
{/case}
{/switch}
</div>
<div class="col-sm-4"></div>
</div>
</td>
{if $Think.config.app_debug}
<td>{php}echo "{\$site.". $item['name'] . "}";{/php}</td>
<td>{if $item['id']>18}<a href="javascript:;" class="btn-delcfg text-muted" data-name="{$item.name|htmlentities}"><i class="fa fa-times"></i></a>{/if}</td>
{/if}
</tr>
{/foreach}
</tbody>
<tfoot>
<tr>
<td></td>
<td>
<div class="layer-footer">
<button type="submit" class="btn btn-primary btn-embossed disabled">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
</div>
</td>
{if $Think.config.app_debug}
<td></td>
<td></td>
{/if}
</tr>
</tfoot>
</table>
</form>
</div>
</div>
{/foreach}
<div class="tab-pane fade" id="addcfg">
<form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="{:url('general.config/add')}">
{:token()}
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Group')}:</label>
<div class="col-xs-12 col-sm-4">
<select name="row[group]" class="form-control selectpicker">
{foreach name="groupList" item="vo"}
<option value="{$key|htmlentities}" {in name="key" value="basic" }selected{/in}>{$vo|htmlentities}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
<div class="col-xs-12 col-sm-4">
<select name="row[type]" id="c-type" class="form-control selectpicker">
{foreach name="typeList" item="vo"}
<option value="{$key|htmlentities}" {in name="key" value="string" }selected{/in}>{$vo|htmlentities}</option>
{/foreach}
</select>
</div>
</div>
<div class="form-group">
<label for="name" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
<div class="col-xs-12 col-sm-4">
<input type="text" class="form-control" id="name" name="row[name]" value="" data-rule="required; length(3~30); remote(general/config/check)"/>
</div>
</div>
<div class="form-group">
<label for="title" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
<div class="col-xs-12 col-sm-4">
<input type="text" class="form-control" id="title" name="row[title]" value="" data-rule="required"/>
</div>
</div>
<div class="form-group hidden tf tf-selectpage tf-selectpages">
<label for="c-selectpage-table" class="control-label col-xs-12 col-sm-2">{:__('Selectpage table')}:</label>
<div class="col-xs-12 col-sm-4">
<select id="c-selectpage-table" name="row[setting][table]" class="form-control selectpicker" data-live-search="true">
<option value="">{:__('Please select table')}</option>
</select>
</div>
</div>
<div class="form-group hidden tf tf-selectpage tf-selectpages">
<label for="c-selectpage-primarykey" class="control-label col-xs-12 col-sm-2">{:__('Selectpage primarykey')}:</label>
<div class="col-xs-12 col-sm-4">
<select name="row[setting][primarykey]" class="form-control selectpicker" id="c-selectpage-primarykey"></select>
</div>
</div>
<div class="form-group hidden tf tf-selectpage tf-selectpages">
<label for="c-selectpage-field" class="control-label col-xs-12 col-sm-2">{:__('Selectpage field')}:</label>
<div class="col-xs-12 col-sm-4">
<select name="row[setting][field]" class="form-control selectpicker" id="c-selectpage-field"></select>
</div>
</div>
<div class="form-group hidden tf tf-selectpage tf-selectpages">
<label class="control-label col-xs-12 col-sm-2">{:__('Selectpage conditions')}:</label>
<div class="col-xs-12 col-sm-8">
<dl class="fieldlist" data-name="row[setting][conditions]">
<dd>
<ins>{:__('Field title')}</ins>
<ins>{:__('Field value')}</ins>
</dd>
<dd><a href="javascript:;" class="append btn btn-sm btn-success"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
<textarea name="row[setting][conditions]" class="form-control hide" cols="30" rows="5"></textarea>
</dl>
</div>
</div>
<div class="form-group hidden tf tf-array">
<label for="c-array-key" class="control-label col-xs-12 col-sm-2">{:__('Array key')}:</label>
<div class="col-xs-12 col-sm-4">
<input type="text" name="row[setting][key]" class="form-control" id="c-array-key">
</div>
</div>
<div class="form-group hidden tf tf-array">
<label for="c-array-value" class="control-label col-xs-12 col-sm-2">{:__('Array value')}:</label>
<div class="col-xs-12 col-sm-4">
<input type="text" name="row[setting][value]" class="form-control" id="c-array-value">
</div>
</div>
<div class="form-group">
<label for="value" class="control-label col-xs-12 col-sm-2">{:__('Value')}:</label>
<div class="col-xs-12 col-sm-4">
<input type="text" class="form-control" id="value" name="row[value]" value="" data-rule=""/>
</div>
</div>
<div class="form-group hide" id="add-content-container">
<label for="content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
<div class="col-xs-12 col-sm-4">
<textarea name="row[content]" id="content" cols="30" rows="5" class="form-control" data-rule="required(content)">value1|title1
value2|title2</textarea>
</div>
</div>
<div class="form-group">
<label for="tip" class="control-label col-xs-12 col-sm-2">{:__('Tip')}:</label>
<div class="col-xs-12 col-sm-4">
<input type="text" class="form-control" id="tip" name="row[tip]" value="" data-rule=""/>
</div>
</div>
<div class="form-group">
<label for="rule" class="control-label col-xs-12 col-sm-2">{:__('Rule')}:</label>
<div class="col-xs-12 col-sm-4">
<div class="input-group pull-left">
<input type="text" class="form-control" id="rule" name="row[rule]" value="" data-tip="{:__('Rule tips')}"/>
<span class="input-group-btn">
<button class="btn btn-primary dropdown-toggle" data-toggle="dropdown" type="button">{:__('Choose')}</button>
<ul class="dropdown-menu pull-right rulelist">
{volist name="ruleList" id="item"}
<li><a href="javascript:;" data-value="{$key|htmlentities}">{$item|htmlentities}<span class="text-muted">({$key|htmlentities})</span></a></li>
{/volist}
</ul>
</span>
</div>
<span class="msg-box n-right" for="rule"></span>
</div>
</div>
<div class="form-group">
<label for="visible" class="control-label col-xs-12 col-sm-2">{:__('Visible condition')}:</label>
<div class="col-xs-12 col-sm-4">
<input type="text" class="form-control" id="visible" name="row[visible]" value="" data-rule=""/>
</div>
</div>
<div class="form-group">
<label for="extend" class="control-label col-xs-12 col-sm-2">{:__('Extend')}:</label>
<div class="col-xs-12 col-sm-4">
<textarea name="row[extend]" id="extend" cols="30" rows="5" class="form-control" data-tip="{:__('Extend tips')}" data-rule="required(extend)" data-msg-extend="当类型为自定义时,扩展属性不能为空"></textarea>
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-12 col-sm-2"></label>
<div class="col-xs-12 col-sm-4">
{if !$Think.config.app_debug}
<button type="button" class="btn btn-primary disabled">{:__('Only work at development environment')}</button>
{else/}
<button type="submit" class="btn btn-primary btn-embossed">{:__('OK')}</button>
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
{/if}
</div>
</div>
</form>
</div>
<!--@formatter:on-->
</div>
</div>
</div>

View File

@@ -0,0 +1,118 @@
<style>
.profile-avatar-container {
position: relative;
width: 100px;
margin: 0 auto;
}
.profile-avatar-container .profile-user-img {
width: 100px;
height: 100px;
}
.profile-avatar-container .profile-avatar-text {
display: none;
}
.profile-avatar-container:hover .profile-avatar-text {
display: block;
position: absolute;
height: 100px;
width: 100px;
background: #444;
opacity: .6;
color: #fff;
top: 0;
left: 0;
line-height: 100px;
text-align: center;
}
.profile-avatar-container button {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
opacity: 0;
}
</style>
<div class="row animated fadeInRight">
<div class="col-md-4">
<div class="box box-primary">
<div class="panel-heading">
{:__('Profile')}
</div>
<div class="panel-body">
<form id="update-form" role="form" data-toggle="validator" method="POST" action="{:url('general.profile/update')}">
{:token()}
<input type="hidden" id="c-avatar" name="row[avatar]" value="{$admin.avatar|htmlentities}"/>
<div class="box-body box-profile">
<div class="profile-avatar-container">
<img class="profile-user-img img-responsive img-circle" src="{$admin.avatar|cdnurl|htmlentities}" alt="">
<div class="profile-avatar-text img-circle">{:__('Click to edit')}</div>
<button type="button" id="faupload-avatar" class="faupload" data-input-id="c-avatar"><i class="fa fa-upload"></i> {:__('Upload')}</button>
</div>
<h3 class="profile-username text-center">{$admin.nickname|htmlentities}</h3>
<div class="form-group">
<label for="username" class="control-label">{:__('Username')}:</label>
<input type="text" class="form-control" id="username" name="row[username]" value="{$admin.username|htmlentities}" disabled/>
</div>
<div class="form-group">
<label for="mobile" class="control-label">{:__('Mobile')}:</label>
<input type="text" class="form-control" id="mobile" name="row[mobile]" value="{$admin.mobile|htmlentities}" disabled/>
</div>
<div class="form-group">
<label for="email" class="control-label">{:__('Email')}:</label>
<input type="text" class="form-control" id="email" name="row[email]" value="{$admin.email|htmlentities}" data-rule="required;email"/>
</div>
<div class="form-group">
<label for="nickname" class="control-label">{:__('Nickname')}:</label>
<input type="text" class="form-control" id="nickname" name="row[nickname]" value="{$admin.nickname|htmlentities}" data-rule="required"/>
</div>
<div class="form-group">
<label for="password" class="control-label">{:__('Password')}:</label>
<input type="password" class="form-control" id="password" placeholder="{:__('Leave password blank if dont want to change')}" autocomplete="new-password" name="row[password]" value="" data-rule="password"/>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">{:__('Submit')}</button>
<button type="reset" class="btn btn-default">{:__('Reset')}</button>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="col-md-8">
<div class="panel panel-default panel-intro panel-nav">
<div class="panel-heading">
<ul class="nav nav-tabs">
<li class="active"><a href="#one" data-toggle="tab"><i class="fa fa-list"></i> {:__('Admin log')}</a></li>
</ul>
</div>
<div class="panel-body">
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="one">
<div class="widget-body no-padding">
<div id="toolbar" class="toolbar">
{:build_toolbar('refresh')}
</div>
<table id="table" class="table table-striped table-bordered table-hover table-nowrap" width="100%">
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<head>
<!-- 加载样式及META信息 -->
{include file="common/meta" /}
</head>
<body class="hold-transition {$Think.config.fastadmin.adminskin|default='skin-black-blue'} sidebar-mini {:$Think.cookie.sidebar_collapse?'sidebar-collapse':''} fixed {:$Think.config.fastadmin.multipletab?'multipletab':''} {:$Think.config.fastadmin.multiplenav?'multiplenav':''}" id="tabs">
<div class="wrapper">
<!-- 头部区域 -->
<header id="header" class="main-header">
{include file='common/header' /}
</header>
<!-- 左侧菜单栏 -->
<aside class="main-sidebar">
{include file='common/menu' /}
</aside>
<!-- 主体内容区域 -->
<div class="content-wrapper tab-content tab-addtabs">
{if $fixedmenu}
<div role="tabpanel" class="tab-pane {:$referermenu?'':'active'}" id="con_{$fixedmenu.id|htmlentities}">
<iframe src="{$fixedmenu.url|htmlentities}{:stripos($fixedmenu.url, '?') !== false ? '&' : '?'}addtabs=1" width="100%" height="100%" frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling-x="no" scrolling-y="auto" allowtransparency="yes"></iframe>
</div>
{/if}
{if $referermenu}
<div role="tabpanel" class="tab-pane active" id="con_{$referermenu.id|htmlentities}">
<iframe src="{$referermenu.url|htmlentities}{:stripos($referermenu.url, '?') !== false ? '&' : '?'}addtabs=1" width="100%" height="100%" frameborder="no" border="0" marginwidth="0" marginheight="0" scrolling-x="no" scrolling-y="auto" allowtransparency="yes"></iframe>
</div>
{/if}
</div>
<!-- 底部链接,默认隐藏 -->
<footer class="main-footer hide">
<div class="pull-right hidden-xs">
</div>
<strong>Copyright &copy; 2017-{:date("Y")} <a href="__PUBLIC__">{$site.name|htmlentities}</a>.</strong> All rights reserved.
</footer>
<!-- 右侧控制栏 -->
<div class="control-sidebar-bg"></div>
{include file="common/control" /}
</div>
<!-- 加载JS脚本 -->
{include file="common/script" /}
</body>
</html>

View File

@@ -0,0 +1,146 @@
<!DOCTYPE html>
<html>
<head>
{include file="common/meta" /}
<style type="text/css">
body {
color: #999;
background-color: #f1f4fd;
background-size: cover;
}
a {
color: #444;
}
.login-screen {
max-width: 430px;
padding: 0;
margin: 100px auto 0 auto;
}
.login-screen .well {
border-radius: 3px;
-webkit-box-shadow: 0 0 30px rgba(0, 0, 0, 0.1);
box-shadow: 0 0 30px rgba(0, 0, 0, 0.1);
background: rgba(255, 255, 255, 1);
border: none;
/*overflow: hidden;*/
padding: 0;
}
@media (max-width: 767px) {
.login-screen {
padding: 0 20px;
}
}
.profile-img-card {
width: 100px;
height: 100px;
display: block;
-moz-border-radius: 50%;
-webkit-border-radius: 50%;
border-radius: 50%;
margin: -93px auto 30px;
border: 5px solid #fff;
}
.profile-name-card {
text-align: center;
}
.login-head {
background: #899fe1;
border-radius: 3px 3px 0 0;
}
.login-form {
padding: 40px 30px;
position: relative;
z-index: 99;
}
#login-form {
margin-top: 20px;
}
#login-form .input-group {
margin-bottom: 15px;
}
#login-form .form-control {
font-size: 13px;
}
</style>
<!--@formatter:off-->
{if $background}
<style type="text/css">
body{
background-image: url('{$background|htmlentities}');
}
</style>
{/if}
<!--@formatter:on-->
</head>
<body>
<div class="container">
<div class="login-wrapper">
<div class="login-screen">
<div class="well">
<div class="login-head">
<img src="__CDN__/assets/img/login-head.png" style="width:100%;"/>
</div>
<div class="login-form">
<img id="profile-img" class="profile-img-card" src="__CDN__/assets/img/avatar.png"/>
<p id="profile-name" class="profile-name-card"></p>
<form action="" method="post" id="login-form">
<!--@AdminLoginFormBegin-->
<div id="errtips" class="hide"></div>
{:token()}
<div class="input-group">
<div class="input-group-addon"><span class="glyphicon glyphicon-user" aria-hidden="true"></span></div>
<input type="text" class="form-control" id="pd-form-username" placeholder="{:__('Username')}" name="username" autocomplete="off" value="" data-rule="{:__('Username')}:required;username"/>
</div>
<div class="input-group">
<div class="input-group-addon"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span></div>
<input type="password" class="form-control" id="pd-form-password" placeholder="{:__('Password')}" name="password" autocomplete="off" value="" data-rule="{:__('Password')}:required;password"/>
</div>
<!--@CaptchaBegin-->
{if $Think.config.fastadmin.login_captcha}
<div class="input-group">
<div class="input-group-addon"><span class="glyphicon glyphicon-option-horizontal" aria-hidden="true"></span></div>
<input type="text" name="captcha" class="form-control" placeholder="{:__('Captcha')}" data-rule="{:__('Captcha')}:required;length({$Think.config.captcha.length|htmlentities})" autocomplete="off"/>
<span class="input-group-addon" style="padding:0;border:none;cursor:pointer;">
<img src="{:rtrim('__PUBLIC__', '/')}/index.php?s=/captcha" width="100" height="30" onclick="this.src = '{:rtrim('__PUBLIC__', '/')}/index.php?s=/captcha&r=' + Math.random();"/>
</span>
</div>
{/if}
<!--@CaptchaEnd-->
{if $keeyloginhours>0}
<div class="form-group checkbox">
<label class="inline" for="keeplogin" data-toggle="tooltip" title="{:__('The duration of the session is %s hours', $keeyloginhours)}">
<input type="checkbox" name="keeplogin" id="keeplogin" value="1"/>
{:__('Keep login')}
</label>
</div>
{/if}
<div class="form-group">
<button type="submit" class="btn btn-success btn-lg btn-block" style="background:#708eea;">{:__('Sign in')}</button>
</div>
<!--@AdminLoginFormEnd-->
</form>
</div>
</div>
</div>
</div>
</div>
{include file="common/script" /}
</body>
</html>

View File

@@ -0,0 +1,45 @@
<!DOCTYPE html>
<html>
<head>
{include file="common/meta" /}
</head>
<body class="inside-header inside-aside {:defined('IS_DIALOG') && IS_DIALOG ? 'is-dialog' : ''}">
<div id="main" role="main">
<div class="tab-content tab-addtabs">
<div id="content">
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<section class="content-header hide">
<h1>
{:__('Dashboard')}
<small>{:__('Control panel')}</small>
</h1>
</section>
{if !IS_DIALOG && !$Think.config.fastadmin.multiplenav && $Think.config.fastadmin.breadcrumb}
<!-- RIBBON -->
<div id="ribbon">
<ol class="breadcrumb pull-left">
{if condition="$auth->check('dashboard')"}
<li><a href="dashboard" class="addtabsit"><i class="fa fa-dashboard"></i> {:__('Dashboard')}</a></li>
{/if}
</ol>
<ol class="breadcrumb pull-right">
{foreach $breadcrumb as $vo}
<li><a href="javascript:;" data-url="{$vo.url|htmlentities}">{$vo.title|htmlentities}</a></li>
{/foreach}
</ol>
</div>
<!-- END RIBBON -->
{/if}
<div class="content">
{__CONTENT__}
</div>
</div>
</div>
</div>
</div>
</div>
{include file="common/script" /}
</body>
</html>

View File

@@ -0,0 +1,87 @@
{include file="/shopro/common/script" /}
<style>
.activity-index .sa-main {
--el-main-padding: 20px 40px;
}
.activity-index .title {
line-height: 20px;
font-size: 16px;
color: var(--sa-title);
margin-bottom: 12px;
}
.activity-index .activity-item {
width: 250px;
padding: 18px 20px;
background: var(--sa-table-header-bg);
border-radius: 4px;
margin: 0 16px 16px 0;
cursor: pointer;
}
.activity-index .activity-item:hover {
transition: width height 0.5s;
transform: scale(1.05);
}
.activity-index .left {
width: 44px;
height: 44px;
background: var(--el-color-primary);
border-radius: 4px;
overflow: hidden;
margin-right: 12px;
}
.activity-index .left img {
width: 100%;
height: 100%;
}
.activity-index .activity-title {
line-height: 18px;
font-size: 14px;
font-weight: 600;
color: var(--sa-subtitle);
margin: 2px 0 6px;
}
.activity-index .activity-subtitle {
line-height: 16px;
font-size: 12px;
color: var(--sa-subfont);
}
</style>
<div id="index" class="activity-index panel panel-default panel-intro" v-cloak>
<el-container class="panel-block">
<el-header class="sa-header">
<div class="sa-title sa-flex">
<div class="sa-title-left">
<div class="left-name">营销活动</div>
</div>
</div>
</el-header>
<el-main class="sa-main">
<template v-for="item in activityData">
<div class="title">
{{item.title}}
</div>
<div class="sa-flex sa-flex-wrap">
<div class="activity-item sa-flex" v-for="(value,key) in item.children"
@click="onActivity(key,value.title)">
<div class="left">
<img :src="`/assets/addons/shopro/img/activity/${key}.png`" />
</div>
<div>
<div class="activity-title">{{value.title}}</div>
<div class="activity-subtitle">{{value.subtitle}}</div>
</div>
</div>
</div>
</template>
</el-main>
</el-container>
</div>

View File

@@ -0,0 +1,674 @@
{include file="/shopro/common/script" /}
<style>
.activity-form .w-120 {
width: 120px;
}
.activity-form .el-form-item-inner {
--el-form-label-font-size: 12px;
}
.activity-form .el-form-item-inner .el-form-item__label {
width: fit-content !important;
}
.activity-form .tip,
.activity-form .delete {
margin-left: 12px;
}
.activity-form .rules-title {
width: 100%;
max-width: 360px;
height: 32px;
line-height: 32px;
padding: 0 16px;
border-radius: 4px;
background: var(--sa-table-header-bg);
font-size: 12px;
color: var(--sa-subtitle);
}
.activity-form .goods-image {
margin-right: 12px;
}
.activity-form .goods-title {
color: var(--sa-font);
margin-bottom: 6px;
}
.activity-form .goods-price {
color: var(--el-color-danger);
}
.activity-form .sa-template-wrap .setting {
flex: none;
width: 100px;
}
</style>
<div id="addEdit" class="activity-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="title">
<el-input class="sa-w-360" v-model="form.model.title" placeholder="例如:国庆活动" />
</el-form-item>
<el-form-item v-if="form.model.status == 'ing'" label="活动时间" required>
<el-form-item prop="start_time">
<el-date-picker v-model="form.model.start_time" type="datetime"
value-format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss"
:disabled="state.activityStatus" prefix-icon="Calendar" placeholder="开始时间"
:editable="false">
</el-date-picker>
</el-form-item>
<span class="ml-2 mr-2"></span>
<el-form-item prop="end_time">
<el-date-picker v-model="form.model.end_time" type="datetime"
value-format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss" prefix-icon="Calendar"
placeholder="结束时间" :editable="false" @change="onChangeEndtime"></el-date-picker>
</el-form-item>
</el-form-item>
<el-form-item v-if="form.model.status != 'ing'" label="活动时间" prop="dateTime">
<div>
<el-date-picker v-model="form.model.dateTime" 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" />
</div>
</el-form-item>
<template v-if="form.model.type == 'full_reduce' || form.model.type == 'full_discount'">
<el-form-item label="优惠类型" prop="rules.type" required>
<el-radio-group v-model="form.model.rules.type">
<el-radio label="money">消费金额</el-radio>
<el-radio label="num">购买件数</el-radio>
</el-radio-group>
</el-form-item>
<div class="el-form-item-inner" v-for="(ditem, dindex) in form.model.rules.discounts"
:key="dindex">
<el-form-item>
<el-form-item :label="`规则${dindex + 1}`" required>
<el-form-item class="is-no-asterisk" label="消费满"
:prop="'rules.discounts.' + dindex + '.full'"
:rules="form.rules.rules.discounts.full">
<el-input class="w-120" v-model="ditem.full" type="number">
<template #append>
{{ form.model.rules.type == 'money' ? '元' : '件' }}
</template>
</el-input>
</el-form-item>
<el-form-item class="is-no-asterisk ml-2"
:label="`${form.model.type == 'full_reduce' ? '优惠' : '折扣'}`"
:prop="'rules.discounts.' + dindex + '.discount'"
:rules="form.rules.rules.discounts.discount">
<el-input class="w-120" v-model="ditem.discount" type="number">
<template #append>
{{ form.model.type == 'full_reduce' ? '元' : '折' }}
</template>
</el-input>
<div class="tip" v-if="form.model.rules.type == 'money' && dindex == 0">
{{
form.model.type == 'full_reduce' ? '满减' : '满折'
}}金额优惠按照商品实际金额计算
</div>
<el-button v-if="dindex" class="delete" type="danger" link
@click="onDeleteDiscounts(dindex)">
删除
</el-button>
</el-form-item>
</el-form-item>
</el-form-item>
</div>
<el-form-item>
<el-button v-if="
form.model.rules.discounts && form.model.rules.discounts.length < 5
" type="primary" link @click="onAddDiscounts">+ 添加优惠</el-button>
</el-form-item>
</template>
<template v-if="form.model.type == 'full_gift'">
<el-form-item label="参与次数" required>
<el-radio-group v-model="state.limitNumType" @change="onChangeLimitNumType">
<el-radio label="all">不限制</el-radio>
<el-radio label="part">
每人最多可参与
<el-input v-if="state.limitNumType == 'part'" class="w-120 ml-2"
v-model="form.model.rules.limit_num">
<template #append>次数</template>
</el-input>
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="赠送时机" prop="rules.event" required>
<el-radio-group v-model="form.model.rules.event">
<el-radio label="paid">支付完成</el-radio>
<el-radio label="confirm">
<div class="sa-flex">
确认收货
<el-popover popper-class="sa-popper" trigger="hover">
<div>必须全部确认收货才能满足条件</div>
<template #reference>
<el-icon class="warning">
<warning />
</el-icon>
</template>
</el-popover>
</div>
</el-radio>
<el-radio label="finish">交易完成</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="优惠类型" prop="rules.type" required>
<el-radio-group v-model="form.model.rules.type">
<el-radio label="money">满足金额</el-radio>
<el-radio label="num">满足件数</el-radio>
</el-radio-group>
</el-form-item>
<div class="el-form-item-inner" v-for="(ditem, dindex) in form.model.rules.discounts"
:key="ditem">
<el-form-item>
<div class="rules-title">{{ `规则${dindex + 1}` }}</div>
</el-form-item>
<el-form-item>
<el-form-item label="消费满" :prop="'rules.discounts.' + dindex + '.full'"
:rules="form.rules.rules.discounts.full">
<el-input class="w-120" v-model="ditem.full" type="number">
<template #append>
{{ form.model.rules.type == 'money' ? '元' : '件' }}
</template>
</el-input>
<div v-if="dindex == 0" class="tip"> 满赠金额优惠按照商品实际金额计算 </div>
<el-button v-if="dindex" class="delete" type="danger" link
@click="onDeleteDiscounts(dindex)">删除</el-button>
</el-form-item>
</el-form-item>
<el-form-item>
<el-form-item label="赠送单数" :prop="'rules.discounts.' + dindex + '.gift_num'"
:rules="form.rules.rules.discounts.gift_num">
<el-input class="w-120" v-positiveinteger v-model="ditem.gift_num" type="number">
<template #append></template>
</el-input>
<div v-if="dindex == 0" class="tip">
该单数指赠品发放单数如设置100单那参与此活动的前100个订单可获取赠品
</div>
</el-form-item>
</el-form-item>
<el-form-item>
<el-form-item label="赠送类型" :prop="'rules.discounts.' + dindex + '.types'"
:rules="form.rules.rules.discounts.types">
<el-checkbox-group v-model="ditem.types">
<el-checkbox label="coupon">优惠券</el-checkbox>
<el-checkbox label="score">积分</el-checkbox>
<el-checkbox label="money">余额</el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-form-item>
<div class="ml-4">
<!-- 优惠券 -->
<el-form-item v-if="ditem.types.includes('coupon')">
<div>
<el-form-item label="优惠券">
<el-button type="primary" link @click="onSelectCoupon(dindex)">
选择优惠券</el-button>
</el-form-item>
<el-form-item>
<div class="sa-template-wrap">
<template v-if="ditem.coupon_list.length > 0">
<div class="header sa-flex">
<div class="key">名称</div>
<div class="key">优惠内容</div>
<div class="oper">操作</div>
</div>
<div class="item" v-for="(element, index) in ditem.coupon_list"
:key="element">
<div class="key">
<div class="sa-table-line-1">{{ element.name }}</div>
</div>
<div class="key">
<div class="sa-table-line-1">
{{ element.amount_text }}
</div>
</div>
<div class="oper">
<el-button type="danger" link
@click="onDeleteCoupon(dindex, index)">
移除
</el-button>
</div>
</div>
</template>
</div>
</el-form-item>
</div>
</el-form-item>
<!-- 积分 -->
<el-form-item v-if="ditem.types.includes('score')">
<el-form-item label="积分">
<el-input class="w-120" v-positiveinteger v-model="ditem.score" type="number">
<template #append>积分</template>
</el-input>
</el-form-item>
</el-form-item>
<!-- 余额 -->
<el-form-item v-if="ditem.types.includes('money')">
<el-form-item label="余额">
<el-input class="w-120" v-model="ditem.money" type="number">
<template #append></template>
</el-input>
</el-form-item>
</el-form-item>
</div>
</div>
<el-form-item>
<el-button type="primary" link @click="onAddDiscounts">+ 添加优惠</el-button>
</el-form-item>
</template>
<template v-if="form.model.type == 'free_shipping'">
<el-form-item label="优惠类型" prop="rules.type" required>
<el-radio-group v-model="form.model.rules.type">
<el-radio label="money">按消费金额包邮</el-radio>
<el-radio label="num">按购买件数包邮</el-radio>
</el-radio-group>
</el-form-item>
<div class="el-form-item-inner">
<el-form-item>
<el-form-item :label="`规则`" required>
<el-form-item class="is-no-asterisk" label="消费满" prop="rules.full_num"
:rules="form.rules.rules.full_num">
<el-input class="w-120" v-model="form.model.rules.full_num" type="number">
<template #append>
{{ form.model.rules.type == 'money' ? '元' : '件' }}
</template>
</el-input>
<span class="tip">满邮金额优惠按照商品实际金额计算</span>
</el-form-item>
</el-form-item>
</el-form-item>
<el-form-item>
<el-form-item label="不支持地区" required>
<div>
<div class="sa-flex">
<template v-for="level in form.model.rules.district_text" :key="level">
<template v-for="name in level" :key="name">{{ name }},</template>
</template>
</div>
<el-button type="primary" link @click="onSelectArea">添加地区</el-button>
</div>
</el-form-item>
</el-form-item>
</div>
</template>
<template v-if="form.model.type == 'groupon' || form.model.type == 'groupon_ladder'">
<el-form-item label="预热时间" prop="prehead_time">
<el-date-picker v-model="form.model.prehead_time" type="datetime"
value-format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss" placeholder="预热时间"
prefix-icon="Calendar" :disabled="state.activityStatus" :editable="false">
</el-date-picker>
</el-form-item>
<el-form-item label="拼团解散时间" prop="rules.valid_time" :rules="form.rules.rules.valid_time">
<el-input class="w-120" v-model="form.model.rules.valid_time" type="number"
:disabled="state.activityStatus">
<template #append>小时</template>
</el-input>
</el-form-item>
<el-form-item v-if="form.model.type == 'groupon'" label="成团人数" prop="rules.team_num"
:rules="form.rules.rules.team_num">
<el-input class="w-120" v-positiveinteger v-model="form.model.rules.team_num"
placeholder="最少两人" type="number" :disabled="state.activityStatus">
<template #append></template>
</el-input>
</el-form-item>
<template v-if="form.model.type == 'groupon_ladder'">
<el-form-item label="成团人数" required>
<el-form-item class="is-no-asterisk" label="第一阶梯人数" prop="rules.ladders.ladder_one"
:rules="form.rules.rules.ladder_one">
<el-input class="w-120" v-positiveinteger
v-model="form.model.rules.ladders.ladder_one" placeholder="最少两人" type="number"
:disabled="state.activityStatus">
<template #append></template>
</el-input>
</el-form-item>
</el-form-item>
<el-form-item>
<el-form-item class="is-no-asterisk" label="第二阶梯人数" prop="rules.ladders.ladder_two"
:rules="form.rules.rules.ladder_two">
<el-input class="w-120" v-positiveinteger
v-model="form.model.rules.ladders.ladder_two" placeholder="最少两人" type="number"
:disabled="state.activityStatus">
<template #append></template>
</el-input>
</el-form-item>
</el-form-item>
<el-form-item v-if="Object.keys(form.model.rules.ladders).includes('ladder_three')">
<el-form-item class="is-no-asterisk" label="第三阶梯人数" prop="rules.ladders.ladder_three"
:rules="form.rules.rules.ladder_three">
<el-input class="w-120" v-positiveinteger
v-model="form.model.rules.ladders.ladder_three" placeholder="最少两人" type="number"
:disabled="state.activityStatus">
<template #append></template>
</el-input>
<el-button class="delete" type="danger" link @click="onDeleteLadders">删除
</el-button>
</el-form-item>
</el-form-item>
<el-form-item v-if="Object.keys(form.model.rules.ladders).length < 3">
<el-button type="primary" link @click="onAddLadders" :disabled="state.activityStatus">+
添加拼团梯队
</el-button>
</el-form-item>
</template>
<el-form-item label="单独购买">
<el-switch v-model="form.model.rules.is_alone" active-value="1" inactive-value="0"
:disabled="state.activityStatus"></el-switch>
<span class="ml-2" :class="form.model.rules.is_alone == 0 ?'':'sa-color--primary'">
{{ form.model.rules.is_alone == 0 ? '不允许' : '允许' }}
</span>
</el-form-item>
<el-form-item label="虚拟成团">
<el-switch v-model="form.model.rules.is_fictitious" active-value="1" inactive-value="0"
:disabled="state.activityStatus"></el-switch>
<span class="ml-2" :class="form.model.rules.is_fictitious == 0 ?'':'sa-color--primary'">
{{ form.model.rules.is_fictitious == 0 ? '不允许' : '允许' }}
</span>
<div class="tip">
开启虚拟成团后,在拼团有效期内人数不够的团,系统会虚拟用户凑满人数,使拼团成功。
虚拟的用户不生成订单,只需对真实买家发货。(请在资料管理中添加足够数量的虚拟用户,否则虚拟成团不会成功)
</div>
</el-form-item>
<div class="el-form-item-inner" v-if="form.model.rules.is_fictitious == 1">
<el-form-item>
<el-form-item class="is-no-asterisk" label="最多虚拟人数" prop="rules.fictitious_num"
:rules="form.rules.rules.fictitious_num">
<el-input class="w-120" v-model="form.model.rules.fictitious_num" type="number"
:disabled="state.activityStatus">
<template #append></template>
</el-input>
<div class="tip"> 单团最多虚拟人数的名额限制,不填时,不限制名额 </div>
</el-form-item>
</el-form-item>
<el-form-item>
<el-form-item class="is-no-asterisk" label="虚拟成团时间" prop="rules.fictitious_time"
:rules="form.rules.rules.fictitious_time">
<el-input class="w-120" v-model="form.model.rules.fictitious_time" type="number"
:disabled="state.activityStatus">
<template #append>小时</template>
</el-input>
<div class="tip">将会在拼团解散时间之前尝试虚拟成团</div>
</el-form-item>
</el-form-item>
</div>
<el-form-item label="参团卡显示">
<el-switch v-model="form.model.rules.is_team_card" active-value="1" inactive-value="0"
:disabled="state.activityStatus"></el-switch>
<span class="ml-2" :class="form.model.rules.is_team_card == 0?'':'sa-color--primary'">
{{ form.model.rules.is_team_card == 0 ? '关闭' : '开启' }}
</span>
<div class="tip">
开启参团卡显示后,商品详情页显示未成团的团列表,买家可以直接选择一个参团。
</div>
</el-form-item>
<el-form-item label="拼团销量展示">
<el-radio-group v-model="form.model.rules.sales_show_type" :disabled="state.activityStatus">
<el-radio label="real">真实活动销量</el-radio>
<el-radio label="goods">
<div class="sa-flex">
商品总销量
<div class="tip">商品总销量包含虚拟销量</div>
</div>
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="是否参与分销">
<el-switch v-model="form.model.rules.is_commission" active-value="1" inactive-value="0"
:disabled="state.activityStatus"></el-switch>
<span class="ml-2" :class="form.model.rules.is_commission == 0?'':'sa-color--primary'">
{{ form.model.rules.is_commission == 0 ? '不参与' : '参与' }}
</span>
</el-form-item>
<el-form-item label="是否包邮">
<el-switch v-model="form.model.rules.is_free_shipping" active-value="1" inactive-value="0"
:disabled="state.activityStatus"></el-switch>
<span class="ml-2" :class="form.model.rules.is_free_shipping == 0?'':'sa-color--primary'">
{{ form.model.rules.is_free_shipping == 0 ? '不包邮' : '包邮' }}
</span>
</el-form-item>
<el-form-item label="团长优惠">
<el-switch v-model="form.model.rules.is_leader_discount" active-value="1" inactive-value="0"
:disabled="state.activityStatus"></el-switch>
</el-form-item>
<el-form-item label="限购数量">
<el-input class="w-120" v-positiveinteger v-model="form.model.rules.limit_num" type="number"
:disabled="state.activityStatus">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item label="退款方式">
<div>
<el-radio-group v-model="form.model.rules.refund_type" :disabled="state.activityStatus">
<el-radio label="back">原路返回</el-radio>
<el-radio label="money">退回到余额</el-radio>
</el-radio-group>
<div class="tip">拼团失败解散时,默认退款方式</div>
</div>
</el-form-item>
<el-form-item label="订单支付时间" prop="rules.order_auto_close"
:rules="form.rules.rules.order_auto_close">
<el-input class="w-120" v-model="form.model.rules.order_auto_close" type="number"
:disabled="state.activityStatus">
<template #append>分钟</template>
</el-input>
</el-form-item>
</template>
<template v-if="form.model.type == 'seckill'">
<el-form-item label="预热时间" prop="prehead_time">
<el-date-picker v-model="form.model.prehead_time" type="datetime"
value-format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss" placeholder="预热时间"
prefix-icon="Calendar" :disabled="state.activityStatus" :editable="false">
</el-date-picker>
</el-form-item>
<el-form-item label="是否参与分销">
<el-switch v-model="form.model.rules.is_commission" active-value="1" inactive-value="0"
:disabled="state.activityStatus"></el-switch>
<span class="ml-2" :class="form.model.rules.is_commission == 0?'':'sa-color--primary'">
{{ form.model.rules.is_commission == 0 ? '不参与' : '参与' }}
</span>
</el-form-item>
<el-form-item label="是否包邮">
<el-switch v-model="form.model.rules.is_free_shipping" active-value="1" inactive-value="0"
:disabled="state.activityStatus"></el-switch>
<span class="ml-2" :class="form.model.rules.is_free_shipping == 0?'':'sa-color--primary'">
{{ form.model.rules.is_free_shipping == 0 ? '不包邮' : '包邮' }}
</span>
</el-form-item>
<el-form-item label="秒杀销量展示">
<el-radio-group v-model="form.model.rules.sales_show_type" :disabled="state.activityStatus">
<el-radio label="real">真实活动销量</el-radio>
<el-radio label="goods">
<div class="sa-flex">
商品总销量
<div class="tip">商品总销量包含虚拟销量</div>
</div>
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="限购数量">
<el-input class="w-120" v-positiveinteger v-model="form.model.rules.limit_num" type="number"
:disabled="state.activityStatus">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item label="订单支付时间" prop="rules.order_auto_close" :rules="form.rules.order_auto_close">
<el-input class="w-120" v-model="form.model.rules.order_auto_close" type="number"
:disabled="state.activityStatus">
<template #append>分钟</template>
</el-input>
</el-form-item>
</template>
<template v-if="form.model.type == 'signin'">
<el-form-item label="日签奖励" prop="rules.everyday">
<span>每日签到固定积分</span>
<el-input class="w-120 ml-2" v-positiveinteger v-model="form.model.rules.everyday"
type="number">
<template #append>积分</template>
</el-input>
</el-form-item>
<el-form-item label="递增签到" prop="rules.is_inc" required>
<el-switch v-model="form.model.rules.is_inc" active-value="1" inactive-value="0">
</el-switch>
<span class="ml-2" :class="form.model.rules.is_inc == 0 ?'':'sa-color--primary'">
{{ form.model.rules.is_inc == 0 ? '关闭' : '开启' }}
</span>
</el-form-item>
<div v-if="form.model.rules.is_inc == 1" class="el-form-item-inner">
<el-form-item>
<el-form-item class="is-no-asterisk" label="次日起递增奖励" prop="rules.inc_num">
<el-input class="w-120" v-positiveinteger v-model="form.model.rules.inc_num"
type="number">
<template #append>积分</template>
</el-input>
</el-form-item>
<el-form-item class="is-no-asterisk ml-2" label="自" prop="rules.until_day">
<el-input class="w-120" v-positiveinteger v-model="form.model.rules.until_day"
type="number">
<template #append></template>
</el-input>
<span class="desc ml-2">后不再递增</span>
</el-form-item>
</el-form-item>
</div>
<el-form-item label="连续签到">
<el-switch v-model="state.is_discounts" active-value="1" inactive-value="0"
@change="onChangeDiscounts"></el-switch>
<span class="ml-2" :class="state.is_discounts == 0?'':'sa-color--primary'">
{{ state.is_discounts == 0 ? '关闭' : '开启' }}
</span>
</el-form-item>
<div v-if="state.is_discounts == 1" class="el-form-item-inner">
<el-form-item v-for="(d, dindex) in form.model.rules.discounts" :key="d">
<el-form-item :label="`条件${dindex + 1}`" required>
<el-form-item class="is-no-asterisk" label="连续签到"
:prop="'rules.discounts.' + dindex + '.full'"
:rules="form.rules.rules.discounts.full">
<el-input class="w-120" v-positiveinteger v-model="d.full" type="number">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item class="is-no-asterisk ml-2" label="赠送积分"
:prop="'rules.discounts.' + dindex + '.value'"
:rules="form.rules.rules.discounts.value">
<el-input class="w-120" v-positiveinteger v-model="d.value" type="number">
<template #append>积分</template>
</el-input>
<el-button v-if="dindex" class="delete" type="danger" link size="small"
@click="onDeleteDiscounts">
删除
</el-button>
</el-form-item>
</el-form-item>
</el-form-item>
<el-form-item>
<el-button v-if="form.model.rules.discounts.length < 3" type="primary" link
@click="onAddDiscounts">
+ 添加连续签到天数
</el-button>
</el-form-item>
</div>
<el-form-item label="补签设置">
<el-switch v-model="form.model.rules.is_replenish" active-value="1" inactive-value="0">
</el-switch>
<span class="ml-2" :class="form.model.rules.is_replenish == 0 ?'':'sa-color--primary'">
{{ form.model.rules.is_replenish == 0 ? '关闭' : '开启' }}
</span>
</el-form-item>
<div v-if="form.model.rules.is_replenish == 1" class="el-form-item-inner">
<el-form-item>
<el-form-item label="用户在" prop="rules.replenish_limit">
<el-input class="w-120" v-positiveinteger v-model="form.model.rules.replenish_limit"
type="number">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item class="is-no-asterisk ml-2" label="内可补签" prop="rules.replenish_days">
<el-input class="w-120" v-positiveinteger v-model="form.model.rules.replenish_days"
type="number">
<template #append></template>
</el-input>
</el-form-item>
</el-form-item>
<el-form-item>
<el-form-item label="每次补签消耗积分" prop="rules.replenish_num">
<el-input class="w-120" v-positiveinteger v-model="form.model.rules.replenish_num"
type="number">
<template #append>积分</template>
</el-input>
</el-form-item>
</el-form-item>
</div>
</template>
<el-form-item label="活动说明">
<el-input class="sa-w-360" v-model="form.model.richtext_title" placeholder="请选择活动说明">
<template #append>
<span class="cursor-pointer" @click="onSelectRichtext">选择活动说明</span>
</template>
</el-input>
</el-form-item>
<template v-if="form.model.type != 'signin'">
<el-form-item v-if="!isActivity" label="活动商品" prop="state.goodsType">
<el-radio-group v-model="state.goodsType" :disabled="state.activityStatus"
@change="onChangeGoodsType">
<el-radio label="all">全部商品</el-radio>
<el-radio label="part">部分商品</el-radio>
</el-radio-group>
</el-form-item>
<template v-if="state.goodsType == 'part'">
<el-form-item :label="isActivity ? '活动商品' : ''"
:prop="state.goodsType == 'part' || isActivity ? 'goods_list' : ''">
<el-button type="primary" link @click="onSelectGoods" :disabled="state.activityStatus">+
添加商品
</el-button>
</el-form-item>
</template>
<el-form-item v-if="form.model.goods_list.length > 0">
<div class="sa-template-wrap" :class="isActivity ? 'sa-template-wrap-activity' : ''">
<div class="header sa-flex">
<div class="key">商品信息</div>
<div v-if="isActivity" class="key setting">设置</div>
<div class="oper">操作</div>
</div>
<div>
<div class="item" v-for="(element, index) in form.model.goods_list" :key="element">
<div class="key goods-item">
<sa-image class="goods-image" :url="element.image" size="40"></sa-image>
<div class="">
<div class="goods-title sa-table-line-1">
{{ element.title }}
</div>
<div class="goods-price"> ¥{{ element.price.join('~') }} </div>
</div>
</div>
<div v-if="isActivity" class="key setting">
<el-button type="primary" link
@click="onSetActivitySkuPrices(index, element.id)">设置商品</el-button>
</div>
<div class="oper">
<el-button type="danger" link @click="onDeleteGoods(index)"
:disabled="state.activityStatus">
移除
</el-button>
</div>
</div>
</div>
</div>
</el-form-item>
</template>
</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,106 @@
{include file="/shopro/common/script" /}
<div id="index" class="activity-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">{{state.title}}</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/activity/activity/add')}
<el-button icon="Plus" type="primary" @click="onAdd">添加</el-button>
{/if}
{if $auth->check('shopro/activity/activity/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="200">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.title }}</div>
</template>
</el-table-column>
<el-table-column v-if="state.type != 'signin'" label="参与商品" min-width="244">
<template #default="scope">
<template v-if="scope.row.goods_ids">
<el-popover width="300" trigger="hover">
<template v-if="scope.row.goods.length>0">
<div class="sa-flex" v-for="item in scope.row.goods" :key="item">
<sa-image class="mr-2" :url="item.image" size="40"></sa-image>
<div>
<div class="sa-table-line-1 mb-1">
{{ item.title }}
</div>
<div>#{{ item.id }}</div>
</div>
</div>
</template>
<div v-else>
#{{scope.row.goods_ids}}
</div>
<template #reference>
<span class="sa-color--primary">{{scope.row.goods_ids.split(',')?.length }}</span>
</template>
</el-popover>
件商品
</template>
<div v-if="!scope.row.goods_ids">全部商品</div>
</template>
</el-table-column>
<el-table-column label="活动状态" min-width="110">
<template #default="scope">
<div :class="`${state.statusStyle[scope.row.status]}`">
{{ scope.row.status_text }}
</div>
</template>
</el-table-column>
<el-table-column label="活动时间" min-width="250">
<template #default="scope">
<div>
<div>开始时间:{{ scope.row.start_time }}</div>
<div>结束时间:{{ scope.row.end_time }}</div>
</div>
</template>
</el-table-column>
<el-table-column prop="updatetime" label="更新时间" width="172"></el-table-column>
<el-table-column label="活动说明" min-width="158">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.richtext_title || '-'}}</div>
</template>
</el-table-column>
<el-table-column label="操作" min-width="160" fixed="right">
<template #default="scope">
{if $auth->check('shopro/activity/groupon/index')}
<el-button v-if="state.type == 'groupon' || state.type == 'groupon_ladder'" type="primary" link
@click="onGroupon(scope.row.id)">查看</el-button>
{/if}
{if $auth->check('shopro/activity/activity/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/activity/activity/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,20 @@
{include file="/shopro/common/script" /}
<div id="recyclebin" class="activity-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="100">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.title || '-' }}</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>

View File

@@ -0,0 +1,33 @@
{include file="/shopro/common/script" /}
<div id="select" class="activity-select" v-cloak>
<el-container class="panel-block">
<el-main>
<el-table height="100%" class="sa-table" :data="state.data" stripe>
<el-table-column prop="id" label="ID" min-width="90"></el-table-column>
<el-table-column label="名称" min-width="128">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.title }}
</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 fixed="right" label="操作" min-width="120">
<template #default="scope">
<el-button type="primary" link @click="onConfirm(scope.row)">选择</el-button>
</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>
</div>

View File

@@ -0,0 +1,171 @@
{include file="/shopro/common/script" /}
<style>
.activity-skus .sku-table-wrap {
width: 100%;
overflow: auto;
}
.activity-skus .sku-table-wrap .sku-table {
font-size: 12px;
font-weight: 500;
}
.activity-skus .sku-table-wrap .sku-table thead {
line-height: 40px;
background: var(--sa-table-header-bg);
color: var(--subtitle);
}
.activity-skus .sku-table-wrap .sku-table tbody {}
.activity-skus .sku-table-wrap .sku-table tbody tr {
line-height: 48px;
color: var(--sa-font);
}
.activity-skus .sku-table-wrap .sku-table tbody tr:nth-of-type(2n) {
background: var(--sa-table-striped);
}
.activity-skus .sku-table-wrap .sku-table th,
.activity-skus .sku-table-wrap .sku-table td {
padding: 0 16px;
text-align: left;
}
.activity-skus .sku-table-wrap .sku-item {
min-width: 100px;
flex-shrink: 0;
}
</style>
<div id="skus" class="activity-skus" v-cloak>
<el-container class="panel-block">
<el-main>
<div class="sku-table-wrap">
<table class="sku-table" rules="none">
<thead>
<tr>
<th class="sku-item" v-for="ss in state.skus" :key="ss">
{{ ss.name }}
</th>
<th class="sku-item">库存</th>
<th class="sku-item">价格</th>
<th class="sku-item">销量</th>
<th class="sku-item">活动库存</th>
<th v-if="['groupon', 'seckill'].includes(state.model.type)" class="sku-item">
活动价格
</th>
<th class="sku-item" v-if="
state.model.type == 'groupon' &&
state.model.rules.is_leader_discount == 1
">
团长价格
</th>
<template v-if="state.model.type == 'groupon_ladder'">
<th class="sku-item">
{{ state.model.rules.ladders.ladder_one }}人团价格
</th>
<th class="sku-item" v-if="state.model.rules.is_leader_discount == 1">
{{ state.model.rules.ladders.ladder_one }}人团长价格
</th>
<th class="sku-item">
{{ state.model.rules.ladders.ladder_two }}人团价格
</th>
<th class="sku-item" v-if="state.model.rules.is_leader_discount == 1">
{{ state.model.rules.ladders.ladder_two }}人团长价格
</th>
<template v-if="Object.keys(state.model.rules.ladders).includes('ladder_three')">
<th class="sku-item">
{{ state.model.rules.ladders.ladder_three }}人团价格
</th>
<th class="sku-item" v-if="state.model.rules.is_leader_discount == 1">
{{ state.model.rules.ladders.ladder_three }}人团长价格
</th>
</template>
</template>
<th class="sku-item">操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(sp, spindex) in state.sku_prices" :key="sp">
<td class="sku-item" v-for="st in sp.goods_sku_text" :key="st">
{{ st }}
</td>
<td class="sku-item">{{ sp.stock }}</td>
<td class="sku-item">{{ sp.price }}</td>
<td class="sku-item">{{ sp.sales }}</td>
<th class="sku-item">
<el-input v-if="state.activity_sku_prices[spindex].status == 'up'" type="number"
v-model="state.activity_sku_prices[spindex].stock"></el-input>
</th>
<th v-if="['groupon', 'seckill'].includes(state.model.type)" class="sku-item">
<el-input v-if="state.activity_sku_prices[spindex].status == 'up'" type="number"
v-model="state.activity_sku_prices[spindex].price" :disabled="state.activityStatus">
</el-input>
</th>
<th class="sku-item" v-if="
state.model.type == 'groupon' &&
state.model.rules.is_leader_discount == 1
">
<el-input v-if="state.activity_sku_prices[spindex].status == 'up'" type="number"
v-model="state.activity_sku_prices[spindex].leader_price"
:disabled="state.activityStatus"></el-input>
</th>
<template v-if="state.model.type == 'groupon_ladder'">
<th class="sku-item">
<el-input v-if="state.activity_sku_prices[spindex].status == 'up'" type="number"
v-model="state.activity_sku_prices[spindex].ladder_one"
:disabled="state.activityStatus"></el-input>
</th>
<th class="sku-item" v-if="state.model.rules.is_leader_discount == 1">
<el-input v-if="state.activity_sku_prices[spindex].status == 'up'" type="number"
v-model="state.activity_sku_prices[spindex].ladder_one_leader"
:disabled="state.activityStatus"></el-input>
</th>
<th class="sku-item">
<el-input v-if="state.activity_sku_prices[spindex].status == 'up'" type="number"
v-model="state.activity_sku_prices[spindex].ladder_two"
:disabled="state.activityStatus"></el-input>
</th>
<th class="sku-item" v-if="state.model.rules.is_leader_discount == 1">
<el-input v-if="state.activity_sku_prices[spindex].status == 'up'" type="number"
v-model="state.activity_sku_prices[spindex].ladder_two_leader"
:disabled="state.activityStatus"></el-input>
</th>
<template v-if="Object.keys(state.model.rules.ladders).includes('ladder_three')">
<th class="sku-item">
<el-input type="number"
v-model="state.activity_sku_prices[spindex].ladder_three"
v-if="state.activity_sku_prices[spindex].status == 'up'"
:disabled="state.activityStatus"></el-input>
</th>
<th class="sku-item" v-if="state.model.rules.is_leader_discount == 1">
<el-input v-if="state.activity_sku_prices[spindex].status == 'up'" type="number"
v-model="state.activity_sku_prices[spindex].ladder_three_leader"
:disabled="state.activityStatus"></el-input>
</th>
</template>
</template>
<th class="sku-item">
<template v-if="!state.activityStatus">
<el-button v-if="state.activity_sku_prices[spindex].status == 'up'" class="is-link"
type="danger" @click="state.activity_sku_prices[spindex].status = 'down'">取消
</el-button>
<el-button v-if="state.activity_sku_prices[spindex].status == 'down'"
class="is-link" type="primary"
@click="state.activity_sku_prices[spindex].status = 'up'">参与</el-button>
</template>
<template v-if="state.activityStatus">-</template>
</th>
</tr>
</tbody>
</table>
</div>
</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,96 @@
{include file="/shopro/common/script" /}
<style>
.groupon-detail .goods-item .goods-title {
color: var(--el-color-primary);
}
.groupon-detail .goods-item .goods-num {
font-size: 12px;
}
</style>
<div id="detail" class="groupon-detail" v-cloak>
<el-container class="panel-block">
<el-main>
<el-table class="sa-table" :data="[{}]" stripe>
<el-table-column label="拼团商品" min-width="490">
<template #default>
<div v-if="state.data.goods" class="goods-item sa-flex">
<sa-image class="mr-2" :url="state.data.goods.image" size="40"></sa-image>
<div>
<div class="goods-title sa-table-line-1"
@click="onOpenGoodsDetail(state.data.goods_id)">
{{ state.data.goods.title || '-' }}
</div>
<div class="goods-num"> 成团人数:{{ state.data.num }} </div>
</div>
</div>
<div v-else>{{state.data.goods_id}}</div>
</template>
</el-table-column>
<el-table-column label="开团时间" width="172">
<template #default>
{{ state.data.createtime || '-' }}
</template>
</el-table-column>
<el-table-column label="拼团状态" min-width="80">
<template #default>
<div :class="`sa-color--${state.statusClass[state.data.status]}`">
{{ state.data.status_text || '-' }}
</div>
</template>
</el-table-column>
</el-table>
<el-table class="sa-table" :data="state.data.groupon_logs" stripe>
<el-table-column label="身份" min-width="80">
<template #default="scope">
<span v-if="scope.row.is_leader == 1">团长</span>
<span v-else>团员</span>
</template>
</el-table-column>
<el-table-column label="头像" width="64">
<template #default="scope">
<sa-image :url="scope.row.avatar" size="32" radius="16"></sa-image>
</template>
</el-table-column>
<el-table-column label="昵称" width="258">
<template #default="scope">
<sa-user-profile :user="scope.row" :id="scope.row.user_id" :isavatar="false"
:ishover="!scope.row.is_fictitious"></sa-user-profile>
</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="170">
<template #default="scope">
<template v-if="scope.row.is_temp">
<el-button type="primary" link @click="onConfirm(scope.row)">确定
</el-button>
<el-button type="danger" link @click="onCancel(scope.$index)">取消
</el-button>
</template>
<span v-if="scope.row.is_fictitious == 1 && !scope.row.is_temp">虚拟</span>
</template>
</el-table-column>
</el-table>
</el-main>
<el-footer v-if="state.data.status == 'ing'" class="sa-footer--submit sa-flex sa-row-between">
<el-popconfirm width="fit-content" confirm-button-text="确认" cancel-button-text="取消" title="确定要解散拼团吗?"
@confirm="onInvalid">
<template #reference>
{if $auth->check('shopro/activity/groupon/invalid')}
<el-button>解散拼团</el-button>
{/if}
</template>
</el-popconfirm>
{if $auth->check('shopro/activity/groupon/addUser')}
<el-button type="primary" :disabled="!(state.data.groupon_logs.length<state.data.num)" @click="onAddUser">
添加虚拟人数</el-button>
{/if}
</el-footer>
</el-container>
</div>

View File

@@ -0,0 +1,105 @@
{include file="/shopro/common/script" /}
<style>
.groupon-index .goods-item .goods-title {
color: var(--el-color-primary);
}
.groupon-index .goods-item .goods-num {
font-size: 12px;
}
.groupon-index .avatar {
margin-right: 4px;
}
</style>
<div id="index" class="groupon-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.status" @tab-change="onChangeTab">
<el-tab-pane v-for="item in state.statusList" :key="item" :label="item.name" :name="item.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>
</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="240">
<template #default="scope">
<div v-if="scope.row.goods" class="goods-item sa-flex">
<sa-image class="mr-2" :url="scope.row.goods.image" size="40"></sa-image>
<div>
<div class="goods-title sa-table-line-1" @click="onOpenGoodsDetail(scope.row.goods_id)">
{{ scope.row.goods.title || '-' }}
</div>
<div class="goods-num"> 成团人数:{{ scope.row.num }} </div>
</div>
</div>
<div v-else>{{scope.row.goods_id}}</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="124">
<template #default="scope">
<sa-user-profile :user="scope.row.user" :id="scope.row.user_id" />
</template>
</el-table-column>
<el-table-column label="已参团成员" min-width="180">
<template #default="scope">
<el-scrollbar>
<div class="sa-flex">
<template v-for="item in scope.row.groupon_logs" :key="item">
<sa-image class="avatar" :url="item.avatar" size="32" radius="16"></sa-image>
</template>
</div>
</el-scrollbar>
</template>
</el-table-column>
<el-table-column label="剩余名额" min-width="90">
<template #default="scope">
{{ scope.row.num - scope.row.current_num }}
</template>
</el-table-column>
<el-table-column label="组团有效时间" width="172">
<template #default="scope">
{{ scope.row.finish_time || '-' }}
</template>
</el-table-column>
<el-table-column label="拼团状态" min-width="88">
<template #default="scope">
<div :class="`sa-color--${state.statusClass[scope.row.status]}`">
{{ scope.row.status_text || '-' }}
</div>
</template>
</el-table-column>
<el-table-column fixed="right" label="操作" min-width="100">
<template #default="scope">
{if $auth->check('shopro/activity/groupon/detail')}
<el-button type="primary" link @click="onDetail(scope.row.id)">查看详情</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,118 @@
{include file="/shopro/common/script" /}
<style>
.desc {
font-size: 14px;
color: #999999;
margin-left: 12px;
}
.title {
margin: 0 0 18px 50px;
}
.price-title {
margin-right: 8px;
}
.price2-title {
margin: 0 8px 0 16px;
}
.el-form .sa-w-160 {
max-width: 160px;
width: 100%;
display: flex;
align-items: center;
flex-wrap: nowrap;
}
</style>
<div id="addEdit" class="molive-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="120px">
<div class="sa-color--warning title">在小程序直播控制台添加的商品,不支持通过此系统操作。</div>
<el-form-item label="商品来源">
<el-radio-group v-model="form.model.type">
<el-radio :label="0">我的小程序</el-radio>
<el-radio :label="1">其他小程序</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="商品选择" prop="goods_id" v-if="form.model.type === 0">
<el-button type="primary" link @click="selectGoods" v-if="!form.model.goods_id">+ 添加商品
</el-button>
<div class="sa-template-wrap">
<template v-if="form.model.goods_id">
<div class="header">
<div class="key">商品信息</div>
<div class="oper">操作</div>
</div>
<div class="item">
<div class="goods-item key">
<sa-image class="goods-image" :url="goods.image" size="40">
</sa-image>
<div>
<div class="goods-title sa-table-line-1">{{ goods.title }}</div>
</div>
</div>
<div class="oper">
<el-button type="danger" link @click="deleteItems()">移除
</el-button>
</div>
</div>
</template>
</div>
</el-form-item>
<el-form-item label="商品封面">
<sa-uploader v-model="form.model.cover_img_url" fileType="image"></sa-uploader>
<div class="desc"> 图片尺寸最大300像素*300像素 </div>
</el-form-item>
<el-form-item label="商品名称" prop="name">
<el-input v-model="form.model.name" :maxlength="14" :minlength="3" show-word-limit
placeholder="请输入商品名称"></el-input>
</el-form-item>
<el-form-item label="价格形式" prop="price_type">
<el-radio-group v-model="form.model.price_type">
<el-radio :label="1">一口价</el-radio>
<el-radio :label="2">价格区间</el-radio>
<el-radio :label="3">显示折扣价</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="价格">
<div class="price-title" v-if="form.model.price_type !== 1">{{
form.model.price_type === 2 ? '最小价格' : '市场价'
}}</div>
<el-input v-model="form.model.price" placeholder="请输入价格" class="sa-w-160" type="number"
:step="0.01" :min="0" :precision="2">
<template #append></template>
</el-input>
<div class="price2-title" v-if="form.model.price_type !== 1">{{
form.model.price_type === 2 ? '最大价格' : '现价'
}}</div>
<el-input v-model="form.model.price2" placeholder="请输入价格" class="sa-w-160" type="number"
:step="0.01" :min="0" :precision="2" v-if="form.model.price_type !== 1">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item label="APPID" prop="third_party_appid" v-if="form.model.type === 1">
<el-input v-model="form.model.third_party_appid" placeholder="请输入该小程序APPID"></el-input>
</el-form-item>
<el-form-item label="商品路径" prop="url">
<div>
<el-input v-model="form.model.url" placeholder="请输入商品路径"></el-input>
<div class="desc">
请确保小程序页面路径可被访问。例如pages/goods/index?query=value
</div>
</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,252 @@
{include file="/shopro/common/script" /}
<style>
.price-title {
text-decoration: line-through;
margin-right: 8px;
color: var(--sa-subfont);
}
.live-qrcode {
width: 150px;
height: 150px;
}
.empty-data {
width: 210px;
height: 150px;
}
</style>
<div id="index" class="mplive-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="dispatchType">
<el-tab-pane label="直播间管理" name="live"></el-tab-pane>
<el-tab-pane label="商品库管理" name="goods"></el-tab-pane>
</el-tabs>
<div class="sa-title sa-flex sa-row-between">
<div class="sa-title-left">
<div class="left-name">{{ dispatchType === 'live' ? '直播间管理' : '商品库管理' }}</div>
<sa-filter-condition v-model="state.filter" @filter-delete="onChangeFilter">
</sa-filter-condition>
</div>
<div v-if="dispatchType === 'live'">
<el-popover placement="bottom" :width="180" trigger="click">
<template #reference>
<el-button class="sa-button-refresh">主播端</el-button>
</template>
<img class="live-qrcode" src="/assets/addons/shopro/img/live-qrcode.png" />
</el-popover>
<!-- :loading="loading" -->
{if $auth->check('shopro/app/mplive/room/sync')}
<el-button class="sa-button-refresh" icon="RefreshRight" @click="sync">同步直播间</el-button>
{/if}
{if $auth->check('shopro/app/mplive/room/add')}
<el-button class="sa-button-refresh" type="primary" icon="Plus" @click="addRow">创建直播间</el-button>
{/if}
</div>
<div v-if="dispatchType === 'goods'">
<el-button class="sa-button-refresh" icon="RefreshRight" @click="getData()"></el-button>
<el-button class="sa-button-refresh" icon="Search" @click="openFilter"></el-button>
{if $auth->check('shopro/app/mplive/goods/add')}
<el-button class="sa-button-refresh" type="primary" icon="Plus" @click="addGoods">添加商品</el-button>
{/if}
</div>
</div>
</el-header>
<!-- v-loading="loading" -->
<el-main class="sa-p-0">
<el-table height="100%" class="sa-table" :data="live.data" stripe @sort-change="onChangeSort" v-if="dispatchType === 'live'">
<el-table-column label="房间ID" sortable="custom" min-width="120" align="center">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.roomid }}</div>
</template>
</el-table-column>
<el-table-column label="直播类型" min-width="120" align="center">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.type_text }}</div>
</template>
</el-table-column>
<el-table-column label="直播间标题" min-width="200" align="center">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.name }}</div>
</template>
</el-table-column>
<el-table-column label="主播昵称" min-width="120" align="center">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.anchor_name }}</div>
</template>
</el-table-column>
<el-table-column label="状态" min-width="120" align="center">
<template #default="scope">
<div class="sa-table-line-1" :class="
scope.row.status === 101
? 'sa-color--success'
: scope.row.status === 102
? 'sa-color--warning'
: scope.row.status === 105
? 'sa-color--info'
: 'sa-color--danger'
">{{ scope.row.status_text }}</div>
</template>
</el-table-column>
<el-table-column label="背景图" min-width="80" align="center">
<template #default="scope">
<div class="sa-flex sa-row-center">
<sa-image :url="scope.row.cover_img" size="30">
</sa-image>
</div>
</template>
</el-table-column>
<el-table-column label="分享图" min-width="80" align="center">
<template #default="scope">
<div class="sa-flex sa-row-center">
<sa-image :url="scope.row.share_img" size="30"></sa-image>
</div>
</template>
</el-table-column>
<el-table-column label="封面图" min-width="80" align="center">
<template #default="scope">
<div class="sa-flex sa-row-center">
<sa-image :url="scope.row.feeds_img" size="30"></sa-image>
</div>
</template>
</el-table-column>
<el-table-column label="开播时间" min-width="200" align="center">
<template #default="scope">
<div class="sa-table-line-1">{{
Moment(scope.row.start_time * 1000).format('YYYY-MM-DD HH:mm')
}}</div>
</template>
</el-table-column>
<el-table-column label="结束时间" min-width="200" align="center">
<template #default="scope">
<div class="sa-table-line-1">{{
Moment(scope.row.end_time * 1000).format('YYYY-MM-DD HH:mm')
}}</div>
</template>
</el-table-column>
<el-table-column label="操作" min-width="340" fixed="right" align="center">
<template #default="scope">
{if $auth->check('shopro/app/mplive/room/edit')}
<el-button link type="primary" @click="editRow(scope.row.roomid)">编辑</el-button>
{/if}
{if $auth->check('shopro/app/mplive/room/pushurl')}
<el-button link type="primary" @click="pushUrl(scope.row.roomid)"
v-if="scope.row.type === 1 && (scope.row.status === 101 || scope.row.status === 102)">推流地址</el-button>
{/if}
{if $auth->check('shopro/app/mplive/room/qrcode')}
<el-button link type="primary" @click="shareQrcode(scope.row.roomid)"
v-if="scope.row.status === 101 || scope.row.status === 102">分享二维码</el-button>
{/if}
{if $auth->check('shopro/app/mplive/room/playback')}
<el-button link type="primary" @click="playBack(scope.row.roomid)"
v-if="scope.row.status === 103">回放</el-button>
{/if}
<el-popconfirm width="fit-content" confirm-button-text="确认" cancel-button-text="取消"
title="确认删除这条记录?" @confirm="deleteApi(scope.row.roomid)">
<template #reference>
{if $auth->check('shopro/app/mplive/room/delete')}
<el-button link type="danger">
删除
</el-button>
{/if}
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<el-table height="100%" class="sa-table" :data="goods.data" stripe v-if="dispatchType === 'goods'">
<el-table-column prop="id" label="ID" min-width="80"></el-table-column>
<el-table-column label="商品来源" min-width="120" align="center">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.type_text }}</div>
</template>
</el-table-column>
<el-table-column label="商品封面" min-width="80" align="center">
<template #default="scope">
<div class="sa-flex sa-row-center">
<sa-image :url="scope.row.cover_img_url" size="30">
</sa-image>
</div>
</template>
</el-table-column>
<el-table-column label="商品名称" min-width="220" align="center">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.name }}</div>
</template>
</el-table-column>
<el-table-column label="价格形式" min-width="120" align="center">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.price_type_text }}</div>
</template>
</el-table-column>
<el-table-column label="价格" min-width="200" align="center">
<template #default="scope">
<div class="sa-table-line-1">
<div class="sa-flex sa-row-center">
<div :class="{ 'price-title': scope.row.price_type === 3 }">{{ scope.row.price }}元</div>
<div>
{{ formatPrice(scope.row.price2, scope.row.price_type) }}
</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="商品路径" min-width="300" align="center">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.url }}</div>
</template>
</el-table-column>
<el-table-column label="审核状态" min-width="120" align="center" fixed="right">
<template #default="scope">
<div class="sa-flex sa-row-center">
<div class="sa-table-line-1" :class="
scope.row.audit_status === 2
? 'sa-color--success'
: scope.row.audit_status === 3
? 'sa-color--danger'
: scope.row.audit_status === 1 ? 'sa-color--warning' : 'sa-color--info'
">{{ scope.row.audit_status_text }}</div>
<el-button link icon="RefreshRight" @click="getStatus(scope.row.id)"></el-button>
</div>
</template>
</el-table-column>
<el-table-column label="操作" min-width="200" fixed="right">
<template #default="scope">
{if $auth->check('shopro/app/mplive/goods/edit')}
<el-button link type="primary" @click="editGoods(scope.row.id)">编辑</el-button>
{/if}
{if $auth->check('shopro/app/mplive/goods/audit')}
<el-button link type="primary" @click="check(scope.row.id, 'resubmit')"
v-if="scope.row.audit_status === 0 || scope.row.audit_status === 3">提交审核</el-button>
{/if}
{if $auth->check('shopro/app/mplive/goods/audit')}
<el-button link type="primary" v-if="scope.row.audit_status === 1"
@click="check(scope.row.id, 'reset')">撤回审核</el-button>
{/if}
<el-popconfirm width="fit-content" confirm-button-text="确认" cancel-button-text="取消"
title="确认删除这条记录?" @confirm="deleteGoods(scope.row.id)">
<template #reference>
{if $auth->check('shopro/app/mplive/goods/delete')}
<el-button link type="danger">删除</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" v-if="dispatchType === 'goods'">
<div class="sa-batch sa-flex">
</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,134 @@
{include file="/shopro/common/script" /}
<style>
.desc {
font-size: 14px;
color: #999999;
margin-left: 12px;
}
.qrcode-img {
width: 150px;
height: 150px;
}
</style>
<div id="addEdit" class="molive-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="120px">
<el-form-item label="直播类型" prop="type">
<div>
<el-radio-group v-model="form.model.type">
<el-radio :label="0">手机直播</el-radio>
<el-radio :label="1">推流设备直播</el-radio>
</el-radio-group>
<div class="desc" v-if="form.model.type === 0">通过“小程序直播”小程序开播</div>
<div class="desc" v-if="form.model.type === 1">通过第三方推流设备发起直播,请自行定义画面宽高比</div>
</div>
</el-form-item>
<el-form-item label="直播间标题" prop="name">
<el-input v-model="form.model.name" placeholder="请输入直播间标题"></el-input>
</el-form-item>
<el-form-item label="背景图" prop="cover_img">
<sa-uploader v-model="form.model.cover_img" fileType="image"></sa-uploader>
<div class="desc"> 直播间背景图图片建议像素1080*1920大小不超过2M </div>
</el-form-item>
<el-form-item label="分享图" prop="share_img">
<sa-uploader v-model="form.model.share_img" fileType="image"></sa-uploader>
<div class="desc"> 直播间分享图图片建议像素800*640大小不超过1M </div>
</el-form-item>
<el-form-item label="封面图" prop="feeds_img">
<sa-uploader v-model="form.model.feeds_img" fileType="image"></sa-uploader>
<div class="desc">
购物直播频道封面图图片建议像素800*800大小不超过100KB
</div>
</el-form-item>
<el-form-item label="开播时间" prop="date_time">
<div>
<el-date-picker v-model="form.model.date_time" type="datetimerange"
value-format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD HH:mm:ss"
:default-time="defaultTime"
range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间"
prefix-icon="Calendar" :editable="false" :disabled-date="disabledDate" />
</div>
<div class="desc">
开播时间需要在当前时间的30分钟后 并且 开始时间不能在 6 个月后<br />
开播时间和结束时间间隔不得短于30分钟不得超过72小时<br />
开播时间段仅供参考,不是实际直播间可以开播的时间。<br />
直播间在开始时间前也可以开播,并且到结束时间后不会强制结束。<br />
若到结束时间仍未开播,则直播间无法再开播。
</div>
</el-form-item>
<el-form-item label="主播昵称" prop="anchor_name">
<el-input v-model="form.model.anchor_name" placeholder="请输入主播昵称"></el-input>
</el-form-item>
<el-form-item label="主播微信账号" prop="anchor_wechat">
<div>
<el-input v-model="form.model.anchor_wechat" placeholder="请输入主播微信账号"></el-input>
<div class="desc">
每个直播间需要绑定一个用作核实主播身份,不会展示给观众。<br />
主播微信号,如果未实名认证,需要先前往“小程序直播”小程序进行实名验证。
</div>
<el-popover :width="180" trigger="click">
<template #reference>
<el-button class="is-link" type="primary">小程序认证</el-button>
</template>
<img class="qrcode-img" src="/assets/addons/shopro/img/live-qrcode.png" />
</el-popover>
</div>
</el-form-item>
<el-form-item label="主播副号" prop="sub_anchor_wechat">
<el-input v-model="form.model.sub_anchor_wechat" placeholder="请输入主播副号"></el-input>
</el-form-item>
<el-form-item label="官方收录">
<div>
<el-switch v-model="form.model.is_feeds_public" :active-value="1"
:inactive-value="0"></el-switch>
<div class="desc">
开启后本场直播将有可能被官方推荐。<br />
此项设置在直播间创建完成后可以在控制台内修改。
</div>
</div>
</el-form-item>
<el-form-item label="允许点赞">
<el-radio-group v-model="form.model.close_like">
<el-radio :label="0">开启</el-radio>
<el-radio :label="1">关闭</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="展示商品货架">
<el-radio-group v-model="form.model.close_goods">
<el-radio :label="0">开启</el-radio>
<el-radio :label="1">关闭</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="允许评论">
<el-radio-group v-model="form.model.close_comment">
<el-radio :label="0">开启</el-radio>
<el-radio :label="1">关闭</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="允许回放">
<el-radio-group v-model="form.model.close_replay">
<el-radio :label="0">开启</el-radio>
<el-radio :label="1">关闭</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="打开客服">
<el-radio-group v-model="form.model.close_kf">
<el-radio :label="0">开启</el-radio>
<el-radio :label="1">关闭</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>
</div>

View File

@@ -0,0 +1,68 @@
{include file="/shopro/common/script" /}
<style>
.program {
width: 360px;
height: 260px;
background: #f5f5f5;
border-radius: 4px;
}
.path {
width: 360px;
height: 260px;
background: #f5f5f5;
border-radius: 4px;
}
.title {
font-size: 14px;
line-height: 20px;
color: var(--sa-subtitle);
}
.desc {
color: var(--sa-subfont);
font-size: 14px;
line-height: 20px;
word-break: break-all;
word-wrap: break-word;
}
</style>
<div id="playback" class="mplive-index panel panel-default panel-intro" v-cloak>
<el-container class="panel-block">
<!-- v-loading="loading" -->
<el-main class="sa-p-0">
<el-table :data="table.data" class="sa-table" stripe>
<template #empty>
<sa-empty />
</template>
<el-table-column label="回放片段" min-width="140">
<template #default="scope">
<div class="sa-table-line-1">{{ '片段' + scope.row.index || '-' }}</div>
</template>
</el-table-column>
<el-table-column label="创建时间" min-width="140">
<template #default="scope">
<div class="sa-table-line-1">{{
dayjs(scope.row.create_time).format('YYYY-MM-DD HH:mm:ss') || '-'
}}</div>
</template>
</el-table-column>
<el-table-column label="过期时间" min-width="140">
<template #default="scope">
<div class="sa-table-line-1">{{
dayjs(scope.row.expire_time).format('YYYY-MM-DD HH:mm:ss') || '-'
}}</div>
</template>
</el-table-column>
<el-table-column fixed="right" label="操作" min-width="120">
<template #default="scope">
<el-button class="is-link" type="primary" @click="play(scope.row.media_url)">播放</el-button>
</template>
</el-table-column>
</el-table>
</el-main>
</el-container>
</div>

View File

@@ -0,0 +1,61 @@
{include file="/shopro/common/script" /}
<style>
.title {
font-size: 16px;
line-height: 24px;
color: var(--sa-title);
margin-bottom: 16px;
}
.sa-m-b-4 {
margin-bottom: 4px;
}
.sa-m-r-4 {
margin-bottom: 4px;
}
.sa-m-b-16 {
margin-bottom: 16px;
}
.sa-m-b-40 {
margin-bottom: 40px;
}
.desc {
font-size: 14px;
line-height: 20px;
color: var(--sa-subtitle);
word-break: break-all;
word-wrap: break-word;
}
.subtitle {
color: var(--sa-subfont);
font-size: 14px;
line-height: 20px;
}
</style>
<div id="pushUrl" class="mplive-index panel panel-default panel-intro" v-cloak>
<el-container class="panel-block">
<!-- v-loading="loading" -->
<el-main class="sa-p-0">
<div class="title">推流地址</div>
<div class="sa-flex copy-box sa-m-b-4">
<div class="desc sa-m-r-4">在第三方推流应用中,以下地址进行推流</div>
<el-button class="is-link sa-m-b-4" type="primary" @click="onClipboard(state.pushUrl)">复制链接</el-button>
</div>
<div class="desc sa-m-b-16">{{ state.pushUrl }}</div>
<div class="subtitle sa-m-b-40">此地址为当前直播间唯一推流地址,不要泄露给第三方。</div>
<div class="title sa-m-b-16">备注</div>
<div class="desc sa-m-b-4">服务器地址:{{ state.serverAddress }}</div>
<div class="desc sa-m-b-16">串流密钥:{{ state.key }}</div>
<div class="sa-flex">
<div class="subtitle sa-m-r-4">推流直播操作详见</div>
<el-button class="is-link sa-m-b-4" type="primary" @click="onJump">指引</el-button>
</div>
</el-main>
</el-container>
</div>

View File

@@ -0,0 +1,64 @@
{include file="/shopro/common/script" /}
<style>
.program {
width: 360px;
height: 260px;
background: #f5f5f5;
border-radius: 4px;
padding: 16px;
margin-bottom: 30px;
}
.path {
width: 360px;
height: 260px;
background: #f5f5f5;
border-radius: 4px;
padding: 16px;
margin-bottom: 30px;
}
.title {
font-size: 14px;
line-height: 20px;
color: var(--sa-subtitle);
margin-bottom: 8px;
}
.desc {
color: var(--sa-subfont);
font-size: 14px;
line-height: 20px;
word-break: break-all;
word-wrap: break-word;
margin-bottom: 24px;
}
</style>
<div id="qrcode" class="mplive-index panel panel-default panel-intro" v-cloak>
<el-container class="panel-block">
<!-- v-loading="loading" -->
<el-main >
<div class="sa-flex sa-flex-wrap sa-row-between">
<div class="program sa-flex sa-col-top sa-row-between">
<div>
<div class="title">直播间小程序码</div>
<div class="desc ">小程序码不带参数</div>
<el-button type="primary" @click="saveImg">保存图片</el-button>
</div>
<sa-image class="" :url="state.cdnUrl" size="120"></sa-image>
</div>
<div class="path">
<div class="title">直播间页面路径</div>
<div class="desc ">{{ state.path }}</div>
<el-button type="primary" @click="onClipboard(state.path)">复制链接</el-button>
<div class="desc">链接是直播间原始页面路径,如需加入参数,详见<el-button class="is-link" type="primary"
@click="onJump">使用方法</el-button></div>
</div>
</div>
</el-main>
</el-container>
</div>

View File

@@ -0,0 +1,79 @@
{include file="/shopro/common/script" /}
<div id="select" class="room-select" v-cloak>
<el-container class="panel-block">
<el-main>
<el-table height="100%" class="sa-table" :data="state.data" stripe @selection-change="onSelectionChange">
<el-table-column type="selection" :selectable="isSelectable" width="48"></el-table-column>
<el-table-column label="房间ID" min-width="120" align="center">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.roomid }}</div>
</template>
</el-table-column>
<el-table-column label="直播类型" min-width="120" align="center">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.type_text }}</div>
</template>
</el-table-column>
<el-table-column label="直播间标题" min-width="200" align="center">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.name }}</div>
</template>
</el-table-column>
<el-table-column label="主播昵称" min-width="120" align="center">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.anchor_name }}</div>
</template>
</el-table-column>
<el-table-column label="状态" min-width="120" align="center">
<template #default="scope">
<div class="sa-table-line-1" :class="
scope.row.status === 101
? 'sa-color--success'
: scope.row.status === 102
? 'sa-color--warning'
: scope.row.status === 105
? 'sa-color--info'
: 'sa-color--danger'
">{{ scope.row.status_text }}</div>
</template>
</el-table-column>
<el-table-column label="背景图" min-width="80" align="center">
<template #default="scope">
<div class="sa-flex sa-row-center">
<sa-image :url="scope.row.cover_img" size="30">
</sa-image>
</div>
</template>
</el-table-column>
<el-table-column label="分享图" min-width="80" align="center">
<template #default="scope">
<div class="sa-flex sa-row-center">
<sa-image :url="scope.row.share_img" size="30"></sa-image>
</div>
</template>
</el-table-column>
<el-table-column label="封面图" min-width="80" align="center">
<template #default="scope">
<div class="sa-flex sa-row-center">
<sa-image :url="scope.row.feeds_img" size="30"></sa-image>
</div>
</template>
</el-table-column>
<el-table-column label="开播时间" width="172">
<template #default="scope">
{{Moment(scope.row.start_time * 1000).format('YYYY-MM-DD HH:mm')}}
</template>
</el-table-column>
<el-table-column label="结束时间" width="172">
<template #default="scope">
{{Moment(scope.row.end_time * 1000).format('YYYY-MM-DD HH:mm')}}
</template>
</el-table-column>
</el-table>
</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,102 @@
{include file="/shopro/common/script" /}
<style>
.score-shop-form .title {
line-height: 22px;
font-size: 14px;
font-weight: 400;
color: var(--sa-subtitle);
}
.score-shop-form .sku-table-wrap {
width: 100%;
overflow: auto;
}
.score-shop-form .sku-table-wrap .sku-table {
font-size: 12px;
font-weight: 500;
}
.score-shop-form .sku-table-wrap .sku-table thead {
line-height: 40px;
background: var(--sa-table-header-bg);
color: var(--subtitle);
}
.score-shop-form .sku-table-wrap .sku-table tbody tr {
line-height: 48px;
color: var(--sa-font);
}
.score-shop-form .sku-table-wrap .sku-table tbody tr:nth-of-type(2n) {
background: var(--sa-table-striped);
}
.score-shop-form .sku-table-wrap .sku-table th,
.score-shop-form .sku-table-wrap .sku-table td {
padding: 0 16px;
text-align: left;
}
.score-shop-form .sku-table-wrap .sku-item {
min-width: 100px;
flex-shrink: 0;
}
</style>
<div id="addEdit" class="score-shop-form" v-cloak>
<el-container class="panel-block">
<el-main>
<el-scrollbar height="100%">
<div class="title mb-4">商品名称:{{ state.title }}</div>
<div class="sku-table-wrap">
<table class="sku-table" rules="none">
<thead>
<tr>
<th class="sku-item" v-for="ss in goods.skus" :key="ss">
{{ ss.name }}
</th>
<th class="sku-item">是否参与</th>
<th class="sku-item">商品价格</th>
<th class="sku-item">可兑换数量</th>
<th class="sku-item">兑换积分</th>
<th class="sku-item">兑换价格</th>
</tr>
</thead>
<tbody>
<tr v-for="(sp, spindex) in goods.sku_prices" :key="sp">
<td class="sku-item" v-for="st in sp.goods_sku_text" :key="st">
{{ st }}
</td>
<td class="sku-item">
<el-switch v-model="goods.score_sku_prices[spindex].status" active-value="up"
inactive-value="down" />
</td>
<td class="sku-item">{{ sp.price }}</td>
<th class="sku-item">
<el-input v-if="goods.score_sku_prices[spindex].status == 'up'" type="number"
v-model="goods.score_sku_prices[spindex].stock"></el-input>
</th>
<th class="sku-item">
<el-input v-if="goods.score_sku_prices[spindex].status == 'up'" type="number"
v-model="goods.score_sku_prices[spindex].score"></el-input>
</th>
<th class="sku-item">
<el-input v-if="goods.score_sku_prices[spindex].status == 'up'" type="number"
v-model="goods.score_sku_prices[spindex].price"></el-input>
</th>
</tr>
</tbody>
</table>
</div>
</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,159 @@
{include file="/shopro/common/script" /}
<style>
.score-shop-index .sa-table-wrap {
height: 100%;
margin-left: -48px;
overflow: hidden;
}
.score-shop-index .sa-table-wrap .sa-expand-table .el-table__header-wrapper {
display: none;
}
.score-shop-index .goods-item .sa-image {
margin-right: 12px;
}
.score-shop-index .goods-item .goods-title {
height: 20px;
line-height: 20px;
font-size: 14px;
font-weight: 500;
color: var(--sa-font);
}
.score-shop-index .goods-item .goods-subtitle {
height: 16px;
line-height: 16px;
font-size: 12px;
font-weight: 400;
color: var(--sa-subfont);
margin-bottom: 6px;
}
.score-shop-index .goods-item .goods-sku {
width: fit-content;
height: 20px;
background: var(--el-color-primary);
border-radius: 10px;
display: flex;
align-items: center;
padding: 0 8px;
font-size: 12px;
color: #fff;
cursor: pointer;
}
.score-shop-index .sku-text {
font-size: 12px;
color: var(--sa-font);
}
</style>
<div id="index" class="score-shop-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/app/score_shop/add')}
<el-button icon="Plus" type="primary" @click="onAdd">添加</el-button>
{/if}
{if $auth->check('shopro/app/score_shop/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" :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="skuPrices.data" stripe>
<el-table-column width="48"></el-table-column>
<el-table-column min-width="90"></el-table-column>
<el-table-column min-width="440">
<template #default="scope">
<div class="sa-flex">
<sa-image :url="scope.row.image || props.row.image" size="32">
</sa-image>
<div class="sku-text ml-2">
{{ scope.row.goods_sku_text?.join('/') }}
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="score_price" min-width="200"></el-table-column>
<el-table-column prop="sales" min-width="100"></el-table-column>
<el-table-column prop="stock" min-width="100"></el-table-column>
<el-table-column min-width="120"></el-table-column>
</el-table>
</template>
</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="goods-item sa-flex">
<sa-image :url="scope.row.image" size="64"></sa-image>
<div>
<div class="goods-title sa-table-line-1">{{scope.row.title}}</div>
<div class="goods-subtitle sa-table-line-1">{{scope.row.subtitle}}</div>
<div v-if="scope.row.is_sku" class="goods-sku"
@click.stop="expandRow(scope.row.id)">
多规格
<el-icon :class="[
'expand-arrow ml-1',
expandRowKeys.includes(scope.row.id) ? 'expand-arrow-up' : 'expand-arrow-down',
]">
<arrow-down />
</el-icon>
</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="积分现金" min-width="200">
<template #default="scope">
<div v-if="scope.row.score_price" class="sa-flex">
{{ scope.row.score_price.score }}积分
<div v-if="Number(scope.row.score_price.price)">+¥{{ scope.row.score_price.price }}
</div>
</div>
<div v-else>-</div>
</template>
</el-table-column>
<el-table-column prop="score_sales" label="销量" min-width="100"></el-table-column>
<el-table-column prop="score_stock" label="库存" min-width="100"></el-table-column>
<el-table-column label="操作" min-width="120" fixed="right">
<template #default="scope">
{if $auth->check('shopro/app/score_shop/edit')}
<el-button type="primary" link @click="onEdit(scope.row)">编辑</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/app/score_shop/delete')}
<el-button type="danger" link>删除</el-button>
{/if}
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</div>
</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="score-shop-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/app/score_shop/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/app/score_shop/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/app/score_shop/restore')}
<el-button type="primary" :disabled="!batchHandle.data.length" @click="onBatchHandle('restore')">还原
</el-button>
{/if}
{if $auth->check('shopro/app/score_shop/destroy')}
<el-button type="danger" :disabled="!batchHandle.data.length" @click="onBatchHandle('destroy')">销毁
</el-button>
{/if}
{if $auth->check('shopro/app/score_shop/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,68 @@
{include file="/shopro/common/script" /}
<style>
.score-shop-select .goods-item .goods-image {
margin-right: 12px;
}
.score-shop-select .goods-item .goods-title {
height: 20px;
line-height: 20px;
font-size: 14px;
font-weight: 500;
color: var(--sa-font);
}
.score-shop-select .goods-item .goods-subtitle {
height: 16px;
line-height: 16px;
font-size: 12px;
font-weight: 400;
color: var(--sa-subfont);
margin-bottom: 6px;
}
</style>
<div id="select" class="score-shop-select" v-cloak>
<el-container class="panel-block">
<el-main>
<el-table height="100%" class="sa-table" :data="state.data" stripe @selection-change="onChangeSelection">
<el-table-column v-if="state.multiple" type="selection" width="48"></el-table-column>
<el-table-column prop="id" label="ID" min-width="80"></el-table-column>
<el-table-column label="商品信息" min-width="440">
<template #default="scope">
<div class="goods-item sa-flex">
<sa-image :url="scope.row.image" size="64"></sa-image>
<div>
<div class="goods-title sa-table-line-1">{{scope.row.title}}</div>
<div class="goods-subtitle sa-table-line-1">{{scope.row.subtitle}}</div>
<div v-if="scope.row.is_sku">
多规格
</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="积分现金" min-width="200">
<template #default="scope">
<div class="sa-flex">
{{ scope.row.score_price.score }}积分
<div v-if="Number(scope.row.score_price.price)">+¥{{ scope.row.score_price.price }}</div>
</div>
</template>
</el-table-column>
<el-table-column prop="score_sales" label="销量" min-width="100"></el-table-column>
<el-table-column prop="score_stock" label="库存" min-width="100"></el-table-column>
<el-table-column v-if="!state.multiple" label="操作" width="80">
<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-footer--submit 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>

View File

@@ -0,0 +1,264 @@
{include file="/shopro/common/script" /}
<style>
.category-form .style-item {
margin-right: 24px;
cursor: pointer;
}
.category-form .style-item:last-of-type {
margin-right: 0;
}
.category-form .style-item .top {
width: 78px;
height: 124px;
border-radius: 4px;
position: relative;
margin-bottom: 8px;
}
.category-form .style-item .top.is-active {
border: 1px solid var(--el-color-primary);
}
.category-form .style-item .top img {
width: 100%;
height: 100%;
border-radius: 4px;
}
.category-form .style-item .top .el-icon {
font-size: 14px;
color: var(--el-color-primary);
position: absolute;
top: -7px;
right: -7px;
display: none;
}
.category-form .style-item .top.is-active .el-icon {
display: block;
}
.category-form .style-item .style-title {
font-size: 12px;
line-height: 14px;
color: var(--sa-font);
}
.category-form .title {
width: 100%;
height: 40px;
background: var(--sa-table-header-bg);
padding: 0 16px;
color: var(--sa-subtitle);
font-size: 14px;
font-weight: 500;
}
.category-form .template-wrap {
overflow: auto;
}
.category-form .template-wrap .template-header {
width: 100%;
background: var(--sa-table-header-bg);
}
.category-form .template-wrap .template-item {
flex-shrink: 0;
height: 56px;
padding: 0 16px;
font-weight: 500;
font-size: 12px;
display: flex;
align-items: center;
}
.category-form .template-header .template-item {
height: 40px;
background: var(--sa-table-header-bg);
}
.category-form .template-wrap .el-tree {
flex: 1;
}
.category-form .template-wrap .el-tree-node__expand-icon {
display: none;
}
.category-form .template-wrap .el-tree-node__content {
height: unset;
}
.category-form .template-item.id {
width: 90px;
}
.category-form .template-item.input {
width: 380px;
}
.category-form .template-item.image {
width: 80px;
}
.category-form .template-item.description {
width: 240px;
}
.category-form .template-item.weigh {
width: 120px;
}
.category-form .template-item.oper {
width: 104px;
}
.category-form .append-title {
margin-left: 12px;
}
.style-popover img {
width: 220px;
height: 350px;
}
</style>
<div id="addEdit" class="category-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="分类类型">
<el-radio-group v-model="state.level" :disabled="state.type=='edit'" @change="onChangeLevel">
<el-radio :label="1">一级分类</el-radio>
<el-radio :label="2">二级分类</el-radio>
<el-radio :label="3">三级分类</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="分类样式">
<div class="style-item" v-for="(item, index) in state.styleList[state.level]" :key="index"
@click="form.model.style = item.type">
<div class="top" :class="form.model.style == item.type ? 'is-active' : ''">
<img :src="`/assets/addons/shopro/img/category/${item.type}.png`" />
<el-icon>
<circle-check-filled />
</el-icon>
</div>
<div class="sa-flex sa-row-center">
<div class="style-title">样式{{ item.name }}</div>
<el-popover popper-class="style-popover sa-popper" placement="right" trigger="hover">
<img :src="`/assets/addons/shopro/img/category/${item.type}.png`" />
<template #reference>
<el-icon class="warning">
<warning />
</el-icon>
</template>
</el-popover>
</div>
</div>
</el-form-item>
<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="分类权重">
<el-input class="sa-w-360" v-model="form.model.weigh" type="number" :min="0"
placeholder="请输入分类权重"></el-input>
</el-form-item>
<div class="title sa-flex sa-row-between">
<div>分类数据</div>
<el-button v-if="state.level" type="primary" link @click="onAdd">+ 插入一级分类</el-button>
</div>
<div class="template-wrap">
<div class="template-header sa-flex">
<div v-if="state.type == 'edit'" class="template-item id"> ID </div>
<div class="template-item input">分类名称</div>
<div class="template-item image sa-flex sa-row-center"> 分类图片 </div>
<div class="template-item description">描述</div>
<div class="template-item weigh">
<el-popover placement="bottom" title="" width="120" trigger="hover">
<template #reference> 排序 </template>
<div class="popover-container">
权重以倒序排列默认值为0相同权重则以ID优先
</div>
</el-popover>
</div>
<div class="template-item oper">操作</div>
</div>
<div class="sa-flex">
<el-tree :data="state.treeData" node-key="id" default-expand-all
:expand-on-click-node="false" :props="defaultProps" :indent="0">
<template #default="{ node, data }">
<div v-if="!(data.deleted && data.deleted == 1)" class="sa-flex">
<div v-if="state.type == 'edit'" class="template-item id">
<span
v-if="(data.id + '').indexOf('add') == -1 && (data.id + '').substring(0, 3) !== 'new'">{{
data.id }}</span>
</div>
<div class="template-item input sa-flex"
:style="{'padding-left':`${node.level*16}px`}">
<div class="expanded-icon sa-flex">
<div v-if="data.children && data.children.length > 0">
<el-icon v-if="node.expanded"
@click="node.expanded = !node.expanded">
<semi-select />
</el-icon>
<el-icon v-if="!node.expanded"
@click="node.expanded = !node.expanded">
<plus />
</el-icon>
</div>
</div>
<div style="margin-left: 16px">
<el-input v-model="data.name" placeholder="请输入分类名称" />
</div>
<el-button v-if="node.level == 1 && state.level != 1" class="append-title"
type="primary" link @click="onAppend(data)">
+ 插入二级分类
</el-button>
<el-button v-if="node.level == 2 && state.level == 3" class="append-title"
type="primary" link @click="onAppend(data)">
+ 插入三级分类
</el-button>
</div>
<div class="template-item image sa-flex sa-row-center">
<el-popover popper-class="sa-popper" trigger="hover"
content="建议尺寸缩略图150X150">
<template #reference>
<sa-uploader v-model="data.image" size="32">
</sa-uploader>
</template>
</el-popover>
</div>
<div class="template-item description">
<el-input v-model="data.description" placeholder="请输入分类描述" />
</div>
<div class="template-item weigh">
<el-input v-model="data.weigh" type="number" :min="0" placeholder="请输入排序" />
</div>
<div class="template-item oper">
<el-button :type="data.status == 'normal'?'info':'success'" link
@click="data.status == 'normal'?data.status = 'hidden':data.status = 'normal'">
{{data.status == 'normal'?'隐藏':'显示'}}
</el-button>
<el-button type="danger" link @click="onRemove(node, data)">删除</el-button>
</div>
</div>
</template>
</el-tree>
</div>
</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,75 @@
{include file="/shopro/common/script" /}
<style>
.category-index .style {
width: 32px;
height: 32px;
}
.style-popover img {
width: 220px;
height: 350px;
}
</style>
<div id="index" class="category-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/category/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>
<el-table-column prop="id" label="ID" min-width="90"> </el-table-column>
<el-table-column prop="name" 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="style" label="分类样式" min-width="100">
<template #default="scope">
<el-popover popper-class="style-popover sa-popper" placement="right-start" trigger="hover">
<img :src="`/assets/addons/shopro/img/category/${scope.row.style}.png`" />
<template #reference>
<img class="style" :src="`/assets/addons/shopro/img/category/${scope.row.style}.png`" />
</template>
</el-popover>
</template>
</el-table-column>
<el-table-column prop="weigh" label="权重" min-width="100">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.weigh || '0' }}</div>
</template>
</el-table-column>
<el-table-column fixed="right" label="操作" min-width="120">
<template #default="scope">
{if $auth->check('shopro/category/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/category/delete')}
<el-button type="danger" link>删除</el-button>
{/if}
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</el-main>
</el-container>
<sa-filter v-model="state.filter" @filter-change="onChangeFilter"></sa-filter>
</div>

View File

@@ -0,0 +1,21 @@
{include file="/shopro/common/script" /}
<div id="select" class="category-select" v-cloak>
<el-container class="panel-block">
<el-main>
<el-scrollbar height="100%">
<el-cascader-panel ref="categoryRef" v-model="state.selectedIds" :options="state.data" :props="{
multiple: state.multiple,
checkStrictly: true,
emitPath: false,
label: 'name',
value: 'id',
}">
</el-cascader-panel>
</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,42 @@
{include file="/shopro/common/script" /}
<div id="addEdit" class="common-word-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="room_id">
<el-cascader v-model="form.model.room_id" :options="chat.config.default_rooms" :props="{
label: 'name',
value: 'value',
checkStrictly: true,
emitPath: false,
}" clearable placeholder="请选择客服分类">
</el-cascader>
</el-form-item>
<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="content">
<form role="form">
<textarea id="commonWordContent" class="editor"></textarea>
</form>
</el-form-item>
<el-form-item label="权重">
<el-input class="sa-w-360" v-model="form.model.weigh" placeholder="请输入权重" type="number">
</el-input>
</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>
</div>

View File

@@ -0,0 +1,97 @@
{include file="/shopro/common/script" /}
<div id="index" class="common-word-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/chat/common_word/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"></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 label="客服分类" min-width="100">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.room_name || '-' }}
</div>
</template>
</el-table-column>
<el-table-column label="状态" min-width="70">
<template #default="scope">
<el-tag :type="scope.row.status == 'normal' ? 'success' : 'info'">
{{ scope.row.status_text }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="权重" min-width="88">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.weigh || 0 }}</div>
</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/chat/common_word/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/chat/common_word/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/chat/common_word/delete')}
<el-button type="danger" :disabled="!batchHandle.data.length" @click="onBatchHandle('delete')">删除
</el-button>
{/if}
{if $auth->check('shopro/chat/common_word/edit')}
<el-button type="success" :disabled="!batchHandle.data.length" @click="onBatchHandle('normal')">正常
</el-button>
{/if}
{if $auth->check('shopro/chat/common_word/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,42 @@
{include file="/shopro/common/script" /}
<div id="addEdit" class="customer-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="120px">
<el-form-item label="客服分类" prop="room_id">
<el-cascader class="sa-w-360" v-model="form.model.room_id" :options="chat.config.default_rooms" :props="{
label: 'name',
value: 'value',
checkStrictly: true,
emitPath: false,
}" clearable placeholder="请选择客服分类" @change="getCustomerServiceSelect">
</el-cascader>
</el-form-item>
<el-form-item v-if="form.model.room_id" label="所属管理员" prop="auth_id">
<el-cascader class="sa-w-360" v-model="form.model.auth_id" :options="customerService.select" :props="{
label: 'nickname',
value: 'id',
checkStrictly: true,
emitPath: false,
}" clearable placeholder="请选择所属管理员">
</el-cascader>
</el-form-item>
<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="avatar">
<sa-uploader v-model="form.model.avatar"></sa-uploader>
</el-form-item>
<el-form-item label="最优接待人数">
<el-input class="sa-w-360" v-model="form.model.max_num" placeholder="请输入最优接待人数" type="number"></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,108 @@
{include file="/shopro/common/script" /}
<div id="index" class="customer-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>
<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/chat/customer_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"></el-table-column>
<el-table-column prop="id" label="ID" min-width="90" sortable="custom"> </el-table-column>
<el-table-column label="客服名称" min-width="180">
<template #default="scope">
<div class="sa-flex">
<el-avatar class="mr-2" :size="32" :src="Fast.api.cdnurl(scope.row.avatar)">
<img src="/assets/addons/shopro/img/default-avatar.png" />
</el-avatar>
<div class="sa-table-line-1">
{{ scope.row.name || '-' }}
</div>
</div>
</template>
</el-table-column>
<el-table-column label="所属管理员" min-width="100">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.auth_model?.username || '-' }}
</div>
</template>
</el-table-column>
<el-table-column label="客服分类" min-width="100">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.room_name || '-' }}
</div>
</template>
</el-table-column>
<el-table-column label="最优接待人数" min-width="120">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.max_num || 0 }}
</div>
</template>
</el-table-column>
<el-table-column label="状态" min-width="70">
<template #default="scope">
<el-tag :type="scope.row.status == 'online' ? 'success' : 'info'">
{{ scope.row.status_text }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="上次服务时间" width="172">
<template #default="scope">
{{ scope.row.last_time || '-' }}
</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/chat/customer_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/chat/customer_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/chat/customer_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>
<sa-filter v-model="state.filter" @filter-change="onChangeFilter"></sa-filter>
</div>

View File

@@ -0,0 +1,42 @@
{include file="/shopro/common/script" /}
<div id="addEdit" class="question-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="room_id">
<el-cascader v-model="form.model.room_id" :options="chat.config.default_rooms" :props="{
label: 'name',
value: 'value',
checkStrictly: true,
emitPath: false,
}" clearable placeholder="请选择客服分类">
</el-cascader>
</el-form-item>
<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="问题内容" prop="content">
<form role="form">
<textarea id="questionContent" class="editor"></textarea>
</form>
</el-form-item>
<el-form-item label="权重">
<el-input class="sa-w-360" v-model="form.model.weigh" placeholder="请输入权重" type="number">
</el-input>
</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>
</div>

View File

@@ -0,0 +1,97 @@
{include file="/shopro/common/script" /}
<div id="index" class="question-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/chat/question/add')}
<el-button icon="Plus" type="primary" @click="onAdd">添加</el-button>
{/if}
</div>
</div>
</el-header>
<el-main class="sa-main">
<el-table class="sa-table" height="100%" :data="state.data" stripe @selection-change="onChangeSelection"
@sort-change="onChangeSort">
<el-table-column type="selection" width="48"></el-table-column>
<el-table-column sortable="custom" prop="id" label="ID" min-width="90"> </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 label="客服分类" min-width="100">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.room_name || '-' }}
</div>
</template>
</el-table-column>
<el-table-column label="状态" min-width="70">
<template #default="scope">
<el-tag :type="scope.row.status == 'normal' ? 'success' : 'info'">
{{ scope.row.status_text }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="权重" min-width="88">
<template #default="scope">
<div class="sa-table-line-1">{{ scope.row.weigh || 0 }}</div>
</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/chat/question/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/chat/question/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/chat/question/delete')}
<el-button type="danger" :disabled="!batchHandle.data.length" @click="onBatchHandle('delete')">删除
</el-button>
{/if}
{if $auth->check('shopro/chat/question/edit')}
<el-button type="success" :disabled="!batchHandle.data.length" @click="onBatchHandle('normal')">正常
</el-button>
{/if}
{if $auth->check('shopro/chat/question/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,197 @@
{include file="/shopro/common/script" /}
<style>
.record-index .sa-title {
border-bottom: 1px solid var(--sa-table-header-bg);
}
.record-index .el-scrollbar {
padding: 20px;
}
.record-index .record-index-main {
--el-main-padding: 0;
}
.record-index .record-item {
margin-bottom: 20px;
align-items: flex-start;
}
.record-index .loading-status {
color: var(--el-color-info);
}
.record-index .center {
flex: 1;
display: flex;
flex-direction: column;
}
.record-index .record-item.sa-row-right .center {
align-items: flex-end;
}
.record-index .record-item.sa-row-left .center {
align-items: flex-start;
}
.record-index .record-message {
max-width: 50%;
padding: 8px;
font-size: 14px;
color: var(--sa-font);
white-space: normal;
word-break: break-all;
word-wrap: break-word;
}
.record-index .message-date {
color: var(--sa-subfont);
font-size: 12px;
}
.record-index .record-item.sa-row-right .record-message {
background: var(--t-bg-active);
border-radius: 4px 4px 0 4px;
}
.record-index .record-item.sa-row-left .record-message {
background: var(--sa-table-header-bg);
border-radius: 4px 4px 4px 0;
}
.record-index .record-emoji {
width: 24px;
height: 24px;
margin-right: 4px;
}
.record-index .record-emoji:last-of-type {
margin-right: 0;
}
.record-index img {
width: 100% !important;
}
.record-index .goods-item .goods-price {
color: var(--el-color-danger);
}
.record-index .order-sn {
font-size: 12px;
color: var(--el-color-primary);
}
.record-index .order-goods {
padding: 8px;
background: var(--sa-background-assist);
border-radius: 4px;
}
</style>
<div id="index" class="record-index" v-cloak>
<el-container class="panel-block">
<el-header>
<div class="sa-title sa-flex sa-row-between">
<div>{{ state.nickname }}</div>
<el-dropdown trigger="click" @command="onCommand">
<el-button class="sa-flex" link>
<div class="mr-2">{{ state.room_name }}</div>
<el-icon>
<arrow-down />
</el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item v-for="item in chat.config.default_rooms" :command="item.value">
{{ item.name }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</el-header>
<el-main class="record-index-main">
<el-scrollbar height="100%">
<div class="loading-status sa-flex sa-row-center mb-2">
<button link v-show="state.data.length && pagination.lastPage > 1" @click="onLoadMore">
{{loadingMap[pagination.loadStatus].title}}
</button>
</div>
<template v-for="(item,index) in state.data">
<div class="sa-flex sa-row-center">
<div v-if="item.sender_identify == 'system'" class="message-system mb-4">
{{ item.content.text }}
</div>
<div v-if="showTime(item, index)" class="message-date mb-4">
{{ formatTime(item.createtime) }}
</div>
</div>
<div class="record-item sa-flex" :class="[
item.sender_identify == 'customer_service'
? 'sa-row-right'
: item.sender_identify == 'customer'
? 'sa-row-left'
: '',
]">
<el-avatar v-if="item.sender_identify == 'customer'" class="mr-2" :size="40"
:src="Fast.api.cdnurl(item.sender?.avatar)">
<img src="/assets/addons/shopro/img/default-avatar.png" />
</el-avatar>
<div class="center">
<div class="mb-1">{{item.sender?.nickname || item.sender?.name || item.sender_id}}</div>
<div class="record-message">
<!-- 文本 -->
<template v-if="item.message_type=='text'">
<div v-html="replaceEmoji(item.message)"></div>
</template>
<!-- 图片 -->
<template v-if="item.message_type=='image'">
<img :src="Fast.api.cdnurl(item.message)" />
</template>
<!-- 商品 -->
<template v-if="item.message_type=='goods'">
<div class="goods-item sa-flex">
<sa-image class="mr-2" :url="item.message.image" size="40"></sa-image>
<div>
<div class="sa-table-line-1">{{item.message.title}}</div>
<div class="goods-price">¥{{item.message.price.join(',')}}</div>
</div>
</div>
</template>
<!-- 订单 -->
<template v-if="item.message_type=='order'">
<div class="order-item">
<div class="order-sn mb-2">{{item.message.order_sn}}</div>
<div class="order-goods sa-flex">
<sa-image class="mr-2" :url="item.message.items[0]?.image" size="40">
</sa-image>
<div>
<div class="sa-table-line-1">{{item.message.items[0]?.goods_title}}
</div>
<div class="sa-flex sa-row-between">
<div class="order-goods-price">共{{item.message.items.length}}件商品
</div>
<div class="order-goods-total">合计 ¥{{item.message.pay_fee}}</div>
</div>
</div>
</div>
</div>
</template>
</div>
</div>
<el-avatar v-if="item.sender_identify== 'customer_service'" class="ml-2" :size="40"
:src="Fast.api.cdnurl(item.sender?.avatar)">
<img src="/assets/addons/shopro/img/default-avatar.png" />
</el-avatar>
</div>
</template>
</el-scrollbar>
</el-main>
</el-container>
</div>

View File

@@ -0,0 +1,109 @@
{include file="/shopro/common/script" /}
<style>
.user-index .auth-id {
color: var(--sa-subfont);
}
</style>
<div id="index" class="user-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 @selection-change="onChangeSelection"
@sort-change="onChangeSort">
<el-table-column type="selection" width="48"></el-table-column>
<el-table-column prop="id" label="ID" min-width="90" sortable="custom"> </el-table-column>
<el-table-column label="用户信息" min-width="160">
<template #default="scope">
<div class="sa-flex sa-col-center">
<el-avatar class="mr-2" :size="32" :src="Fast.api.cdnurl(scope.row.avatar)">
<img src="/assets/addons/shopro/img/default-avatar.png" />
</el-avatar>
<div>
<div class="sa-table-line-1">
{{ scope.row.nickname || '-' }}
</div>
<div class="auth-id">
{{ scope.row.auth_id ? '用户' : '游客' }}
</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="手机号" min-width="120">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.user?.mobile || '-' }}
</div>
</template>
</el-table-column>
<el-table-column label="最后会话客服" min-width="160">
<template #default="scope">
<div v-if="scope.row.customer_service" class="sa-flex sa-col-center">
<el-avatar class="mr-2" :size="32"
:src="Fast.api.cdnurl(scope.row.customer_service.avatar)">
<img src="/assets/addons/shopro/img/default-avatar.png" />
</el-avatar>
<div>
<div class="sa-table-line-1">
{{ scope.row.customer_service.name || '-' }}
</div>
<div class="auth-id">
{{ scope.row.customer_service.room_name }}
</div>
</div>
</div>
<div v-else>{{scope.row.customer_service_id}}</div>
</template>
</el-table-column>
<el-table-column label="最后会话时间" width="172">
<template #default="scope">
{{ scope.row.last_time || '-' }}
</template>
</el-table-column>
<el-table-column fixed="right" label="操作" min-width="120">
<template #default="scope">
{if $auth->check('shopro/chat/record/index')}
<el-button type="primary" link @click="onRecord(scope.row)">查看</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/chat/user/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/chat/user/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>
<sa-filter v-model="state.filter" @filter-change="onChangeFilter"></sa-filter>
</div>

View File

@@ -0,0 +1,601 @@
{include file="/shopro/common/script" /}
<style>
.agent-detail .agent-detail-scrollbar>.el-scrollbar__wrap {
overflow-x: hidden;
}
.agent-detail .agent-detail-scrollbar>.el-scrollbar__bar.is-horizontal {
display: none;
}
.agent-detail .agent-content {
height: 450px;
line-height: 1;
padding: 20px;
background: var(--sa-table-header-bg);
border-radius: 8px;
margin: 0 0 20px;
}
.agent-detail .user-content .refresh {
line-height: 16px;
font-size: 12px;
font-weight: 400;
color: var(--sa-font);
cursor: pointer;
}
.agent-detail .user-content .refresh .el-icon {
font-size: 16px;
margin-right: 4px;
}
.agent-detail .user-content .nickname {
line-height: 22px;
font-size: 16px;
font-weight: 500;
color: var(--sa-subtitle);
}
.agent-detail .user-content .status {
font-size: 12px;
font-weight: 400;
color: #999999;
cursor: pointer;
}
.agent-content .el-form-item--small {
margin-bottom: 8px;
}
.agent-detail .user-content .commission-item {
width: 30%;
line-height: 18px;
font-size: 14px;
font-weight: 500;
}
.agent-detail .user-content .commission-item .title {
height: 24px;
line-height: 24px;
font-size: 12px;
font-weight: 400;
margin-bottom: 4px;
}
.agent-detail .apply-content .sa-image {
width: 140px;
height: 90px;
}
.agent-detail .dashboard-content {
height: fit-content;
}
.agent-detail .dashboard-content .title {
height: 18px;
line-height: 18px;
font-size: 14px;
font-weight: 500;
color: var(--sa-title);
margin-bottom: 16px;
}
.agent-detail .dashboard-content>.el-col {
border-bottom: 1px dashed var(--sa-border);
margin-bottom: 16px;
padding-bottom: 8px;
}
.agent-detail .dashboard-content>.el-col:last-of-type {
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}
.agent-detail .dashboard-content .item {
margin-bottom: 16px;
}
.agent-detail .dashboard-content .left {
line-height: 16px;
font-size: 12px;
font-weight: 400;
color: var(--sa-subfont);
margin-bottom: 8px;
display: flex;
align-items: center;
}
.agent-detail .dashboard-content .item {
line-height: 22px;
font-size: 18px;
font-weight: 500;
color: var(--sa-font);
}
.agent-detail .dashboard-content .unit {
font-size: 12px;
font-weight: 400;
color: var(--sa-font);
margin-left: 4px;
}
.agent-detail .rewards-item {
margin-right: 8px;
}
.agent-detail .rewards-item:last-of-type {
margin-right: 0;
}
</style>
<div id="detail" class="agent-detail panel panel-default panel-intro" v-cloak>
<el-container class="panel-block">
<el-main>
<el-scrollbar class="agent-detail-scrollbar" height="100%">
<el-row :gutter="20">
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<div class="user-content agent-content">
<div class="title sa-flex sa-row-between">
<span>分销商信息</span>
<span class="refresh sa-flex" @click="getDetail">
<el-icon>
<refresh-right />
</el-icon>
刷新
</span>
</div>
<div v-if="state.data.user" class="sa-flex sa-row-center">
<sa-image :url="state.data.user.avatar" size="80" radius="40">
</sa-image>
</div>
<div class="nickname sa-flex sa-row-center mt-1">
{{
state.data.user
? state.data.user.nickname
: state.data.user_id
}}
</div>
<el-form size="small" label-position="right" label-width="76px">
<el-form-item label="分销商状态:">
<el-dropdown popper-class="agent-popover" trigger="click" @command="onChangeStatus">
<span class="status" :style="{
color: statusStyle[state.data.status]?.color,
}">
{{ state.data.status_text }}
<el-icon>
<arrow-down />
</el-icon>
</span>
<template #dropdown>
{if $auth->check('shopro/commission/agent/edit')}
<el-dropdown-menu>
<el-dropdown-item class="status" :style="{
color: value.color,
}" v-for="(value, key) in statusStyle" :key="key" :command="key">{{ value.label }}
</el-dropdown-item>
</el-dropdown-menu>
{/if}
</template>
</el-dropdown>
</el-form-item>
<el-form-item label="分销等级:">
<template v-if="state.data.level_info">
<div>{{ state.data.level_info.name }}</div>
<div>(等级{{ state.data.level_info.level }})</div>
</template>
<template v-if="!state.data.level_info">
{{ state.data.level }}
</template>
{if $auth->check('shopro/commission/agent/edit')}
<el-button class="ml-2" type="primary" link @click="onChangeLevel">更换</el-button>
{/if}
</el-form-item>
<el-form-item v-if="state.data.level_status > 0" label="待升级等级:">
<div v-if="state.data.level_status_info">
{{ state.data.level_status_info.name }}
</div>
<div>(等级{{ state.data.level_status || '-' }})</div>
{if $auth->check('shopro/commission/agent/edit')}
<el-button class="ml-2" type="primary" link
@click="onEdit({level_status: state.data.level_status})">同意</el-button>
<el-button type="danger" link @click="onEdit({level_status: 0})">拒绝</el-button>
{/if}
</el-form-item>
<el-form-item label="上级分销商:">
<sa-user-profile type="agent" :user="state.data.user?.parent_user"
:id="state.data.user?.parent_user_id" :isavatar="false"></sa-user-profile>
<el-button class="ml-2" type="primary" link @click="onChangeParentUser">更换
</el-button>
</el-form-item>
<el-form-item label="佣金比例:">
<div class="commission-item">
<div class="title">一级(自购)</div>
<div>
{{
state.data.level_info
? state.data.level_info.commission_rules.commission_1
: '0.00'
}}%
</div>
</div>
<div class="commission-item">
<div class="title">二级</div>
<div>
{{
state.data.level_info
? state.data.level_info.commission_rules.commission_2
: '0.00'
}}%
</div>
</div>
<div class="commission-item">
<div class="title">三级</div>
<div>
{{
state.data.level_info
? state.data.level_info.commission_rules.commission_3
: '0.00'
}}%
</div>
</div>
</el-form-item>
<el-form-item label="允许升级:">
{if $auth->check('shopro/commission/agent/edit')}
<el-switch v-model="state.data.upgrade_lock" :active-value="0" :inactive-value="1"
@change="state.data.user_id?onEdit({upgrade_lock: state.data.upgrade_lock}): ''">
</el-switch>
{/if}
</el-form-item>
</el-form>
</div>
</el-col>
<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
<div class="apply-content agent-content">
<el-form size="small" label-position="right" label-width="76px">
<div class="title sa-flex sa-row-between mb-4">
<span>申请信息</span>
<div>
{if $auth->check('shopro/commission/agent/edit')}
<el-button v-if="!applyInfo.flag" type="primary" link
@click="applyInfo.flag = true">编辑</el-button>
<div v-if="applyInfo.flag" class="sa-flex">
<el-button type="danger" link @click="onCancelApplyInfo">
取消
</el-button>
<el-button type="primary" link @click="onSaveApplyInfo">保存
</el-button>
</div>
{/if}
</div>
</div>
<template v-for="(item, index) in applyInfo.data" :key="item">
<el-form-item :label="`${item.name}:`">
<div class="sa-flex sa-col-top">
<template v-if="item.type == 'text' || item.type == 'number'">
<el-input v-if="applyInfo.flag" class="sa-w-140" v-model="item.value">
</el-input>
<template v-if="!applyInfo.flag">
{{ item.value }}
</template>
</template>
<sa-image v-if="item.type == 'image'" :url="item.value"></sa-image>
<el-button v-if="applyInfo.flag" class="ml-2" type="danger" link
size="small" @click="onDeleteApplyInfo(index)">
删除
</el-button>
</div>
</el-form-item>
</template>
</el-form>
</div>
</el-col>
<el-col class="sa-col-24" :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
<el-row class="dashboard-content agent-content">
<el-col :span="24">
<div class="title sa-flex">
<span>团队统计</span>
{if $auth->check('shopro/commission/agent/team')}
<el-button class="ml-2" type="primary" link @click="onTeam">查看团队</el-button>
{/if}
</div>
<el-row>
<el-col class="item" :xs="12" :sm="8" :md="8" :lg="8" :xl="8">
<div class="left">团队人数:</div>
<div class="right">
{{ state.data.child_user_count_all }}
<span class="unit"></span>
</div>
</el-col>
<el-col class="item" :xs="12" :sm="8" :md="8" :lg="8" :xl="8">
<div class="left">一级团队人数:</div>
<div class="right">
{{ state.data.child_user_count_1 }}
<span class="unit"></span>
</div>
</el-col>
<el-col class="item" :xs="12" :sm="8" :md="8" :lg="8" :xl="8">
<div class="left">二级团队人数:</div>
<div class="right">
{{ state.data.child_user_count_2 }}
<span class="unit"></span>
</div>
</el-col>
<el-col class="item" :xs="12" :sm="8" :md="8" :lg="8" :xl="8">
<div class="left">
团队分销商人数:
<el-popover placement="top" trigger="hover">
<div v-for="(value, key) in state.data.child_agent_level_all"
:key="key">
等级{{ key }}{{ value }}人
</div>
<template #reference>
<div class="sa-flex">
<el-icon v-if="state.data.child_agent_count_all"
class="warning">
<Warning />
</el-icon>
</div>
</template>
</el-popover>
</div>
<div class="right">
{{ state.data.child_agent_count_all }}
<span class="unit"></span>
</div>
</el-col>
<el-col class="item" :xs="12" :sm="8" :md="8" :lg="8" :xl="8">
<div class="left">
一级分销商人数:
<el-popover placement="top" trigger="hover">
<div v-for="(value, key) in state.data.child_agent_level_1" :key="key">
等级{{ key }}{{ value }}人
</div>
<template #reference>
<div class="sa-flex">
<el-icon v-if="state.data.child_agent_count_1" class="warning">
<Warning />
</el-icon>
</div>
</template>
</el-popover>
</div>
<div class="right">
{{ state.data.child_agent_count_1 }}
<span class="unit"></span>
</div>
</el-col>
<el-col class="item" :xs="12" :sm="8" :md="8" :lg="8" :xl="8">
<div class="left">二级分销商人数:</div>
<div class="right">
{{ state.data.child_agent_count_2 }}
<span class="unit"></span>
</div>
</el-col>
</el-row>
</el-col>
<el-col :span="24">
<div class="title sa-flex">
<span>业绩统计</span>
</div>
<el-row>
<el-col class="item" :xs="12" :sm="6" :md="6" :lg="6" :xl="6">
<div class="left">团队分销总金额:</div>
<div class="right">
{{ state.data.child_order_money_all }}
<span class="unit"></span>
</div>
</el-col>
<el-col class="item" :xs="12" :sm="6" :md="6" :lg="6" :xl="6">
<div class="left">一级分销总金额:</div>
<div class="right">
{{ state.data.child_order_money_1 }}
<span class="unit"></span>
</div>
</el-col>
<el-col class="item" :xs="12" :sm="6" :md="6" :lg="6" :xl="6">
<div class="left">二级分销总金额:</div>
<div class="right">
{{ state.data.child_order_money_2 }}
<span class="unit"></span>
</div>
</el-col>
<el-col class="item" :xs="12" :sm="6" :md="6" :lg="6" :xl="6">
<div class="left">
自购分销总金额:
<el-popover popper-class="sa-popper" placement="top" trigger="hover"
content="分销商自购分销商品金额统计">
<template #reference>
<div class="sa-flex">
<el-icon class="warning">
<Warning />
</el-icon>
</div>
</template>
</el-popover>
</div>
<div class="right">
{{ state.data.child_order_money_0 }}
<span class="unit"></span>
</div>
</el-col>
<el-col class="item" :xs="12" :sm="6" :md="6" :lg="6" :xl="6">
<div class="left">团队分销订单:</div>
<div class="right">
{{ state.data.child_order_count_all }}
<span class="unit"></span>
</div>
</el-col>
<el-col class="item" :xs="12" :sm="6" :md="6" :lg="6" :xl="6">
<div class="left">一级分销订单:</div>
<div class="right">
{{ state.data.child_order_count_1 }}
<span class="unit"></span>
</div>
</el-col>
<el-col class="item" :xs="12" :sm="6" :md="6" :lg="6" :xl="6">
<div class="left">二级分销订单:</div>
<div class="right">
{{ state.data.child_order_count_2 }}
<span class="unit"></span>
</div>
</el-col>
<el-col class="item" :xs="12" :sm="6" :md="6" :lg="6" :xl="6">
<div class="left">
自购分销订单:
<el-popover popper-class="sa-popper" placement="top" trigger="hover"
content="分销商自购分销订单数量统计">
<template #reference>
<div class="sa-flex">
<el-icon class="warning">
<Warning />
</el-icon>
</div>
</template>
</el-popover>
</div>
<div class="right">
{{ state.data.child_order_count_0 }}
<span class="unit"></span>
</div>
</el-col>
</el-row>
</el-col>
<el-col :span="24">
<div class="title sa-flex">
<span>资产信息</span>
</div>
<el-row>
<el-col class="item" :xs="12" :sm="8" :md="8" :lg="8" :xl="8">
<div class="left">累计佣金:</div>
<div class="right">
{{ state.data.total_income }}
<span class="unit"></span>
</div>
</el-col>
<el-col class="item" :xs="12" :sm="8" :md="8" :lg="8" :xl="8">
<div class="left">待入账佣金:</div>
<div class="right">
{{ state.data.pending_reward }}
<span class="unit"></span>
</div>
</el-col>
<el-col class="item" :xs="12" :sm="8" :md="8" :lg="8" :xl="8">
<div class="left">消费金额:</div>
<div class="right">
{{ state.data.user?.total_consume || 0 }}
<span class="unit"></span>
</div>
</el-col>
</el-row>
</el-col>
</el-row>
</el-col>
</el-row>
<el-tabs class="sa-tabs" v-model="log.tabActive" @tab-change="onChangeTab">
<el-tab-pane label="分销动态" name="log"></el-tab-pane>
<el-tab-pane label="分销订单" name="order"></el-tab-pane>
<el-tab-pane label="佣金明细" name="reward"></el-tab-pane>
</el-tab-pane>
</el-tabs>
<el-table v-if="log.tabActive=='log'" class="sa-table" :data="log.data" stripe>
<el-table-column prop="id" label="ID" min-width="90"></el-table-column>
<el-table-column label="分销商" min-width="160">
<template #default="scope">
<sa-user-profile :user="scope.row.agent" :id="scope.row.agent_id"></sa-user-profile>
</template>
</el-table-column>
<el-table-column prop="remark" label="内容" min-width="300"></el-table-column>
<el-table-column label="操作人" min-width="160">
<template #default="scope">
<sa-user-profile type="oper" :user="scope.row.oper" :id="scope.row.oper_id">
</sa-user-profile>
</template>
</el-table-column>
<el-table-column prop="createtime" label="动态时间" width="172"></el-table-column>
</el-table>
<el-table v-if="log.tabActive=='order'" class="sa-table" :data="log.data" stripe>
<el-table-column prop="id" label="ID" min-width="90"></el-table-column>
<el-table-column label="订单号" min-width="260">
<template #default="scope">
{{ scope.row.order?.order_sn || scope.row.order_id }}
</template>
</el-table-column>
<el-table-column label="下单用户" min-width="160">
<template #default="scope">
<sa-user-profile :user="scope.row.buyer" :id="scope.row.buyer_id"></sa-user-profile>
</template>
</el-table-column>
<el-table-column label="分佣状态" min-width="100">
<template #default="scope">
<span :class="`sa-color--${log.status[scope.row.commission_reward_status]}`">
{{ scope.row.commission_reward_status_text }}
</span>
</template>
</el-table-column>
<el-table-column label="商品结算金额" min-width="160">
<template #default="scope"> {{ scope.row.amount }}元 </template>
</el-table-column>
<el-table-column label="分销总金额/到账金额" min-width="160">
<template #default="scope">
{{ countCommission(scope.row.rewards) }}
</template>
</el-table-column>
<el-table-column label="佣金详情" min-width="200" align="center">
<template #default="scope">
<div class="sa-flex sa-row-center">
<div class="rewards-item sa-flex sa-flex-col" v-for="rewards in scope.row.rewards"
:key="rewards">
<template v-if="rewards.agent">
<sa-image :url="rewards.agent.avatar" size="32" radius="16"></sa-image>
</template>
<template v-if="!rewards.agent">
{{ rewards.agent_id }}
</template>
<div class="commission sa-m-t-6">{{ rewards.commission }}元</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column prop="commission_time" label="加入时间" width="172"></el-table-column>
</el-table>
<el-table v-if="log.tabActive=='reward'" class="sa-table" :data="log.data" stripe>
<el-table-column prop="id" label="ID" min-width="90"></el-table-column>
<el-table-column label="订单号" min-width="260">
<template #default="scope">
{{ scope.row.order?.order_sn || scope.row.order_id }}
</template>
</el-table-column>
<el-table-column label="下单用户" min-width="160">
<template #default="scope">
<sa-user-profile :user="scope.row.buyer" :id="scope.row.buyer_id"></sa-user-profile>
</template>
</el-table-column>
<el-table-column label="分销用户" min-width="160">
<template #default="scope">
<sa-user-profile :user="scope.row.agent" :id="scope.row.agent_id"></sa-user-profile>
</template>
</el-table-column>
<el-table-column label="分销金额" min-width="160">
<template #default="scope"> {{ scope.row.commission }}元 </template>
</el-table-column>
<el-table-column label="入账状态" min-width="80">
<template #default="scope">
<span :class="`sa-color--${log.status[scope.row.status]}`">
{{ scope.row.status_text }}
</span>
</template>
</el-table-column>
<el-table-column prop="type_text" label="入账方式" min-width="80"></el-table-column>
<el-table-column prop="commission_time" label="分佣时间" width="172"></el-table-column>
</el-table>
<el-footer class="sa-footer sa-flex sa-row-right">
<sa-pagination v-model="pagination" @pagination-change="getLog"></sa-pagination>
</el-footer>
</el-scrollbar>
</el-main>
</el-container>
</div>

View File

@@ -0,0 +1,204 @@
{include file="/shopro/common/script" /}
<style>
.agent-index .status-text {
margin-right: 12px;
}
</style>
<div id="index" class="agent-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.tabActive" @tab-change="onChangeTab">
<el-tab-pane v-for="item in type.data.status" :key="item" :label="item.name" :name="item.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>
</div>
</div>
</el-header>
<el-main class="sa-main">
<el-table v-if="state.filter.data.tabActive=='all'" height="100%" class="sa-table" :data="state.data"
stripe>
<el-table-column prop="user_id" label="ID" min-width="90">
</el-table-column>
<el-table-column label="分销商信息" min-width="150">
<template #default="scope">
<sa-user-profile :user="scope.row.user" :id="scope.row.user_id"></sa-user-profile>
</template>
</el-table-column>
<el-table-column label="等级" min-width="120">
<template #default="scope">
<template v-if="scope.row.level_info">
<div>{{ scope.row.level_info.name }}</div>
<div>(等级{{ scope.row.level_info.level }})</div>
</template>
<template v-else>{{ scope.row.level }}</template>
</template>
</el-table-column>
<el-table-column label="累计佣金" min-width="120">
<template #default="scope"> {{ scope.row.total_income }}元 </template>
</el-table-column>
<el-table-column label="消费金额" min-width="120">
<template #default="scope"> {{ scope.row.user?.total_consume || 0 }}元 </template>
</el-table-column>
<el-table-column label="自购分销业绩" min-width="120">
<template #default="scope">
<div>{{ scope.row.child_order_count_0 }}单</div>
<div>{{ scope.row.child_order_money_0 }}元</div>
</template>
</el-table-column>
<el-table-column label="上级分销商" min-width="120" align="center">
<template #default="scope">
<sa-user-profile type="agent" :user="scope.row.user?.parent_user"
:id="scope.row.user?.parent_user_id" mode="col"></sa-user-profile>
</template>
</el-table-column>
<el-table-column label="一级用户人数" min-width="120">
<template #default="scope"> {{ scope.row.child_user_count_1 }}人 </template>
</el-table-column>
<el-table-column label="一级分销商人数" min-width="160">
<template #default="scope">
<div>{{ scope.row.child_agent_count_1 }}人</div>
</template>
</el-table-column>
<el-table-column prop="createtime" label="创建时间" width="172"></el-table-column>
<el-table-column label="操作" min-width="140" fixed="right">
<template #default="scope">
<div class="sa-flex">
<span class="mr-2" :style="{
color: statusStyle[scope.row.status]?.color,
}">
{{ scope.row.status_text }}
</span>
{if $auth->check('shopro/commission/agent/detail')}
<el-button type="primary" link @click="onDetail(scope.row.user_id)">查看</el-button>
{/if}
</div>
</template>
</el-table-column>
</el-table>
<el-table v-if="state.filter.data.tabActive=='pending'" height="100%" class="sa-table" :data="state.data"
stripe>
<el-table-column prop="user_id" label="ID" min-width="90">
</el-table-column>
<el-table-column label="分销商信息" min-width="150">
<template #default="scope">
<sa-user-profile :user="scope.row.user" :id="scope.row.user_id" />
</template>
</el-table-column>
<el-table-column label="等级" min-width="120">
<template #default="scope">
<template v-if="scope.row.level_info">
<div>{{ scope.row.level_info.name }}</div>
<div>(等级{{ scope.row.level_info.level }})</div>
</template>
<template v-else>{{ scope.row.level }}</template>
</template>
</el-table-column>
<el-table-column label="上级分销商" min-width="120" align="center">
<template #default="scope">
<sa-user-profile type="agent" :user="scope.row.user?.parent_user"
:id="scope.row.user?.parent_user_id" mode="col" />
</template>
</el-table-column>
<el-table-column label="消费金额" min-width="120">
<template #default="scope"> {{ scope.row.user?.total_consume || 0 }}元 </template>
</el-table-column>
<el-table-column label="推广人数" min-width="120">
<template #default="scope"> {{ scope.row.child_user_count_1 }}人 </template>
</el-table-column>
<el-table-column label="提交次数" min-width="120">
<template #default="scope"> {{ scope.row.apply_num }}次</template>
</el-table-column>
<el-table-column prop="createtime" label="创建时间" min-width="172"></el-table-column>
<el-table-column label="操作" min-width="160" fixed="right">
<template #default="scope">
<div class="sa-flex">
{if $auth->check('shopro/commission/agent/edit')}
<el-button type="success" link @click="onEdit(scope.row.user_id, {status:'normal'})">
同意
</el-button>
{/if}
{if $auth->check('shopro/commission/agent/edit')}
<el-button type="warning" link @click="onEdit(scope.row.user_id,{status:'reject'} )">
驳回
</el-button>
{/if}
{if $auth->check('shopro/commission/agent/detail')}
<el-button type="primary" link @click="onDetail(scope.row.user_id)">查看</el-button>
{/if}
</div>
</template>
</el-table-column>
</el-table>
<el-table v-if="state.filter.data.tabActive==0" height="100%" class="sa-table" :data="state.data" stripe>
<el-table-column prop="user_id" label="ID" min-width="90"></el-table-column>
<el-table-column label="分销商信息" min-width="150">
<template #default="scope">
<sa-user-profile :user="scope.row.user" :id="scope.row.user_id" />
</template>
</el-table-column>
<el-table-column label="等级" min-width="120">
<template #default="scope">
<template v-if="scope.row.level_info">
<div>{{ scope.row.level_info.name }}</div>
<div>(等级{{ scope.row.level_info.level }})</div>
</template>
<template v-else>{{ scope.row.level }}</template>
</template>
</el-table-column>
<el-table-column label="消费金额" min-width="120">
<template #default="scope"> {{ scope.row.user?.total_consume || 0 }}元 </template>
</el-table-column>
<el-table-column label="推广人数" min-width="120">
<template #default="scope"> {{ scope.row.child_user_count_1 }}人 </template>
</el-table-column>
<el-table-column label="升级之后的等级" min-width="200">
<template #default="scope">
<div v-if="scope.row.level_status_info">
{{ scope.row.level_status_info.name }}
</div>
<div>等级{{ scope.row.level_status }}</div>
</template>
</el-table-column>
<el-table-column prop="createtime" label="创建时间" min-width="172"></el-table-column>
<el-table-column label="操作" min-width="200" fixed="right">
<template #default="scope">
<div class="sa-flex">
<span class="sa-color--info mr-2" v-if="!scope.row.level_status_info">
未找到等级
</span>
<template v-if="scope.row.level_status_info">
{if $auth->check('shopro/commission/agent/edit')}
<el-button type="success" link
@click=" onEdit(scope.row.user_id, {level_status: scope.row.level_status})">
同意
</el-button>
<el-button type="danger" link @click="onEdit(scope.row.user_id, { level_status: 0 })">
拒绝
</el-button>
{/if}
</template>
{if $auth->check('shopro/commission/agent/detail')}
<el-button type="primary" link @click="onDetail(scope.row.user_id)">查看</el-button>
{/if}
</div>
</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,81 @@
{include file="/shopro/common/script" /}
<style>
.agent-select .filter-item {
width: 330px;
}
.agent-select .filter-item .el-select {
width: 110px;
}
</style>
<div id="select" class="agent-select" v-cloak>
<el-container class="panel-block">
<el-header class="sa-header">
<el-alert class="mt-4">
<template #title>
温馨提示:更换上级推荐人之后,该用户之后的所有团队和业绩将移至新的推荐人名下
</template>
</el-alert>
<div class="sa-flex sa-flex-wrap sa-row-between mt-4">
<div class="sa-flex">
当前推荐人:
<sa-user-profile type="agent" :user="state.userDetail.parent_user"
:id="state.userDetail?.parent_user_id" :isHover="false"></sa-user-profile>
</div>
<el-input class="filter-item" v-model="state.filter.data.user.value" placeholder="请输入查询内容">
<template #prepend>
<el-select v-model="state.filter.data.user.field">
<el-option label="分销商ID" value="user_id"></el-option>
<el-option label="分销商昵称" value="user.nickname"></el-option>
<el-option label="分销商手机号" value="user.mobile"></el-option>
</el-select>
</template>
<template #append>
<button @click="getData">搜索</button>
</template>
</el-input>
</div>
</el-header>
<el-main>
<el-table height="100%" class="sa-table" :data="state.data" stripe>
<el-table-column prop="user_id" label="ID" min-width="90"></el-table-column>
<el-table-column label="分销商信息" min-width="150">
<template #default="scope">
<sa-user-profile :user="scope.row.user" :id="scope.row.user_id" :isHover="false" />
</template>
</el-table-column>
<el-table-column label="等级" min-width="150" align="center">
<template #default="scope">
<template v-if="scope.row.level_info">
{{ scope.row.level_info.name }}
(等级{{ scope.row.level_info.level }})
</template>
<template v-else>{{ scope.row.level }}</template>
</template>
</el-table-column>
<el-table-column label="手机号" min-width="120" align="center">
<template #default="scope">
{{ scope.row.user ? scope.row.user.mobile : '-' }}
</template>
</el-table-column>
<el-table-column label="操作" min-width="80" fixed="right">
<template #default="scope">
<span v-if="scope.row.user_id == state.parent_user_id" class="status"> 已选择 </span>
<el-button v-else class="is-link" type="primary" @click="onSelect(scope.row)">选择</el-button>
</template>
</el-table-column>
</el-table>
</el-main>
<el-footer class="sa-flex sa-row-between">
<el-checkbox v-model="state.parent_user_id" :true-label="0" :false-label="-1">设为平台直推</el-checkbox>
<sa-pagination class="is-ellipsis" v-model="pagination" @pagination-change="getData"></sa-pagination>
</el-footer>
<el-footer class="sa-footer--submit sa-flex sa-row-right">
<!-- {if $auth->check('shopro/commission/agent/changeParentUser')} -->
<el-button type="primary" @click="onConfirm">确定</el-button>
<!-- {/if} -->
</el-footer>
</el-container>
</div>

View File

@@ -0,0 +1,159 @@
{include file="/shopro/common/script" /}
<div id="team" class="agent-team" v-cloak>
<el-container class="panel-block">
<el-header class="sa-header sa-flex sa-flex-wrap mt-4">
<template v-if="state.data.user?.parent_user">
推荐人:
<sa-user-profile class="cursor-pointer" type="agent" :user="state.data.user?.parent_user" :id="state.data.user?.parent_user_id"
:isHover="false" @click="getTeam(state.data.user.parent_user_id)"></sa-user-profile>
</template>
</el-header>
<el-main>
<el-table class="sa-table mb-4" :data="[state.data]">
<el-table-column prop="user_id" label="ID" min-width="90"></el-table-column>
<el-table-column label="当前用户" min-width="150">
<template #default="scope">
<sa-user-profile :user="scope.row.user" :id="scope.row.user_id" :isHover="false">
</sa-user-profile>
</template>
</el-table-column>
<el-table-column label="等级" min-width="150">
<template #default="scope">
<div v-if="scope.row.level_info" class="sa-flex">
<sa-image :url="scope.row.level_info.image" size="32"></sa-image>
<span class="ml-2">{{ scope.row.level_info.name }}</span>
</div>
<template v-else>{{ scope.row.level }}</template>
</template>
</el-table-column>
<el-table-column label="状态" min-width="120" align="center">
<template #default="scope">
<span :style="{ color: statusStyle[scope.row.status]?.color }">
{{ scope.row.status_text }}
</span>
</template>
</el-table-column>
<el-table-column label="团队人数/分销商人数" min-width="160" align="center">
<template #default="scope">
{{ scope.row.child_user_count_all }}人/ {{ scope.row.child_agent_count_all }}人
</template>
</el-table-column>
<el-table-column label="一级团队人数/一级分销商人数" min-width="220" align="center">
<template #default="scope">
{{ scope.row.child_user_count_1 }}人/ {{ scope.row.child_agent_count_1 }}人
</template>
</el-table-column>
<el-table-column label="二级团队人数/二级分销商人数" min-width="220" align="center">
<template #default="scope">
{{ scope.row.child_user_count_2 }}人/ {{ scope.row.child_agent_count_2 }}人
</template>
</el-table-column>
<el-table-column label="团队分销总额/团队分销订单" min-width="220" align="center">
<template #default="scope">
{{ scope.row.child_order_money_all }}元/ {{ scope.row.child_order_count_all }}单
</template>
</el-table-column>
<el-table-column label="一级分销总额/一级分销订单" min-width="220" align="center">
<template #default="scope">
{{ scope.row.child_order_money_1 }}元/ {{ scope.row.child_order_count_1 }}单
</template>
</el-table-column>
<el-table-column label="二级分销总额/二级分销订单" min-width="220" align="center">
<template #default="scope">
{{ scope.row.child_order_money_2 }}元/ {{ scope.row.child_order_count_2 }}单
</template>
</el-table-column>
<el-table-column label="自购分销总金额/订单数" min-width="220" align="center">
<template #default="scope">
{{ scope.row.child_order_money_0 }}元/ {{ scope.row.child_order_count_0 }}单
</template>
</el-table-column>
<el-table-column label="累计佣金" min-width="160" align="center">
<template #default="scope"> {{ scope.row.total_income }}元 </template>
</el-table-column>
<el-table-column label="消费金额" min-width="160" align="center">
<template #default="scope"> {{ scope.row.user?.total_consume || 0 }}元 </template>
</el-table-column>
<el-table-column label="待入账佣金" min-width="160" align="center">
<template #default="scope"> {{ scope.row.pending_reward }}元 </template>
</el-table-column>
<el-table-column label="加入时间" min-width="172" align="center">
<template #default="scope"> {{ scope.row.createtime }} </template>
</el-table-column>
</el-table>
<el-table class="sa-table" :data="state.data.agent_team">
<el-table-column prop="user_id" label="ID" min-width="90"></el-table-column>
<el-table-column label="团队用户" min-width="150">
<template #default="scope">
<sa-user-profile class="cursor-pointer" :user="scope.row.user" :id="scope.row.user_id" :isHover="false" @click="getTeam(scope.row.user_id)">
</sa-user-profile>
</template>
</el-table-column>
<el-table-column label="等级" min-width="150">
<template #default="scope">
<div v-if="scope.row.level_info" class="sa-flex">
<sa-image :url="scope.row.level_info.image" size="32"></sa-image>
<span class="ml-2">{{ scope.row.level_info.name }}</span>
</div>
<template v-else>{{ scope.row.level }}</template>
</template>
</el-table-column>
<el-table-column label="状态" min-width="120" align="center">
<template #default="scope">
<span :style="{ color: statusStyle[scope.row.status]?.color }">
{{ scope.row.status_text }}
</span>
</template>
</el-table-column>
<el-table-column label="团队人数/分销商人数" min-width="160" align="center">
<template #default="scope">
{{ scope.row.child_user_count_all }}人/ {{ scope.row.child_agent_count_all }}人
</template>
</el-table-column>
<el-table-column label="一级团队人数/一级分销商人数" min-width="220" align="center">
<template #default="scope">
{{ scope.row.child_user_count_1 }}人/ {{ scope.row.child_agent_count_1 }}人
</template>
</el-table-column>
<el-table-column label="二级团队人数/二级分销商人数" min-width="220" align="center">
<template #default="scope">
{{ scope.row.child_user_count_2 }}人/ {{ scope.row.child_agent_count_2 }}人
</template>
</el-table-column>
<el-table-column label="团队分销总额/团队分销订单" min-width="220" align="center">
<template #default="scope">
{{ scope.row.child_order_money_all }}元/ {{ scope.row.child_order_count_all }}单
</template>
</el-table-column>
<el-table-column label="一级分销总额/一级分销订单" min-width="220" align="center">
<template #default="scope">
{{ scope.row.child_order_money_1 }}元/ {{ scope.row.child_order_count_1 }}单
</template>
</el-table-column>
<el-table-column label="二级分销总额/二级分销订单" min-width="220" align="center">
<template #default="scope">
{{ scope.row.child_order_money_2 }}元/ {{ scope.row.child_order_count_2 }}单
</template>
</el-table-column>
<el-table-column label="自购分销总金额/订单数" min-width="220" align="center">
<template #default="scope">
{{ scope.row.child_order_money_0 }}元/ {{ scope.row.child_order_count_0 }}单
</template>
</el-table-column>
<el-table-column label="累计佣金" min-width="160" align="center">
<template #default="scope"> {{ scope.row.total_income }}元 </template>
</el-table-column>
<el-table-column label="消费金额" min-width="160" align="center">
<template #default="scope"> {{ scope.row.user?.total_consume || 0 }}元 </template>
</el-table-column>
<el-table-column label="待入账佣金" min-width="160" align="center">
<template #default="scope"> {{ scope.row.pending_reward }}元 </template>
</el-table-column>
<el-table-column label="加入时间" min-width="172" align="center">
<template #default="scope"> {{ scope.row.createtime }} </template>
</el-table-column>
</el-table>
</el-main>
</el-container>
</div>

View File

@@ -0,0 +1,353 @@
{include file="/shopro/common/script" /}
<style>
.goods-form .sa-title.is-line {
margin-bottom: 16px;
}
.goods-form .goods-item {
margin-bottom: 16px;
}
.goods-form .goods-item .goods-title {
height: 16px;
line-height: 16px;
font-size: 14px;
font-weight: 500;
color: var(--sa-font);
margin-bottom: 8px;
}
.goods-form .goods-item .goods-sku {
width: fit-content;
height: 18px;
line-height: 18px;
background: var(--el-color-primary);
border-radius: 10px;
padding: 0 8px;
font-size: 12px;
color: var(--sa-background-assist);
}
.goods-form .commission-table {
overflow: hidden;
overflow-x: auto;
}
.goods-form .commission-table .commission-header {
border-left: 1px solid var(--sa-border);
}
.goods-form .commission-table .commission-header .col-item {
padding: 0 12px;
height: 40px;
line-height: 40px;
background: var(--sa-table-header-bg);
border-top: 1px solid var(--sa-border);
}
.goods-form .commission-table .commission-content {
border-left: 1px solid var(--sa-border);
}
.goods-form .commission-table .col-item {
width: 150px;
min-width: 150px;
padding: 0 12px;
height: 48px;
line-height: 48px;
display: flex;
align-items: center;
justify-content: center;
border-right: 1px solid var(--sa-border);
border-bottom: 1px solid var(--sa-border);
}
.goods-form .commission-table .col-item .el-input {
margin-right: 12px;
}
.goods-form .commission-table .col-item .el-input:last-of-type {
margin-right: 0;
}
.goods-form .commission-table .col-item.commission-item {
width: 240px;
min-width: 240px;
}
.goods-form .batch-edit {
color: var(--el-color-primary);
margin-left: 8px;
}
.commission-popover .commission-item {
margin-bottom: 12px;
}
.commission-popover .commission-item .el-input {
margin-right: 12px;
}
.commission-popover .commission-item .el-input:last-of-type {
margin-right: 0;
}
</style>
<div id="addEdit" class="goods-form" v-cloak>
<el-container class="panel-block">
<el-main>
<el-scrollbar height="100%">
<div class="sa-title is-line">商品信息</div>
<div v-for="goods in state.data?.goods" :key="goods">
<div class="goods-item sa-flex sa-col-top">
<sa-image class="mr-2" :url="goods.image" size="48"></sa-image>
<div>
<div class="goods-title sa-table-line-1">
{{ goods.title }}
</div>
<div v-if="goods.is_sku" class="goods-sku">
{{ goods.is_sku ? '多规格' : '' }}
</div>
</div>
</div>
</div>
<div class="sa-title is-line">佣金设置</div>
<el-form label-width="120px">
<el-form-item label="是否参与">
<el-radio-group v-model="state.commission_goods.status">
<el-radio :label="0">不参与</el-radio>
<el-radio :label="1">参与</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="分销商业绩">
<el-radio-group v-model="state.commission_goods.commission_order_status">
<el-radio :label="0">不计入</el-radio>
<el-radio :label="1">
<span class="sa-flex">
计入
<el-popover placement="top" :width="310" content="关闭则只分佣,不计入分销订单金额和订单数">
<template #reference>
<el-icon class="warning sa-m-l-8">
<warning />
</el-icon>
</template>
</el-popover>
</span>
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="佣金规则">
<el-radio-group v-model="state.commission_goods.self_rules" @change="onChangeSelfRules">
<el-radio :label="0">默认规则</el-radio>
<el-radio :label="1" v-if="state.rulesType != 'batch'">独立规则</el-radio>
<el-radio :label="2">批量规则</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="state.commission_goods.self_rules == 1 || state.commission_goods.self_rules == 2"
label="分销设置">
<el-switch v-model="state.commission_config_temp.status"
@change="onChangeCommissionConfigStatus" :active-value="1" :inactive-value="0" />
<span class="sa-m-l-8">
{{ state.commission_config_temp.status ? '自定义' : '默认' }}
</span>
</el-form-item>
<el-form-item label="分销层级">
<el-radio-group v-model="state.commission_config_temp.level"
:disabled="state.commission_config_temp.status == 0">
<el-radio :label="1">一级</el-radio>
<el-radio :label="2">二级</el-radio>
<el-radio :label="3">三级</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="分销自购">
<div>
<el-radio-group v-model="state.commission_config_temp.self_buy"
:disabled="state.commission_config_temp.status == 0">
<el-radio :label="0">关闭</el-radio>
<el-radio :label="1">开启</el-radio>
</el-radio-group>
<div class="tip"> 分销自购开启后,分销商自己购买时,下单可以给自己返佣 </div>
</div>
</el-form-item>
<el-form-item label="商品结算方式">
<div>
<el-radio-group v-model="state.commission_config_temp.reward_type"
:disabled="state.commission_config_temp.status == 0">
<el-radio label="goods_price">商品价</el-radio>
<el-radio label="pay_price">实际支付价</el-radio>
</el-radio-group>
<div class="tip">
商品价: 商品实际售价/规格价,实际支付价:实际支付的费用(不含运费)
</div>
</div>
</el-form-item>
<el-form-item label="佣金结算方式">
<el-radio-group v-model="state.commission_config_temp.reward_event"
:disabled="state.commission_config_temp.status == 0">
<el-radio label="paid">支付后结算</el-radio>
<el-radio label="confirm">确认收货结算</el-radio>
<el-radio label="finish">订单完成结算</el-radio>
<el-radio label="admin">手动打款</el-radio>
</el-radio-group>
</el-form-item>
<div class="commission-table">
<template v-if="state.commission_goods.self_rules == 0">
<div class="commission-header sa-flex">
<div class="col-item">分销等级名称</div>
<template v-for="commission in state.commission_config_temp.level" :key="commission">
<div v-if="commission == 1" class="col-item commission-item">
一级(自购)佣金比例
</div>
<div v-if="commission == 2" class="col-item commission-item"> 二级佣金比例 </div>
<div v-if="commission == 3" class="col-item commission-item"> 三级佣金比例 </div>
</template>
</div>
<div class="commission-content sa-flex" v-for="level in state.levelData" :key="level">
<div class="col-item">{{ level.name }}</div>
<template v-for="commission in state.commission_config_temp.level" :key="commission">
<div class="col-item commission-item">
{{ level.commission_rules[`commission_${commission}`] }}%
</div>
</template>
</div>
</template>
<template v-if="state.commission_goods.self_rules == 1">
<div class="commission-header sa-flex">
<div class="col-item">商品规格</div>
<div class="col-item">价格</div>
<div class="col-item">分销等级名称</div>
<template v-for="commission in state.commission_config_temp.level" :key="commission">
<div class="col-item commission-item">
<template v-if="commission == 1">一级(自购)佣金比例</template>
<template v-if="commission == 2">二级佣金比例</template>
<template v-if="commission == 3">三级佣金比例</template>
<el-popover popper-class="commission-popover"
v-model:visible="commissionPopover.flag[commission]" placement="top"
:width="220" trigger="click">
<div class="commission-item sa-flex">
<el-input v-model="commissionPopover.form.rate" type="number"
:disabled="commissionPopover.form.money != ''">
<template #append>%</template>
</el-input>
<el-input v-model="commissionPopover.form.money" type="number"
:disabled="commissionPopover.form.rate != ''">
<template #append></template>
</el-input>
</div>
<div class="sa-flex sa-row-right">
<el-button class="is-link" type="primary" size="small"
@click="onCancelCommissionPopover(commission)">取消</el-button>
<el-button type="primary" size="small"
@click="onConfirmCommissionPopover(commission)">确定</el-button>
</div>
<template #reference>
<el-icon class="batch-edit">
<edit />
</el-icon>
</template>
</el-popover>
</div>
</template>
</div>
<div class="commission-content sa-flex">
<div class="sa-flex sa-flex-col">
<div class="sa-flex" v-for="sku in state.detailData.sku_prices" :key="sku">
<div class="col-item" :style="{ height: 48 * state.levelData.length + 'px' }">
{{ state.detailData?.is_sku ? sku.goods_sku_text.join(',') : '默认规格' }}
</div>
<div class="col-item" :style="{ height: 48 * state.levelData.length + 'px' }">
{{ sku.price }}
</div>
<div>
<div class="col-item" v-for="level in state.levelData" :key="level">
{{ level.name }}
</div>
</div>
</div>
</div>
<div>
<div v-for="sku in state.commission_goods.commission_rules" :key="sku">
<div class="sa-flex" v-for="level in sku" :key="level">
<template v-for="commission in state.commission_config_temp.level"
:key="commission">
<div v-if="level[commission]" class="col-item commission-item">
<el-input v-model="level[commission].rate" type="number"
:disabled="level[commission].money != ''">
<template #append>%</template>
</el-input>
<el-input v-model="level[commission].money" type="number"
:disabled="level[commission].rate != ''">
<template #append></template>
</el-input>
</div>
</template>
</div>
</div>
</div>
</div>
</template>
<template v-if="state.commission_goods.self_rules == 2">
<div class="commission-header sa-flex">
<div class="col-item">商品规格</div>
<template v-for="commission in state.commission_config_temp.level" :key="commission">
<div class="col-item commission-item">
<template v-if="commission == 1">一级(自购)佣金比例</template>
<template v-if="commission == 2">二级佣金比例</template>
<template v-if="commission == 3">三级佣金比例</template>
<el-popover popper-class="commission-popover"
v-model:visible="commissionPopover.flag[commission]" placement="top"
:width="220" trigger="click">
<div class="commission-item sa-flex">
<el-input v-model="commissionPopover.form.rate" type="number"
:disabled="commissionPopover.form.money != ''">
<template #append>%</template>
</el-input>
</div>
<div class="sa-flex sa-row-right">
<el-button class="is-link" type="primary" size="small"
@click="onCancelCommissionPopover(commission)">取消</el-button>
<el-button size="small" type="primary"
@click="onConfirmCommissionPopover(commission)">确定</el-button>
</div>
<template #reference>
<el-icon class="batch-edit">
<edit />
</el-icon>
</template>
</el-popover>
</div>
</template>
</div>
<div class="commission-content sa-flex">
<div>
<div class="col-item" v-for="level in state.levelData" :key="level">
{{ level.name }}
</div>
</div>
<div>
<div class="sa-flex" v-for="level in state.commission_goods.commission_rules"
:key="level">
<template v-for="commission in state.commission_config_temp.level"
:key="commission">
<div v-if="level[commission]" class="col-item commission-item">
<el-input v-model="level[commission].rate" type="number"
:disabled="level[commission].money != ''">
<template #append>%</template>
</el-input>
</div>
</template>
</div>
</div>
</div>
</template>
</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,116 @@
{include file="/shopro/common/script" /}
<style>
.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 .goods-item .goods-sku {
width: fit-content;
height: 18px;
line-height: 18px;
background: var(--el-color-primary);
border-radius: 10px;
padding: 0 8px;
font-size: 12px;
color: var(--sa-background-assist);
}
</style>
<div id="index" class="goods-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 @selection-change="onChangeSelection">
<el-table-column 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="300">
<template #default="scope">
<div class="goods-item sa-flex sa-col-top">
<sa-image class="mr-2" :url="scope.row.image" size="64"></sa-image>
<div>
<div class="goods-title sa-table-line-1">{{scope.row.title}}</div>
<div class="goods-subtitle sa-table-line-1">{{scope.row.subtitle}}</div>
<div v-if="scope.row.is_sku==1" class="goods-sku">多规格</div>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="价格" min-width="150">
<template #default="scope">
<div>{{ scope.row.price?.join('~') || 0 }}</div>
</template>
</el-table-column>
<el-table-column label="分销规则" width="100">
<template #default="scope">
<template v-if="scope.row.commission_goods && scope.row.commission_goods.status == 1">
<template v-if="scope.row.commission_goods.self_rules == 0">默认规则</template>
<template v-if="scope.row.commission_goods.self_rules == 1">独立规则</template>
<template v-if="scope.row.commission_goods.self_rules == 2">批量规则</template>
</template>
<template v-else>-</template>
</template>
</el-table-column>
<el-table-column label="商品状态" width="100">
<template #default="scope">
<span :class="`sa-color--${state.statusStyle[scope.row.status]}`">
{{ scope.row.status_text }}
</span>
</template>
</el-table-column>
<el-table-column label="操作" min-width="140" fixed="right">
<template #default="scope">
<div class="sa-flex">
<span class="mr-2"
:class="`sa-color--${state.goodsStatusStyle[scope.row.commission_goods?.status] || 'info'}`">
{{ scope.row.commission_goods?.status_text || '未参与' }}
</span>
{if $auth->check('shopro/commission/goods/edit')}
<el-button type="primary" link @click="onEdit(scope.row.id)">设置佣金</el-button>
{/if}
</div>
</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/commission/goods/edit')}
<el-button type="primary" :disabled="!batchHandle.data.length" @click="onBatchHandle('edit')">设置佣金
</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,187 @@
{include file="/shopro/common/script" /}
<style>
.level-form .title {
height: 32px;
line-height: 32px;
background: var(--sa-background-hex-hover);
padding: 0 16px;
font-size: 12px;
font-weight: 400;
color: var(--sa-subtitle);
border-radius: 4px;
margin-bottom: 16px;
}
.level-form .sa-title.is-line {
margin-bottom: 20px;
}
.level-form .w-120 {
width: 120px;
}
.level-form .item {
height: 32px;
padding: 0 16px;
font-size: 14px;
border: 1px solid var(--sa-border);
border-radius: 4px;
margin: 0 16px 16px 0;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.level-form .item:last-of-type {
margin: 0 0 16px 0;
}
.level-form .item.is-disabled {
background: var(--sa-background-hex-active);
color: #fff;
border: 1px solid var(--sa-background-hex-active);
cursor: not-allowed;
}
.level-form .item.is-active {
background: var(--el-color-primary);
color: #fff;
border: 1px solid var(--el-color-primary);
}
.level-form .item.is-active.is-none {
display: flex;
}
.level-form .item.is-none {
display: none;
}
.level-form .condition-group .condition-item {
padding: 0 12px;
}
</style>
<div id="addEdit" class="level-form" v-cloak>
<el-container class="panel-block">
<el-main>
<el-scrollbar height="100%">
<el-alert class="mb-4" type="warning">
<template #title>
新增或编辑等级后,请及时在分销商品中完善对应的佣金规则
</template>
</el-alert>
<el-form :model="form.model" :rules="form.rules" ref="formRef" label-width="150px">
<div class="sa-title is-line">等级佣金比例</div>
<el-form-item label="等级权重" prop="level">
<div :class="[
'item',
item.level == form.model.level ? 'is-active' : '',
level.existLevel.includes(item.level) ? 'is-disabled' : '',
form.model.level == 1 ? 'is-none' : '',
]" v-for="item in level.data" :key="item" @click="onSelectLevel(item.level)">
{{ item.name }}
</div>
</el-form-item>
<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="image">
<sa-uploader v-model="form.model.image"></sa-uploader>
</el-form-item>
<el-form-item label="一级(自购)佣金比例" prop="commission_rules.commission_1"
:rules="form.rules.commission_rules.commission">
<el-input class="sa-w-360" v-model="form.model.commission_rules.commission_1" type="number">
<template #append>%</template>
</el-input>
</el-form-item>
<el-form-item label="二级佣金比例" prop="commission_rules.commission_2"
:rules="form.rules.commission_rules.commission">
<el-input class="sa-w-360" v-model="form.model.commission_rules.commission_2" type="number">
<template #append>%</template>
</el-input>
</el-form-item>
<el-form-item label="三级佣金比例" prop="commission_rules.commission_3"
:rules="form.rules.commission_rules.commission">
<el-input class="sa-w-360" v-model="form.model.commission_rules.commission_3" type="number">
<template #append>%</template>
</el-input>
</el-form-item>
<template v-if="form.model.level != 1">
<div class="sa-title is-line">添加升级条件</div>
<el-form-item label="升级方式" prop="upgrade_rules">
<div>
<el-radio-group class="mb-2" v-model="form.model.upgrade_type">
<el-radio :label="0">满足以下任意条件</el-radio>
<el-radio :label="1">满足以下全部条件</el-radio>
</el-radio-group>
<div>
<div class="sa-flex sa-flex-wrap condition-group" v-for="group in upgradeCondition"
:key="group">
<div :class="[
'item',
'condition-item',
Object.keys(form.model.upgrade_rules).includes(key) ? 'is-active' : '',
]" v-for="(item, key) in group" :key="item"
@click="onSelectUpgradeCondition(key)">
{{ item.name }}
</div>
</div>
</div>
</div>
</el-form-item>
<template v-for="(group, gkey) in upgradeCondition" :key="group">
<template v-for="(item, key) in group" :key="item">
<el-form-item :label="item.name"
v-if="Object.keys(form.model.upgrade_rules).includes(key)"
:prop="`upgrade_rules.${key}`" :rules="form.rules.upgrade_rules_inner.rules">
<template v-if="gkey != 'agent_level'">
<el-input class="w-120" v-model="form.model.upgrade_rules[key]" type="number">
<template #append> {{ initUnit(key) }}</template>
</el-input>
<el-button class="delete" type="danger" link @click="onDeleteRules(key)">
删除
</el-button>
</template>
<div v-if="gkey == 'agent_level'">
<div class="sa-flex sa-flex-wrap mb-4"
v-for="(al, index) in form.model.upgrade_rules[key]" :key="al">
<el-form-item :prop="`upgrade_rules.${key}.${index}.level`"
:rules="form.rules.upgrade_rules_inner.level">
<el-select class="w-120" v-model="al.level" placeholder="请选择分销商等级">
<template v-for="item in level.select" :key="item">
<el-option v-if="item.level < form.model.level"
:label="item.name" :value="item.level+''"></el-option>
</template>
</el-select>
<span class="ml-2 mr-2"></span>
</el-form-item>
<el-form-item :prop="`upgrade_rules.${key}.${index}.count`"
:rules="form.rules.upgrade_rules_inner.rules">
<el-input class="w-120" v-model="al.count" type="number">
<template #append></template>
</el-input>
<el-button class="delete" type="danger" link
@click="onDeleteRules(key, index)">
删除
</el-button>
</el-form-item>
</div>
<el-button type="primary" link size="small" @click="onAddUpgradeRules(key)">
+ 添加</el-button>
</div>
</el-form-item>
</template>
</template>
</template>
</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="level-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/commission/level/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>
<el-table-column label="等级" min-width="90">
<template #default="scope"> 等级{{ scope.row.level }} </template>
</el-table-column>
<el-table-column label="等级名称" min-width="150">
<template #default="scope">
{{ scope.row.name }}
</template>
</el-table-column>
<el-table-column label="等级徽章" min-width="120">
<template #default="scope">
<sa-image :url="scope.row.image" size="24"></sa-image>
</template>
</el-table-column>
<el-table-column label="一级(自购)佣金比例" min-width="160">
<template #default="scope"> {{ scope.row.commission_rules?.commission_1 }}% </template>
</el-table-column>
<el-table-column label="二级佣金比例" min-width="120">
<template #default="scope"> {{ scope.row.commission_rules?.commission_2 }}% </template>
</el-table-column>
<el-table-column label="三级佣金比例" min-width="120">
<template #default="scope"> {{ scope.row.commission_rules?.commission_3 }}% </template>
</el-table-column>
<el-table-column label="操作" min-width="120" fixed="right">
<template #default="scope">
{if $auth->check('shopro/commission/level/edit')}
<el-button type="primary" link @click="onEdit(scope.row.level)">编辑</el-button>
{/if}
<el-popconfirm v-if="scope.row.level != 1" width="fit-content" confirm-button-text="确认"
cancel-button-text="取消" title="确认删除这条记录?" @confirm="onDelete(scope.row.level)">
<template #reference>
{if $auth->check('shopro/commission/level/delete')}
<el-button type="danger" link>删除</el-button>
{/if}
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</el-main>
</el-container>
</div>

View File

@@ -0,0 +1,29 @@
{include file="/shopro/common/script" /}
<div id="select" class="level-select" v-cloak>
<el-container class="panel-block">
<el-header class="sa-header">
<el-alert class="mt-4">
<template #title>温馨提示:更换等级后,该用户不会降级</template>
</el-alert>
</el-header>
<el-main>
<el-table height="100%" class="sa-table" :data="state.data" stripe>
<el-table-column prop="name" label="等级信息" min-width="150"></el-table-column>
<el-table-column label="等级权重" min-width="90">
<template #default="scope"> 等级{{ scope.row.level }} </template>
</el-table-column>
<el-table-column label="操作" min-width="80" fixed="right">
<template #default="scope">
<span v-if="scope.row.level == state.level" class="sa-color--info"> 已选择 </span>
<el-button v-else class="is-link" type="primary" @click="onSelect(scope.row.level)">选择
</el-button>
</template>
</el-table-column>
</el-table>
</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,56 @@
{include file="/shopro/common/script" /}
<div id="index" class="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>
<div class="really-status sa-flex ml-4">
实时动态
<el-switch class="ml-2" v-model="really.reallyStatus" :active-value="1" :inactive-value="0"
@change="onChangeReallyStatus"></el-switch>
<span class="ml-1" :class="really.reallyStatus == 1?'sa-color--primary':''">
{{ really.reallyStatus == 1 ? '开启' : '关闭' }}
</span>
<el-popover popper-class="sa-popper" trigger="hover" content="开启后,该页面将实时刷新">
<template #reference>
<el-icon class="sa-color--warning ml-1">
<Warning />
</el-icon>
</template>
</el-popover>
</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>
<el-table-column prop="id" label="ID" min-width="90"></el-table-column>
<el-table-column prop="event_text" label="动态筛选" min-width="120"></el-table-column>
<el-table-column label="分销商" min-width="160">
<template #default="scope">
<sa-user-profile :user="scope.row.agent" :id="scope.row.agent_id"></sa-user-profile>
</template>
</el-table-column>
<el-table-column prop="remark" label="内容" min-width="300"></el-table-column>
<el-table-column label="操作人" min-width="160">
<template #default="scope">
<sa-user-profile type="oper" :user="scope.row.oper" :id="scope.row.oper_id"></sa-user-profile>
</template>
</el-table-column>
<el-table-column prop="createtime" label="动态时间" width="172"></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,513 @@
{include file="/shopro/common/script" /}
<style>
.order-index .dashboard-content {
padding: 20px 20px 0;
background: var(--sa-table-header-bg);
border-radius: 8px;
margin-bottom: 20px;
}
.order-index .dashboard-content .dashboard-item {
text-align: center;
margin-bottom: 20px;
}
.order-index .dashboard-content .dashboard-item .top {
line-height: 24px;
font-size: 20px;
font-weight: 400;
color: var(--sa-subtitle);
}
.order-index .dashboard-content .dashboard-item .top .unit {
font-size: 12px;
margin-left: 4px;
}
.order-index .dashboard-content .dashboard-item .bottom {
line-height: 16px;
font-size: 12px;
font-weight: 400;
color: var(--sa-font);
}
.order-index .order-content {
font-size: 12px;
font-weight: 400;
color: var(--sa-subtitle);
}
.order-index .goods-item .goods-title {
height: 14px;
line-height: 14px;
font-size: 12px;
font-weight: 500;
margin-bottom: 4px;
}
.order-index .goods-item .goods-title .goods-id {
color: var(--el-color-primary);
cursor: pointer;
}
.order-index .goods-item .goods-sku-text {
height: 14px;
line-height: 14px;
margin-bottom: 10px;
}
.order-index .sa-table-wrap {
height: 100%;
margin-left: -48px;
overflow: hidden;
}
.order-index .sa-table-wrap .sa-table .el-table__header-wrapper {
margin-bottom: 4px;
}
.order-index .sa-table-wrap .sa-table .el-table__row {
background: var(--sa-background-hex-hover);
}
.order-index .sa-table-wrap .sa-table .el-table__expanded-cell {
padding: 0;
}
.order-index .sa-table-wrap .sa-expand-table .el-table__header-wrapper {
margin-bottom: 0;
display: none;
}
.order-index .sa-table-wrap .sa-expand-table .el-table__row {
background: var(--el-table-tr-bg-color);
}
.order-index .rewards-item {
margin-right: 8px;
}
.order-index .rewards-item:last-of-type {
margin-right: 0;
}
.order-index .rewards-item .rewards-agent-id {
line-height: 32px;
}
.rewards-popover {
line-height: 16px;
font-size: 12px;
font-weight: 400;
color: var(--sa-font);
margin-bottom: 4px;
}
.rewards-popover .nickname {
height: 20px;
line-height: 20px;
}
.rewards-popover .id {
line-height: 16px;
font-size: 12px;
font-weight: 400;
color: var(--sa-subfont);
}
.rewards-popover .rewards-status {
height: 16px;
overflow: hidden;
}
.rewards-popover .rewards-commission {
width: 80px;
}
</style>
<div id="index" class="order-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/commission/order/export')}
<el-button :loading="exportLoading" :disabled="exportLoading" @click="onExport('export')">订单导出
</el-button>
{/if}
</div>
</div>
<el-row class="dashboard-content">
<el-col class="dashboard-item" :xs="8" :sm="8" :md="6" :lg="6" :xl="6">
<div class="top"> {{ state.count.total }}<span class="unit"></span> </div>
<div class="bottom">商品总订单数</div>
</el-col>
<el-col class="dashboard-item" :xs="8" :sm="8" :md="3" :lg="3" :xl="3">
<div class="top">
{{ state.count.total_amount?.toFixed(2) }}<span class="unit"></span>
</div>
<div class="bottom">商品结算总金额</div>
</el-col>
<el-col class="dashboard-item" :xs="8" :sm="8" :md="3" :lg="3" :xl="3">
<div class="top">
{{ state.count.total_commission?.toFixed(2) }}<span class="unit"></span>
</div>
<div class="bottom">分佣总金额</div>
</el-col>
<el-col class="dashboard-item" :xs="8" :sm="8" :md="3" :lg="3" :xl="3">
<div class="top">
{{ state.count.total_commission_cancel?.toFixed(2) }}<span class="unit"></span>
</div>
<div class="bottom">已取消佣金</div>
</el-col>
<el-col class="dashboard-item" :xs="8" :sm="8" :md="3" :lg="3" :xl="3">
<div class="top">
{{ state.count.total_commission_back?.toFixed(2) }}<span class="unit"></span>
</div>
<div class="bottom">已退回佣金</div>
</el-col>
<el-col class="dashboard-item" :xs="8" :sm="8" :md="3" :lg="3" :xl="3">
<div class="top">
{{ state.count.total_commission_pending?.toFixed(2) }}<span class="unit"></span>
</div>
<div class="bottom">未结算佣金</div>
</el-col>
<el-col class="dashboard-item" :xs="8" :sm="8" :md="3" :lg="3" :xl="3">
<div class="top">
{{ state.count.total_commission_accounted?.toFixed(2) }}<span class="unit"></span>
</div>
<div class="bottom">已结算佣金</div>
</el-col>
</el-row>
</el-header>
<el-main class="sa-main">
<div class="sa-table-wrap">
<el-table height="100%" class="sa-table" :data="state.data" :span-method="arraySpanMethod"
default-expand-all>
<el-table-column type="expand">
<template #default="props">
<el-table class="sa-table sa-expand-table" :data="[props.row]">
<el-table-column width="48"></el-table-column>
<el-table-column min-width="300">
<template #default>
<div v-if="props.row.order_item" class="goods-item sa-flex">
<sa-image class="mr-2" :url="props.row.order_item.goods_image" size="58">
</sa-image>
<div>
<div class="goods-title sa-table-line-1">
<span class="goods-id mr-1"
@click="onOpenGoodsDetail(props.row.order_item.goods_id)">
#{{props.row.order_item.goods_id }}
</span>
{{ props.row.order_item.goods_title }}
</div>
<div class="goods-sku-text sa-table-line-1">
<span v-if="props.row.order_item.goods_sku_text">{{
props.row.order_item.goods_sku_text
}}</span>
</div>
<div class="sa-flex">
<span class="goods-price mr-2">¥{{
props.row.order_item.goods_price }}</span>
<span class="goods-num">x{{
props.row.order_item.goods_num }}</span>
</div>
</div>
</div>
<div v-else>{{ props.row.order_item }}</div>
</template>
</el-table-column>
<el-table-column min-width="100">
<template #default>
<!-- 0=未退款|1=申请退款|2=退款完成 -->
<span
:class="props.row.order_item?.refund_status==0?'sa-color--info':'sa-color--success'">
{{ props.row.order_item?.refund_status_text || '-' }}
</span>
</template>
</el-table-column>
<el-table-column min-width="100" align="center">
<template #default>
<sa-user-profile :user="props.row.buyer" :id="props.row.buyer_id" mode="col">
</sa-user-profile>
</template>
</el-table-column>
<el-table-column min-width="100" align="center">
<template #default>
<sa-user-profile :user="props.row.agent" :id="props.row.agent_id" mode="col">
</sa-user-profile>
</template>
</el-table-column>
<el-table-column min-width="200" align="center">
<template #default>
<el-scrollbar>
<div class="sa-flex sa-row-center">
<template v-for="(rewards, index) in props.row.rewards" :key="rewards">
<el-popover placement="top-start" :width="240" trigger="click">
<div class="rewards-popover">
<div class="mb-2">
<div v-if="rewards.agent" class="sa-flex">
<sa-image :url="rewards.agent.avatar" size="32"
radius="16"></sa-image>
<div class="ml-2">
<div class="nickname sa-table-line-1">
{{ rewards.agent.nickname }}
</div>
<div class="id">#{{ rewards.agent.id }}</div>
</div>
</div>
<div v-else>#{{ rewards.agent_id }}</div>
</div>
<div>用户等级:等级{{ rewards.agent_level }}</div>
<div> 用户层级:{{ rewards.commission_level }}级分销 </div>
<div>
比例/佣金:
<template v-if="rewards.commission_rules">
<template v-if="rewards.commission_rules.rate">
{{ rewards.commission_rules.rate }}%
</template>
<template v-if="rewards.commission_rules.money">
{{ rewards.commission_rules.money }}元
</template>
</template>
</div>
<div class="rewards-status sa-flex">
佣金状态:
<span class="mr-1">{{rewards.status_text}}</span>
<template v-if="rewards.status == 0">
{if $auth->check('shopro/commission/order/confirm')}
<el-button type="primary" link size="small"
@click="onConfirm({commission_reward_id: rewards.id})">
手动结算</el-button>
{/if}
{if $auth->check('shopro/commission/order/cancel')}
<el-button class="ml-1" type="info" link
size="small"
@click="onCancel({commission_reward_id: rewards.id})">
取消
</el-button>
{/if}
</template>
<el-popconfirm v-if="rewards.status == 1"
width="fit-content" confirm-button-text="确认"
cancel-button-text="取消" title="确认?"
@confirm="onBack({commission_reward_id: rewards.id})">
<template #reference>
{if
$auth->check('shopro/commission/order/back')}
<el-button type="danger" link size="small">
手动退回
</el-button>
{/if}
</template>
</el-popconfirm>
</div>
<div>入账方式:{{ rewards.type_text }}</div>
<div class="sa-flex sa-col-top">
<span class="sa-flex-0">佣金金额:</span>
<div class="sa-flex sa-flex-wrap">
<template v-if="!rewardsPopover.flag[index]">
<span>{{ rewards.commission }}元</span>
{if
$auth->check('shopro/commission/order/edit')}
<el-button v-if="rewards.status == 0"
class="ml-1" type="primary" link
size="small"
@click="rewardsPopover.flag[index] = true">
修改
</el-button>
{/if}
</template>
<template v-if="rewardsPopover.flag[index]">
<el-input class="rewards-commission"
v-model="rewardsPopover.commission"
size="small">
<template #append></template>
</el-input>
<el-button class="ml-1" type="info" link
size="small"
@click="onCancelRewardsPopover(index)">取消
</el-button>
<el-button class="ml-1" type="primary" link
size="small"
@click="onConfirmRewardsPopover(index,rewards.id)">
确定</el-button>
</template>
<s v-if="rewards.original_commission != rewards.commission"
class="ml-1">
{{rewards.original_commission}}
</s>
</div>
</div>
</div>
<template #reference>
<div class="rewards-item sa-flex sa-flex-col sa-row-center">
<template v-if="rewards.agent">
<sa-image :url="rewards.agent.avatar" size="32"
radius="16" :ispreview="false"></sa-image>
</template>
<div v-if="!rewards.agent" class="rewards-agent-id">
{{ rewards.agent_id }}
</div>
<div class="commission mt-1"> {{ rewards.commission }}元
</div>
</div>
</template>
</el-popover>
</template>
</div>
</el-scrollbar>
</template>
</el-table-column>
<el-table-column min-width="80">
<template #default>
<!-- commission_reward_status -2=已退回|-1=已取消|0=未结算|1=已结算 -->
<span
:class="`sa-color--${state.statusStyle[props.row.commission_reward_status]}`">
{{ props.row.commission_reward_status_text }}
</span>
</template>
</el-table-column>
<el-table-column min-width="172">
<template #default>
<div>{{ props.row.reward_event_text }}</div>
{{ props.row.commission_time }}
</template>
</el-table-column>
<el-table-column min-width="110">
<template #default>
<div>{{ props.row.reward_type_text }}</div>
{{ props.row.amount }}元
</template>
</el-table-column>
<el-table-column min-width="100">
<template #default>
<!-- commission_order_status -2=已扣除|-1=已取消|0=不计入|1=已计入 -->
<span
:class="`sa-color--${state.statusStyle[props.row.commission_order_status]}`">
{{ props.row.commission_order_status_text }}
</span>
</template>
</el-table-column>
<el-table-column min-width="160">
<template #default>
{{ countRewards(props.row.rewards) }}
</template>
</el-table-column>
<el-table-column min-width="160">
<template #default>
<el-popover v-model:visible="commissionPopover.flag[props.$index]"
placement="top-start" :width="312" trigger="click">
<div class="commission-popover">
<div class="title sa-flex">
<el-icon class="sa-color--warning mr-1">
<question-filled />
</el-icon>
<template v-if="props.row.commission_reward_status == 0">
<template v-if="commissionPopover.type == 'confirm'">
手动提前结算,佣金将不再按结算方式自动执行。
</template>
<template v-if="commissionPopover.type == 'cancel'">
取消结算,佣金将不再结算。
</template>
</template>
<template v-if="props.row.commission_reward_status == 1">
您确定要手动退回佣金?
</template>
</div>
<div class="sa-flex sa-row-between">
<div>
<el-checkbox
v-if="commissionPopover.type == 'back' || commissionPopover.type == 'cancel'"
v-model="commissionPopover.isDelete" true-label="1"
false-label="0">扣除推广分销商业绩
</el-checkbox>
</div>
<div>
<el-button type="info" link size="small"
@click="onCancelCommissionPopover(props.$index)">
取消</el-button>
<el-button size="small" type="primary"
@click="onConfirmCommissionPopover(props.$index,props.row.id)">
确定</el-button>
</div>
</div>
</div>
<template #reference>
<div class="sa-flex">
<template v-if="props.row.commission_reward_status == 0">
{if $auth->check('shopro/commission/order/confirm')}
<el-button type="primary" link
@click="commissionPopover.type = 'confirm'">手动结算</el-button>
{/if}
{if $auth->check('shopro/commission/order/cancel')}
<el-button type="info" link
@click="commissionPopover.type = 'cancel'">
取消结算
</el-button>
{/if}
</template>
{if $auth->check('shopro/commission/order/back')}
<el-button v-if="props.row.commission_reward_status == 1"
type="danger" link @click="commissionPopover.type = 'back'">
手动退回
</el-button>
{/if}
</div>
</template>
</el-popover>
<template v-if="props.row.commission_reward_status < 0">-</template>
</template>
</el-table-column>
</el-table>
</template>
</el-table-column>
<el-table-column label="商品信息" min-width="300">
<template #default="scope">
<div class="order-content sa-flex">
<div class="id mr-4">ID{{ scope.row.id }}</div>
<template v-if="scope.row.order">
<div class="order-sn sa-flex mr-4">
订单号:{{ scope.row.order.order_sn }}
<el-icon class="copy-document" @click="onClipboard(scope.row.order.order_sn)">
<copy-document />
</el-icon>
</div>
<div class="mr-4">下单时间:{{ scope.row.order.createtime }}</div>
<div class="mr-4">订单状态:{{ scope.row.order.status_text }}</div>
</template>
</div>
</template>
</el-table-column>
<el-table-column label="退款状态" min-width="100"></el-table-column>
<el-table-column label="下单用户" min-width="100" align="center"></el-table-column>
<el-table-column label="推广分销商" min-width="100" align="center"></el-table-column>
<el-table-column label="佣金详情" min-width="200" align="center"></el-table-column>
<el-table-column label="佣金状态" min-width="80"></el-table-column>
<el-table-column label="结算方式/结算时间" min-width="172"></el-table-column>
<el-table-column label="商品结算金额" min-width="110"> </el-table-column>
<el-table-column label="分销商业绩" min-width="100"> </el-table-column>
<el-table-column label="分销总金额/到账金额" min-width="160">
</el-table-column>
<el-table-column label="操作" min-width="160">
<template #default="scope">
<el-button type="primary" link @click="onOpenOrderDetail(scope.row.order_id)">订单详情
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</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,59 @@
{include file="/shopro/common/script" /}
<div id="index" class="reward-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/commission/reward/export')}
<el-button :loading="exportLoading" :disabled="exportLoading" @click="onExport('export')">导出
</el-button>
{/if}
</div>
</div>
</el-header>
<el-main class="sa-main">
<el-table height="100%" class="sa-table" :data="state.data" stripe>
<el-table-column prop="id" label="ID" min-width="90"></el-table-column>
<el-table-column label="订单号" min-width="260">
<template #default="scope">
{{ scope.row.order?.order_sn || scope.row.order_id }}
</template>
</el-table-column>
<el-table-column label="下单用户" min-width="160">
<template #default="scope">
<sa-user-profile :user="scope.row.buyer" :id="scope.row.buyer_id"></sa-user-profile>
</template>
</el-table-column>
<el-table-column label="分销用户" min-width="160">
<template #default="scope">
<sa-user-profile :user="scope.row.agent" :id="scope.row.agent_id"></sa-user-profile>
</template>
</el-table-column>
<el-table-column label="分销金额" min-width="160">
<template #default="scope"> {{ scope.row.commission }}元 </template>
</el-table-column>
<el-table-column label="入账状态" min-width="80">
<template #default="scope">
<span :class="`sa-color--${state.statusStyle[scope.row.status]}`">
{{ scope.row.status_text }}
</span>
</template>
</el-table-column>
<el-table-column prop="type_text" label="入账方式" min-width="80"></el-table-column>
<el-table-column prop="commission_time" label="分佣时间" width="172"></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,25 @@
<link rel="stylesheet" href="//at.alicdn.com/t/c/font_2385137_b8qygb2jne.css?v={$site.version|htmlentities}">
<link rel="stylesheet" href="__CDN__/assets/addons/shopro/css/index.css?v={$site.version|htmlentities}">
{if condition="$DARK_TYPE neq 'none'" }
<link rel="stylesheet" href="__CDN__/assets/addons/shopro/css/dark.css?v={$site.version|htmlentities}" data-render="darktheme" />
{/if}
<link rel="stylesheet" href="__CDN__/assets/addons/shopro/libs/element-plus/index.css?v={$site.version|htmlentities}">
<script src="__CDN__/assets/addons/shopro/libs/vue.js?v={$site.version|htmlentities}"></script>
<script src="__CDN__/assets/addons/shopro/libs/element-plus/index.js?v={$site.version|htmlentities}"></script>
<script src="__CDN__/assets/addons/shopro/libs/element-plus/zh-cn.js?v={$site.version|htmlentities}"></script>
<script src="__CDN__/assets/addons/shopro/libs/element-plus/icons-vue.js?v={$site.version|htmlentities}"></script>
<script src="__CDN__/assets/addons/shopro/libs/sortable.js?v={$site.version|htmlentities}"></script>
<script src="__CDN__/assets/addons/shopro/libs/vuedraggable.js?v={$site.version|htmlentities}"></script>
<script src="__CDN__/assets/addons/shopro/libs/common.js?v={$site.version|htmlentities}"></script>
<script src="__CDN__/assets/addons/shopro/libs/clipboard.min.js?v={$site.version|htmlentities}"></script>
<script src="__CDN__/assets/addons/shopro/components/sa-image.js?v={$site.version|htmlentities}"></script>
<script src="__CDN__/assets/addons/shopro/components/sa-uploader.js?v={$site.version|htmlentities}"></script>
<script src="__CDN__/assets/addons/shopro/components/sa-user-profile.js?v={$site.version|htmlentities}"></script>
<script src="__CDN__/assets/addons/shopro/components/sa-filter.js?v={$site.version|htmlentities}"></script>
<script src="__CDN__/assets/addons/shopro/components/sa-filter-condition.js?v={$site.version|htmlentities}"></script>
<script src="__CDN__/assets/addons/shopro/components/sa-pagination.js?v={$site.version|htmlentities}"></script>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,182 @@
{include file="/shopro/common/script" /}
<style>
.config-platform .el-select {
flex: 1;
}
.config-platform .title {
width: 100%;
padding: 10px 0 10px 16px;
background: var(--sa-background-hex-hover);
font-weight: 500;
font-size: 14px;
color: var(--sa-subtitle);
margin: 0 0 16px;
display: flex;
align-items: center;
}
.config-platform .title-h5 {
margin-left: 20px;
}
.config-platform .pay-tip {
font-weight: 400;
font-size: 14px;
line-height: 20px;
color: var(--sa-subtitle);
margin-left: 16px;
}
</style>
<div id="platform" class="config-platform" v-cloak>
<el-container class="panel-block">
<el-main>
<el-scrollbar height="100%">
<el-form ref="formRef" :model="form.model" :rules="form.rules" label-width="100px">
<div class="title">状态</div>
<el-form-item label="状态">
<el-switch v-model="form.model.status" :active-value="1" :inactive-value="0"></el-switch>
<span class="label-tip" :class="form.model.status == 1 ? 'sa-color--primary' : ''">
{{form.model.status == 0 ? '关闭' : '开启'}}</span>
</el-form-item>
<div class="title">支付配置<span class="pay-tip">启用货到付款后,请自行安排合作快递完成收款和结算</span> </div>
<el-form-item label="支付方式">
<el-checkbox-group v-model="form.model.payment.methods">
<el-checkbox label="wechat">微信</el-checkbox>
<el-checkbox label="alipay">支付宝</el-checkbox>
<el-checkbox label="money">余额</el-checkbox>
<el-checkbox label="offline">货到付款</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item v-if="form.model.payment.methods.includes('wechat')" label="微信" prop="payment.wechat">
<div class="sa-w-360">
<el-select v-model="form.model.payment.wechat" placeholder="请选择">
<el-option v-for="item in payConfig.select.wechat" :key="item.id" :label="item.name"
:value="item.id">
</el-option>
</el-select>
<el-button class="label-tip" type="primary" link @click="onAddPayConfig"> 添加支付方式
</el-button>
</div>
</el-form-item>
<el-form-item v-if="form.model.payment.methods.includes('alipay')" label="支付宝"
prop="payment.alipay">
<div class="sa-w-360">
<el-select v-model="form.model.payment.alipay" placeholder="请选择">
<el-option v-for="item in payConfig.select.alipay" :key="item.id" :label="item.name"
:value="item.id">
</el-option>
</el-select>
<el-button class="label-tip" type="primary" link @click="onAddPayConfig"> 添加支付方式
</el-button>
</div>
</el-form-item>
<div class="title">
{{state.platform == 'H5' ? '微信H5' : state.label}}平台设置
<div v-if="state.platform == 'H5'" class="title-h5">
如使用微信支付请在此输入已开通微信H5支付的Appid
</div>
</div>
<el-form-item label="Appid" prop="app_id">
<div class="sa-w-360">
<el-input v-model="form.model.app_id" placeholder="请输入Appid"></el-input>
<el-button v-if="state.platform=='H5' || state.platform=='App'" class="label-tip"
type="primary" link @click="onConfiguration">查看配置引导</el-button>
</div>
</el-form-item>
<el-form-item label="AppSecret" prop="secret" v-if="state.platform != 'H5'">
<el-input class="sa-w-360" v-model="form.model.secret" placeholder="请输入AppSecret"></el-input>
</el-form-item>
<div v-if="state.platform != 'H5'">
<div class="title">微信登录设置</div>
<el-form-item v-if="state.platform != 'App'" label="自动登录">
<div class="sa-flex">
<el-switch v-model="form.model.auto_login" :active-value="1" :inactive-value="0">
</el-switch>
<span class="label-tip" :class="form.model.auto_login == 1 ? 'sa-color--primary' : ''">
{{form.model.auto_login == 0 ? '关闭' : '开启'}}</span>
<div v-if="state.platform == 'WechatMiniProgram'" class="tip label-tip"> 进入应用后,已注册用户将会自动登录,未注册用户需手动授权 </div>
<div v-if="state.platform == 'WechatOfficialAccount'" class="tip label-tip"> 进入应用后,用户将会自动授权登录,未注册用户将会自动注册 </div>
</div>
</el-form-item>
<el-form-item label="绑定手机号">
<div class="sa-flex">
<el-switch v-model="form.model.bind_mobile" :active-value="1" :inactive-value="0">
</el-switch>
<span class="label-tip" :class="form.model.bind_mobile == 1 ? 'sa-color--primary' : ''">
{{form.model.bind_mobile == 0 ? '关闭' : '开启'}}</span>
<div class="tip label-tip"> 授权登录后,未绑定手机号的用户,将会立即提醒绑定手机号 </div>
</div>
</el-form-item>
</div>
<div v-if="state.platform == 'App'">
<div class="title">APP下载</div>
<el-form-item label="Android地址">
<el-input class="sa-w-360" v-model="form.model.download.android"
placeholder="请输入Android下载地址"></el-input>
</el-form-item>
<el-form-item label="IOS地址">
<el-input class="sa-w-360" v-model="form.model.download.ios" placeholder="请输入IOS下载地址">
</el-input>
</el-form-item>
<el-form-item label="本地地址">
<el-input class="sa-w-360" v-model="form.model.download.local" placeholder="请输入本地地址">
</el-input>
</el-form-item>
</div>
<template v-if="form.model.share">
<div class="title">分享设置</div>
<el-form-item label="分享方式">
<el-checkbox-group v-model="form.model.share.methods">
<el-checkbox label="forward" disabled>直接转发</el-checkbox>
<el-checkbox label="poster">分享海报</el-checkbox>
<el-checkbox label="link">复制链接</el-checkbox>
</el-checkbox-group>
</el-form-item>
<template v-if="form.model.share.methods.includes('forward')">
<el-form-item label="标题">
<el-input class="sa-w-360" v-model="form.model.share.forwardInfo.title"
placeholder="请输入分享标题"></el-input>
</el-form-item>
<el-form-item label="副标题">
<el-input class="sa-w-360" v-model="form.model.share.forwardInfo.subtitle"
placeholder="请输入分享副标题">
</el-input>
</el-form-item>
<el-form-item label="分享图片">
<sa-uploader v-model="form.model.share.forwardInfo.image">
</sa-uploader>
</el-form-item>
</template>
<template v-if="form.model.share.methods.includes('poster')">
<el-form-item label="用户海报">
<sa-uploader v-model="form.model.share.posterInfo.user_bg">
</sa-uploader>
</el-form-item>
<el-form-item label="商品海报">
<sa-uploader v-model="form.model.share.posterInfo.goods_bg">
</sa-uploader>
</el-form-item>
<el-form-item label="拼团海报">
<sa-uploader v-model="form.model.share.posterInfo.groupon_bg">
</sa-uploader>
</el-form-item>
</template>
<el-form-item label="分享Url">
<div class="sa-form-wrap">
<el-input class="sa-w-360" v-model="form.model.share.linkAddress"
placeholder="请输入分享Url"></el-input>
<div class="tip">分享链接的默认域名</div>
</div>
</el-form-item>
</template>
</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,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>

View File

@@ -0,0 +1,382 @@
{include file="/shopro/common/script" /}
<script src="__CDN__/assets/addons/shopro/libs/echarts.min.js?v={$site.version|htmlentities}"></script>
<style>
.dashboard-index .panel-block {
/* background: #f1f4f6; */
}
.dashboard-index .dashboard-index-main {
--el-main-padding: 0;
}
.dashboard-index .el-scrollbar__wrap {
overflow-x: hidden;
}
.dashboard-index .el-scrollbar__bar.is-horizontal {
display: none;
}
.dashboard-index #userTotal,
.dashboard-index #agentTotal,
.dashboard-index #shareTotal {
width: 100%;
height: 66px;
}
.dashboard-index .card {
line-height: 1;
background: var(--sa-background-assist);
border-radius: 8px;
border: 1px solid var(--sa-space);
box-shadow: 0 2px 6px rgb(140 140 140 / 12%);
padding: 12px;
font-size: 12px;
color: var(--sa-font);
margin-bottom: 20px;
}
.dashboard-index .card:hover {
transition: all .2s;
}
@media screen and (min-width: 1200px) {
.dashboard-index .scale-card:hover {
transform: scale(1.05);
}
}
.dashboard-index .card .card-title .left {
font-size: 14px;
color: var(--sa-subtitle);
}
.dashboard-index .card .card-title .left .num {
font-size: 16px;
}
.dashboard-index .card .card-footer {
margin-top: 12px;
}
.dashboard-index .card .card-footer .left {
margin-right: 8px;
}
.dashboard-index .card .card-footer .dot {
width: 6px;
height: 6px;
border-radius: 50%;
display: inline-block;
margin-right: 8px;
}
.dashboard-index .bar-card {
min-height: 358px;
}
.dashboard-index #chartContent {
width: 100%;
height: 296px;
}
.dashboard-index .tab-item {
height: 32px;
line-height: 32px;
margin-right: 20px;
font-size: 14px;
color: var(--sa-subfont);
cursor: pointer;
}
.dashboard-index .tab-item:last-of-type {
margin-right: 0;
}
.dashboard-index .tab-item.is-active {
color: var(--sa-subtitle);
font-weight: bold;
}
@media only screen and (max-width: 768px) {
.dashboard-index .date-time .el-date-editor {
--el-date-editor-datetimerange-width: 320px;
}
}
.dashboard-index .chart-card {
height: 106px;
color: var(--sa-subfont);
}
.dashboard-index .chart-card .card-icon {
width: 24px;
height: 24px;
}
.dashboard-index .chart-card .num {
font-size: 24px;
color: var(--sa-subtitle);
}
.dashboard-index .chart-card .warning {
color: var(--el-color-warning);
}
.dashboard-index .goods-card,
.dashboard-index .hot-search-card {
height: 326px;
}
.dashboard-index .goods-card .header,
.dashboard-index .hot-search-card .header {
line-height: 16px;
font-size: 14px;
color: var(--sa-subtitle);
margin-bottom: 16px;
}
.dashboard-index .top {
width: 18px;
height: 20px;
}
.dashboard-index #rankingContent {
width: 192px;
height: 192px;
}
</style>
<div id="index" class="dashboard-index panel panel-default panel-intro" v-cloak>
<el-container class="panel-block">
<el-main class="dashboard-index-main">
<el-scrollbar height="100%">
{if $auth->check('shopro/dashboard/total')}
<el-row :gutter="20">
<!-- -- commission code start -- -->
<el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8">
<div class="scale-card card ">
<div class="card-title sa-flex sa-row-between">
<div class="left">{{state.total.user.title}} <span
class="num">{{state.total.user.data.total}}</span> </div>
<div>{{state.total.user.tip}} <span>{{state.total.user.data.today}}</span> </div>
</div>
<div id="userTotal"></div>
<div class="card-footer sa-flex">
<span class="left sa-flex">
<span class="dot" :style="{ background: state.total.user.color }"></span>
<span>{{ state.total.user.footer }}</span>
</span>
<span>{{ state.total.user.data.week }}</span>
</div>
</div>
</el-col>
<el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8">
<div class="scale-card card ">
<div class="card-title sa-flex sa-row-between">
<div class="left">{{state.total.agent.title}} <span
class="num">{{state.total.agent.data.total}}</span> </div>
<div>{{state.total.agent.tip}} <span>{{state.total.agent.data.today}}</span> </div>
</div>
<div id="agentTotal"></div>
<div class="card-footer sa-flex">
<span class="left sa-flex">
<span class="dot" :style="{ background: state.total.agent.color }"></span>
<span>{{ state.total.agent.footer }}</span>
</span>
<span>{{ state.total.agent.data.week }}</span>
</div>
</div>
</el-col>
<el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8">
<div class="scale-card card ">
<div class="card-title sa-flex sa-row-between">
<div class="left">{{state.total.share.title}} <span
class="num">{{state.total.share.data.total}}</span> </div>
<div>{{state.total.share.tip}} <span>{{state.total.share.data.today}}</span> </div>
</div>
<div id="shareTotal"></div>
<div class="card-footer sa-flex">
<span class="left sa-flex">
<span class="dot" :style="{ background: state.total.share.color }"></span>
<span>{{ state.total.share.footer }}</span>
</span>
<span>{{ state.total.share.data.week }}</span>
</div>
</div>
</el-col>
<!-- -- commission code end -- -->
<!-- <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="scale-card card ">
<div class="card-title sa-flex sa-row-between">
<div class="left">{{state.total.user.title}} <span
class="num">{{state.total.user.data.total}}</span> </div>
<div>{{state.total.user.tip}} <span>{{state.total.user.data.today}}</span> </div>
</div>
<div id="userTotal"></div>
<div class="card-footer sa-flex">
<span class="left sa-flex">
<span class="dot" :style="{ background: state.total.user.color }"></span>
<span>{{ state.total.user.footer }}</span>
</span>
<span>{{ state.total.user.data.week }}</span>
</div>
</div>
</el-col>
<el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
<div class="scale-card card ">
<div class="card-title sa-flex sa-row-between">
<div class="left">{{state.total.share.title}} <span
class="num">{{state.total.share.data.total}}</span> </div>
<div>{{state.total.share.tip}} <span>{{state.total.share.data.today}}</span> </div>
</div>
<div id="shareTotal"></div>
<div class="card-footer sa-flex">
<span class="left sa-flex">
<span class="dot" :style="{ background: state.total.share.color }"></span>
<span>{{ state.total.share.footer }}</span>
</span>
<span>{{ state.total.share.data.week }}</span>
</div>
</div>
</el-col> -->
</el-row>
{/if}
{if $auth->check('shopro/dashboard/chart')}
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="24" :lg="16" :xl="16">
<div class="bar-card card">
<div class="sa-flex sa-row-between sa-flex-wrap">
<div class="sa-flex">
<div class="tab-item" :class="chart.tabActive == key ? 'is-active' : ''"
v-for="(value, key) in chart.tabsData" :key="key"
@click="onChangeTabActive(key)">
{{ value }}
</div>
</div>
<div class="date-time">
<el-date-picker v-model="chart.dateTime" 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="结束日期"
:shortcuts="chart.shortcuts" @change="onChangeDateTime" :editable="false">
</el-date-picker>
</div>
</div>
<div id="chartContent"></div>
</div>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="8" :xl="8">
<el-row :gutter="20">
<el-col :xs="12" :sm="8" :md="12" :lg="12" :xl="12" v-for="(value, key) in statistics"
:key="key">
<div class="chart-card scale-card card">
<div class="sa-flex sa-row-between mb-2">
<img class="card-icon"
:src="`/assets/addons/shopro/img/dashboard/${key}.png`" />
<div class="sa-flex" @click="onOpen(value.status)">
<el-button type="info" link size="small">详情
<el-icon class="ml-1">
<arrow-right />
</el-icon>
</el-button>
</div>
</div>
<div class="num mb-1">{{ value.num }}</div>
<div class="sa-flex sa-row-between">
<span>{{ value.text }}</span>
<el-popover popper-class="sa-popper" placement="top" trigger="hover"
:content="value.tip">
<template #reference>
<el-icon class="warning">
<Warning />
</el-icon>
</template>
</el-popover>
</div>
</div>
</el-col>
</el-row>
</el-col>
</el-row>
{/if}
{if $auth->check('shopro/dashboard/ranking')}
<el-row :gutter="20">
<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
<div class="goods-card card">
<div class="header">
<span>销量榜</span>
</div>
<el-table class="sa-table" :data="ranking.goods" stripe>
<el-table-column label="排名" width="60" align="center">
<template #default="scope">
<img class="top"
:src="`/assets/addons/shopro/img/dashboard/top${scope.$index + 1}.png`" />
</template>
</el-table-column>
<el-table-column label="名称" min-width="200">
<template #default="scope">
<div class="sa-flex">
<sa-image :url="scope.row.image" size="20"></sa-image>
<div class="ml-2 sa-table-line-1">
{{ scope.row.title || '-' }}
</div>
</div>
</template>
</el-table-column>
<el-table-column label="销量" width="100">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.real_sales || '-' }}
</div>
</template>
</el-table-column>
</el-table>
</div>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12">
<div class="hot-search-card card">
<div class="header">
<span>热搜榜</span>
</div>
<el-row :gutter="16">
<el-col :xs="24" :sm="24" :md="16" :lg="16" :xl="16">
<el-table class="sa-table" :data="ranking.hot_search" stripe>
<el-table-column label="排名" width="60" align="center">
<template #default="scope">
<img class="top"
:src="`/assets/addons/shopro/img/dashboard/top${scope.$index + 1}.png`" />
</template>
</el-table-column>
<el-table-column label="名称" min-width="200">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.keyword || '-' }}
</div>
</template>
</el-table-column>
<el-table-column label="搜索量(次)" width="100">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.num }}
</div>
</template>
</el-table-column>
</el-table>
</el-col>
<el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8">
<div class="sa-flex sa-row-center">
<div id="rankingContent"></div>
</div>
</el-col>
</el-row>
</div>
</el-col>
</el-row>
{/if}
</el-scrollbar>
</el-main>
</el-container>
</div>

View File

@@ -0,0 +1,29 @@
{include file="/shopro/common/script" /}
<div id="addEdit" class="area-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="pid">
<el-cascader class="sa-w-360" v-model="form.model.pid" :options="area.select" :props="{
label: 'name',
value: 'id',
checkStrictly: true,
emitPath: false,
}" clearable placeholder="请选择上级行政区"></el-cascader>
</el-form-item>
<el-form-item label="行政区ID" prop="id">
<el-input class="sa-w-360" v-model="form.model.id" placeholder="请输入行政区ID"></el-input>
</el-form-item>
<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>
</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,108 @@
{include file="/shopro/common/script" /}
<style>
.area-index .sa-title .tip {
margin-left: 8px;
font-weight: 400;
font-size: 12px;
color: var(--sa-subfont);
}
.area-index .sa-title .tip a {
color: var(--sa-subfont);
text-decoration: underline;
}
.area-index .tree-header {
height: 40px;
padding-left: 20px;
background: var(--sa-table-header-bg);
}
.area-index .tree-content .el-tree-node__content {
height: 48px;
}
.area-index .tree-content .el-tree-node__label {
flex: 1;
}
.area-index .tree-header .left,
.area-index .tree-content .left {
flex: 1;
}
.area-index .tree-header .id,
.area-index .tree-content .id {
margin-right: 12px;
color: #999;
}
.area-index .tree-header .level,
.area-index .tree-header .oper,
.area-index .tree-content .level,
.area-index .tree-content .oper {
flex-shrink: 0;
width: 120px;
}
</style>
<div id="index" class="area-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-flex-wrap sa-row-between">
<div class="sa-title-left">
<div class="left-name">省市区</div>
<div class="tip">
数据来源:
<a href="http://www.stats.gov.cn/sj/tjbz/tjyqhdmhcxhfdm/2022/" target="_blank">
2022年国家统计局区划代码
</a>
更新时间2022-10-31
</div>
</div>
<div class="sa-title-right">
<el-button class="sa-button-refresh" icon="RefreshRight" @click="getData"></el-button>
{if $auth->check('shopro/data/area/add')}
<el-button icon="Plus" type="primary" @click="onAdd">添加</el-button>
{/if}
</div>
</div>
</el-header>
<el-main class="sa-main">
<el-scrollbar height="100%">
<div class="tree-header sa-flex">
<div class="left">名称</div>
<div class="level">级别</div>
<div class="oper">操作</div>
</div>
<el-tree class="tree-content" :data="state.data" node-key="id" ref="accessTree">
<template #default="{ node, data }">
<div class="tree-item sa-flex">
<div class="left sa-flex">
<div class="id"> #{{ data.id }} </div>
<div class="name">{{ data.name }}</div>
</div>
<div class="level">
{{ data.level == 'province' ? '省级' : data.level == 'city' ? '市级' : '区级' }}
</div>
<div class="oper">
{if $auth->check('shopro/data/area/edit')}
<el-button type="primary" link @click.stop="onEdit(node.data.id)">编辑</el-button>
{/if}
<el-popconfirm width="fit-content" confirm-button-text="确认" cancel-button-text="取消"
title="确认删除这条记录?" @confirm="onDelete(node.data.id)">
<template #reference>
{if $auth->check('shopro/data/area/delete')}
<el-button type="danger" link @click.stop>删除</el-button>
{/if}
</template>
</el-popconfirm>
</div>
</div>
</template>
</el-tree>
</el-scrollbar>
</el-main>
</el-container>
</div>

View File

@@ -0,0 +1,19 @@
{include file="/shopro/common/script" /}
<div id="select" class="area-select" v-cloak>
<el-container class="panel-block">
<el-main>
<el-scrollbar height="100%">
<el-checkbox v-model="state.checkedAll" :indeterminate="isIndeterminate" label="全选" @change="onChange">
</el-checkbox>
<el-tree :data="state.data" node-key="id" show-checkbox :default-checked-keys="state.ids"
@check-change="onChangeCheck" ref="treeRef">
<template #default="{ data }">{{ data.name }}</template>
</el-tree>
</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,24 @@
{include file="/shopro/common/script" /}
<div id="addEdit" class="express-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="快递编码" prop="code">
<el-input class="sa-w-360" v-model="form.model.code" placeholder="请输入快递编码"></el-input>
</el-form-item>
<el-form-item label="权重" prop="weigh">
<el-input class="sa-w-360" v-model="form.model.weigh" placeholder="请输入权重" type="number"></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,77 @@
{include file="/shopro/common/script" /}
<div id="index" class="express-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/data/express/add')}
<el-button icon="Plus" type="primary" @click="onAdd">添加</el-button>
{/if}
</div>
</div>
<el-alert class="mb-3" type="warning">
<template #title>快递鸟所有快递公司列表,可以只保留自己需要的,删除多余的快递公司</template>
</el-alert>
</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="200">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.name || '-' }}
</div>
</template>
</el-table-column>
<el-table-column label="快递编码" min-width="140">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.code || '-' }}
</div>
</template>
</el-table-column>
<el-table-column prop="weigh" label="权重" min-width="100" sortable="custom">
</el-table-column>
<el-table-column fixed="right" label="操作" min-width="120">
<template #default="scope">
{if $auth->check('shopro/data/express/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/data/express/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/data/express/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>
<sa-filter v-model="state.filter" @filter-change="onChangeFilter"></sa-filter>
</div>

View File

@@ -0,0 +1,45 @@
{include file="/shopro/common/script" /}
<div id="addEdit" class="fake-user-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="avatar">
<sa-uploader v-model="form.model.avatar" fileType="image"></sa-uploader>
</el-form-item>
<el-form-item label="用户名" prop="username">
<el-input class="sa-w-360" v-model="form.model.username" placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item label="用户昵称" prop="nickname">
<el-input class="sa-w-360" v-model="form.model.nickname" placeholder="请输入用户昵称"></el-input>
</el-form-item>
<el-form-item label="电子邮箱" prop="email">
<el-input class="sa-w-360" v-model="form.model.email" placeholder="请输入电子邮箱"></el-input>
</el-form-item>
<el-form-item label="手机号" prop="mobile">
<el-input class="sa-w-360" v-model="form.model.mobile" placeholder="请输入手机号"></el-input>
</el-form-item>
<el-form-item label="用户密码">
<el-input class="sa-w-360" v-model="form.model.password" placeholder="不修改请留空"></el-input>
</el-form-item>
<el-form-item label="用户性别">
<el-radio-group v-model="form.model.gender">
<el-radio :label="0"></el-radio>
<el-radio :label="1"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="state.type == 'edit'" label="创建时间">
{{ form.model.createtime }}
</el-form-item>
<el-form-item v-if="state.type == 'edit'" label="更新时间">
{{ form.model.updatetime }}
</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,96 @@
{include file="/shopro/common/script" /}
<div id="index" class="fake-user-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/data/fake_user/add')}
<el-button icon="Plus" type="primary" @click="onAdd">添加</el-button>
{/if}
{if $auth->check('shopro/data/fake_user/random')}
<el-button @click="onRandom">自动生成</el-button>
{/if}
</div>
</div>
<el-alert class="mb-3" type="warning">
<template #title>
<div>1、可作为虚拟成团时候的虚拟用户和虚拟评价时候的虚拟用户</div>
<div>2、添加完之后可修改虚拟用户信息不要轻易删除虚拟用户</div>
</template>
</el-alert>
</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="180">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.username || '-' }}
</div>
</template>
</el-table-column>
<el-table-column label="用户信息" min-width="180">
<template #default="scope">
<sa-user-profile :user="scope.row" :id="scope.row.id" />
</template>
</el-table-column>
<el-table-column label="电子邮箱" min-width="170">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.email || '-' }}
</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/data/fake_user/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/data/fake_user/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/data/fake_user/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>
<sa-filter v-model="state.filter" @filter-change="onChangeFilter"></sa-filter>
</div>

View File

@@ -0,0 +1,18 @@
{include file="/shopro/common/script" /}
<div id="random" class="fake-user-random" 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="num">
<el-input v-model="form.model.num" placeholder="请输入生成虚拟人数" type="number" min="0"></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,31 @@
{include file="/shopro/common/script" /}
<div id="select" class="fake-user-select" v-cloak>
<el-container class="panel-block">
<el-main>
<el-table height="100%" class="sa-table" :data="state.data" stripe>
<el-table-column prop="id" label="ID" min-width="90"> </el-table-column>
<el-table-column label="用户名" min-width="180">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.username || '-' }}
</div>
</template>
</el-table-column>
<el-table-column label="用户信息" min-width="180">
<template #default="scope">
<sa-user-profile :user="scope.row" :id="scope.row.id" />
</template>
</el-table-column>
<el-table-column fixed="right" label="操作" min-width="120">
<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-footer sa-flex sa-row-right">
<sa-pagination class="is-ellipsis" v-model="pagination" @pagination-change="getData"></sa-pagination>
</el-footer>
</el-container>
</div>

View File

@@ -0,0 +1,28 @@
{include file="/shopro/common/script" /}
<div id="addEdit" class="faq-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="title">
<el-input class="sa-w-360" v-model="form.model.title" placeholder="请输入标题"></el-input>
</el-form-item>
<el-form-item label="内容" prop="content">
<el-input class="sa-w-360" type="textarea" v-model="form.model.content" placeholder="请输入内容">
</el-input>
</el-form-item>
<el-form-item label="状态" required>
<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>
</div>

View File

@@ -0,0 +1,97 @@
{include file="/shopro/common/script" /}
<div id="index" class="faq-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/data/faq/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="100">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.title || '-' }}
</div>
</template>
</el-table-column>
<el-table-column label="内容" min-width="140">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.content || '-' }}
</div>
</template>
</el-table-column>
<el-table-column label="状态" min-width="100">
<template #default="scope">
<el-tag :type="scope.row.status == 'normal' ? 'success' : 'info'">
{{ scope.row.status_text }}
</el-tag>
</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/data/faq/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/data/faq/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/data/faq/delete')}
<el-button type="danger" :disabled="!batchHandle.data.length" @click="onBatchHandle('delete')">删除
</el-button>
{/if}
{if $auth->check('shopro/data/faq/edit')}
<el-button type="success" :disabled="!batchHandle.data.length" @click="onBatchHandle('normal')">正常
</el-button>
{/if}
{if $auth->check('shopro/data/faq/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,24 @@
{include file="/shopro/common/script" /}
<div id="addEdit" class="page-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="路径" prop="path">
<el-input class="sa-w-360" v-model="form.model.path" placeholder="请输入路径"></el-input>
</el-form-item>
<el-form-item label="分组" prop="group">
<el-input class="sa-w-360" v-model="form.model.group" 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,86 @@
{include file="/shopro/common/script" /}
<div id="index" class="page-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/data/page/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="200">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.name || '-' }}
</div>
</template>
</el-table-column>
<el-table-column label="路径" min-width="340">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.path || '-' }}
</div>
</template>
</el-table-column>
<el-table-column label="分组" min-width="100">
<template #default="scope">
<div class="sa-table-line-1">
{{ scope.row.group || '-' }}
</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/data/page/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/data/page/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/data/page/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>
<sa-filter v-model="state.filter" @filter-change="onChangeFilter"></sa-filter>
</div>

View File

@@ -0,0 +1,123 @@
{include file="/shopro/common/script" /}
<style>
.page-select .page-select-main {
--el-main-padding: 0;
}
.page-select .el-aside {
--el-aside-width: 140px;
border-right: 1px solid var(--sa-border);
padding: 20px;
}
.page-select .top {
height: 100%;
}
.page-select .group .name {
margin: 0 0 12px 12px;
}
.page-select .group .link {
margin-bottom: 12px;
}
.page-select .group .link .item {
padding: 0 16px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid var(--sa-border);
border-radius: 4px;
margin: 0 12px 12px 0;
font-size: 14px;
font-weight: 400;
color: var(--sa-font);
cursor: pointer;
}
.page-select .group .link .item:hover {
color: var(--el-color-primary);
background: var(--t-bg-hover);
}
.page-select .group .link .item.item-active {
color: var(--el-color-primary);
background: var(--t-bg-active);
}
.page-select .left .group {
height: 32px;
line-height: 32px;
border-radius: 4px;
font-size: 14px;
font-weight: 400;
color: var(--sa-subtitle);
margin-bottom: 4px;
cursor: pointer;
}
.page-select .left .group:hover {
color: var(--el-color-primary);
background: var(--t-bg-hover);
}
.page-select .left .group.is-active {
color: var(--el-color-primary);
background: var(--t-bg-active);
}
.page-select .right .name {
line-height: 16px;
font-size: 14px;
font-weight: 600;
color: var(--sa-subtitle);
margin: 0 0 12px 0;
}
.page-select .right-group .link {
border-bottom: 1px dashed var(--sa-border);
}
</style>
<div id="select" class="page-select" v-cloak>
<el-container class="panel-block">
<el-main class="page-select-main">
<el-container class="top">
<el-aside>
<el-scrollbar class="left" height="100%">
<div class="group" :class="state.currentIndex == i ? 'is-active' : ''"
v-for="(g, i) in state.data" :key="g" @click.stop="onChangeIndex(i)">
<div class="name">{{ g.group }}</div>
</div>
</el-scrollbar>
</el-aside>
<el-main>
<el-scrollbar class="right" ref="rightScrollRef" height="100%" @scroll="onRightScroll">
<div class="group right-group" :ref="(el) => setRightRef(el, g, i)" v-for="(g, i) in state.data"
:key="g">
<div class="name">{{ g.group }}</div>
<div class="link sa-flex sa-flex-wrap">
<template v-for="l in g.children" :key="l">
<el-popover popper-class="sa-popper" trigger="hover" :content="l.path">
<template #reference>
<div class="item" :class="state.selected.id == l.id ? 'item-active' : ''"
@click="onSelect(l)">
{{ l.name }}
</div>
</template>
</el-popover>
</template>
</div>
</div>
</el-scrollbar>
</el-main>
</el-container>
</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>

Some files were not shown because too many files have changed in this diff Show More