修复内容

This commit is contained in:
2026-01-30 18:48:13 +08:00
parent 5fe5289e26
commit 76cfa6b278
25 changed files with 943 additions and 289 deletions

View File

@@ -6,6 +6,7 @@ use app\admin\model\OrderRecharge;
use app\admin\model\OrderYearcard;
use app\admin\model\User;
use app\common\server\UrlServer;
use think\Db;
use think\facade\Url;
use app\admin\model\Order;
@@ -15,6 +16,14 @@ class BulletinBoard extends AdminBase
//看板统计
public function index()
{
// 本月与上月时间范围
$monthStart = date('Y-m-01 00:00:00');
$monthEnd = date('Y-m-t 23:59:59');
$lastMonthStart = date('Y-m-01 00:00:00', strtotime('-1 month'));
$lastMonthEnd = date('Y-m-t 23:59:59', strtotime('-1 month'));
$monthStartTs = strtotime($monthStart);
$monthEndTs = strtotime($monthEnd);
//查询商品订单
$orderMoney = Order::where('status','<>', 0)->sum('order_amount');
//年卡订单
@@ -104,6 +113,243 @@ class BulletinBoard extends AdminBase
// 本月注册但没下过单的(新客户)
$newCustomerCount = count($monthUsers) - $oldCustomerCount;
}
// ========== 目标完成率与客服进度 ==========
// 销售目标(可以后续做成后台可配置,这里先写死为 100000
$monthlyTarget = 100000;
$overallCompletion = $monthlyTarget > 0 ? round(($monthlySales / $monthlyTarget) * 100, 2) : 0;
// 按客服统计本月与上月销售额
$staffCurrent = Db::name('order')
->alias('o')
->join('admin a', 'o.admin_id = a.id', 'LEFT')
->where('o.status', '<>', 0)
->whereTime('o.create_time', 'between', [$monthStart, $monthEnd])
->field('o.admin_id,a.name as staff_name,SUM(o.order_amount) as total')
->group('o.admin_id')
->select();
$staffLast = Db::name('order')
->alias('o')
->join('admin a', 'o.admin_id = a.id', 'LEFT')
->where('o.status', '<>', 0)
->whereTime('o.create_time', 'between', [$lastMonthStart, $lastMonthEnd])
->field('o.admin_id,SUM(o.order_amount) as total')
->group('o.admin_id')
->select();
$staffLastMap = [];
foreach ($staffLast as $row) {
$staffLastMap[$row['admin_id']] = $row['total'];
}
$staffProgress = [];
foreach ($staffCurrent as $row) {
$adminId = $row['admin_id'];
$staffSales = (float)$row['total'];
$lastSales = isset($staffLastMap[$adminId]) ? (float)$staffLastMap[$adminId] : 0;
$percent = $monthlySales > 0 ? round(($staffSales / $monthlySales) * 100, 2) : 0;
$yoy = $lastSales > 0 ? round((($staffSales - $lastSales) / $lastSales) * 100, 2) : 0;
$staffProgress[] = [
'name' => $row['staff_name'] ?: '未分配',
'sales' => $staffSales,
'percent' => $percent,
'yoy' => $yoy,
];
}
// ========== 渠道分析(当月订单数按渠道) ==========
$channelRows = Db::name('order')
->alias('o')
->join('orderchannel c', 'o.channel_id = c.id', 'LEFT')
->where('o.status', '<>', 0)
->whereTime('o.create_time', 'month')
->field('c.name as channel_name, COUNT(*) as total')
->group('o.channel_id')
->select();
$channelPie = [];
foreach ($channelRows as $row) {
$name = $row['channel_name'] ?: '其他';
$value = (int)$row['total'];
$channelPie[] = [
'name' => $name,
'value' => $value,
];
}
// ========== 每日销售趋势(仅商品订单,按天汇总) ==========
$trendRows = Db::name('order')
->where('status', '<>', 0)
->whereTime('create_time', 'between', [$monthStart, $monthEnd])
->field("FROM_UNIXTIME(create_time,'%Y-%m-%d') as day, SUM(order_amount) as total")
->group('day')
->order('day asc')
->select();
$trendDates = [];
$trendValues = [];
$trendTotal = 0;
foreach ($trendRows as $row) {
$trendDates[] = $row['day'];
$amount = (float)$row['total'];
$trendValues[] = $amount;
$trendTotal += $amount;
}
// 上月总销售额(用于计算趋势图上的“上月同比”)
$lastTrendTotal = Db::name('order')
->where('status', '<>', 0)
->whereTime('create_time', 'between', [$lastMonthStart, $lastMonthEnd])
->sum('order_amount');
$trendCompare = $lastTrendTotal > 0 ? round((($trendTotal - $lastTrendTotal) / $lastTrendTotal) * 100, 2) : 0;
// ========== 区域月销售额(通过地址模糊匹配简单统计) ==========
$regions = ['南明区', '云岩区', '白云区', '乌当区', '花溪区', '龙里'];
$regionTotals = [];
foreach ($regions as $regionName) {
$total = Db::name('order')
->where('status', '<>', 0)
->whereTime('create_time', 'month')
->whereLike('address', '%' . $regionName . '%')
->sum('order_amount');
$regionTotals[] = (float)$total;
}
// ========== 本月销售情况(单次/年卡/次卡/其它服务) ==========
// 复用统计图表控制器中的规则:根据 number 字段区分不同卡类型
$salesSituation = [
['value' => 0, 'name' => '单次服务'],
['value' => 0, 'name' => '年卡销量'],
['value' => 0, 'name' => '次卡销量'],
['value' => 0, 'name' => '其它服务'],
];
$kaWhere = [
['del', '=', 0],
['create_time', '>=', $monthStartTs],
['create_time', '<=', $monthEndTs],
];
// 单次服务number = 1
$salesSituation[0]['value'] = Db::name('order')
->where($kaWhere)
->where('number', '=', 1)
->sum('total_amount');
// 年卡number > 6
$salesSituation[1]['value'] = Db::name('order')
->where($kaWhere)
->where('number', '>', 6)
->sum('total_amount');
// 次卡2 <= number <= 6
$salesSituation[2]['value'] = Db::name('order')
->where($kaWhere)
->where('number', '>=', 2)
->where('number', '<=', 6)
->sum('total_amount');
// 其它服务number = 0
$salesSituation[3]['value'] = Db::name('order')
->where($kaWhere)
->where('number', '=', 0)
->sum('total_amount');
// ========== 渠道 & 区域详细拆分(总额 / 年卡 / 次卡 / 单次 / 其它) ==========
$serviceTypes = [
'total' => [],
'year' => [['number', '>', 6]],
'times' => [['number', '>=', 2], ['number', '<=', 6]],
'single'=> [['number', '=', 1]],
'other' => [['number', '=', 0]],
];
// 渠道关键字到列 key 的映射
$channelBuckets = [
'meituan' => '美团',
'gzh' => '公众号',
'douyin' => '抖音',
'staff' => '员工',
'yeye' => '异业',
'other' => '渠道',
];
$channelDetail = [];
foreach ($serviceTypes as $typeKey => $extraWhere) {
$totals = [
'meituan' => 0,
'gzh' => 0,
'douyin' => 0,
'staff' => 0,
'yeye' => 0,
'other' => 0,
];
$query = Db::name('order')
->alias('o')
->join('orderchannel c', 'o.channel_id = c.id', 'LEFT')
->where('o.status', '<>', 0)
->whereBetween('o.create_time', [$monthStartTs, $monthEndTs]);
if (!empty($extraWhere)) {
$query->where($extraWhere);
}
$rows = $query
->field('c.name as channel_name, SUM(o.order_amount) as total')
->group('o.channel_id')
->select();
foreach ($rows as $row) {
$name = $row['channel_name'] ?? '';
$value = (float)($row['total'] ?? 0);
$bucket = 'other';
if (mb_strpos($name, '美团') !== false) {
$bucket = 'meituan';
} elseif (mb_strpos($name, '公众号') !== false || mb_strpos($name, '公') !== false) {
$bucket = 'gzh';
} elseif (mb_strpos($name, '抖音') !== false) {
$bucket = 'douyin';
} elseif (mb_strpos($name, '员工') !== false) {
$bucket = 'staff';
} elseif (mb_strpos($name, '异业') !== false) {
$bucket = 'yeye';
}
$totals[$bucket] += $value;
}
$channelDetail[$typeKey] = $totals;
}
// 区域明细:每种服务类型在各区域的销售额
$regionDetail = [];
foreach ($serviceTypes as $typeKey => $extraWhere) {
$regionDetail[$typeKey] = [];
foreach ($regions as $regionName) {
$q = Db::name('order')
->where('status', '<>', 0)
->whereBetween('create_time', [$monthStartTs, $monthEndTs])
->whereLike('address', '%' . $regionName . '%');
if (!empty($extraWhere)) {
$q->where($extraWhere);
}
$regionDetail[$typeKey][$regionName] = (float)$q->sum('order_amount');
}
}
// 汇总仪表盘数据供前端使用
$dashboardData = [
'monthlyTarget' => $monthlyTarget,
'overallCompletion' => $overallCompletion,
'staffProgress' => $staffProgress,
'channelPie' => $channelPie,
'trendDates' => $trendDates,
'trendValues' => $trendValues,
'trendCompare' => $trendCompare,
'regions' => $regions,
'regionTotals' => $regionTotals,
'salesSituation' => $salesSituation,
'channelDetail' => $channelDetail,
'regionDetail' => $regionDetail,
];
// 传递数据到视图
$this->assign([
@@ -115,6 +361,7 @@ class BulletinBoard extends AdminBase
'customersCompare' => $customersCompare,
'oldCustomers' => $oldCustomerCount, // 老客户数量(本月注册且下过单的)
'newCustomers' => $newCustomerCount, // 新客户数量(本月注册但没下过单的)
'dashboardData' => json_encode($dashboardData, JSON_UNESCAPED_UNICODE),
]);
return $this->fetch();

View File

@@ -100,26 +100,42 @@ class Order extends AdminBase
*/
public function del()
{
if ($this->request->isAjax()) {
dump(123);die;
// $post = $this->request->post('');
// $order=Db::name('order')->where('id',$post['order_id'])->find();//查询订单信息
// if($this->admin_id!=6){
// $this->_error('无权限删除');
// }else{
// $orderdel=Db::name('order_exe')->where('order_sn',$order['order_sn'])->find();
// if($orderdel){
// $this->_error('无法删除,存在主订单');
// }else{
// $del=Db::name('order')->where('id',$post['order_id'])->delete();
// $this->_success('删除成功');
// }
// }
$id = $this->request->get('id');
$order = Db::name('order')->find($id);//查询订单信息
if ($order == null){
$this->_error('订单不存在');
}
$del = Db::name('order')->where('id',$id)->update(['del' => 1]);
if($del){
$this->_success('删除成功');
}else{
$this->_error('删除失败');
}
}
}
/**
* User: 恢复已删除订单
* Desc: 将 del 从 1 恢复为 0
*/
public function recover()
{
if ($this->request->isAjax()) {
$id = $this->request->get('id');
$order = Db::name('order')->find($id);// 查询订单信息
if ($order == null){
$this->_error('订单不存在');
}
if ($order['del'] == 0) {
$this->_error('订单未删除,无需恢复');
}
$res = Db::name('order')->where('id',$id)->update(['del' => 0]);
if ($res) {
$this->_success('恢复成功');
} else {
$this->_error('恢复失败');
}
}
}
@@ -268,7 +284,7 @@ class Order extends AdminBase
$this->_success('修改订单成功', OrderLogic::edit($post));
}
$this->assign('info', json_encode(OrderLogic::orderinfoid($id), JSON_UNESCAPED_UNICODE));
$this->assign('info', json_encode(OrderLogic::orderinfoid($id), JSON_UNESCAPED_UNICODE));
$brand_lists=Db::name('orderchannel')->select();
$this->assign('brand_lists', json_encode($brand_lists, JSON_UNESCAPED_UNICODE));
$this->assign('category_lists', json_encode(StaffLogic::getAllTree(), JSON_UNESCAPED_UNICODE));

View File

@@ -659,6 +659,13 @@ public function group_del(){
$this->assign('goods_brand',StaffLogic::goods_brand());
return $this->fetch();
}
// 员工工资导出
public function exportWages()
{
$get = $this->request->get();
$this->_success('', StaffLogic::wagesExport($get));
}
//删除员工的工资
public function wagesdel(){

View File

@@ -291,7 +291,8 @@ class GoodsLogic
'give_integral_type' => $give_integral_type,
'give_integral' => $give_integral,
'spec_type' => $post['spec_type'],
'create_time' => $time
'create_time' => $time,
'type' => $post['type']
];
$goods_id = Db::name('goods')->insertGetId($data);

View File

@@ -34,10 +34,14 @@ class OrderLogic
public static function getListsCondition($get)
{
$where = [];
//订单状态
if ($get['type'] != '') {
$where[] = ['pay_status', '=', $get['type']];
if ($get['type'] != 66){
//订单状态
if ($get['type'] != '') {
$where[] = ['pay_status', '=', $get['type']];
}
$where[] = ['del', '=', 0];
}else{
$where[] = ['del', '=', 1];
}
//订单编号查询
if (isset($get['order_sn']) && $get['order_sn'] != '') {
@@ -117,7 +121,7 @@ class OrderLogic
$order = new Order();
$where = self::getListsCondition($get);
$field = 'o.*,order_status as order_status_text,pay_way as pay_way_text';
$brand = Db::name('goods_brand')->where(['del' => 0])->column('name', 'id'); //订单类型
$brand = Db::name('goods_brand')->column('name', 'id'); //订单类型
$admin = Db::name('admin')->column('name', 'id');
$count = $order
->where($where)

View File

@@ -14,7 +14,9 @@ class OrderautoLogic{
public static function lists($get){
$where = [];
//判断已经支付的订单
$where[] = ['pay_status', '=', 1];
// $where[] = ['pay_status', '=', 1];
$where[] = ['refund_status', '=', 0];
$where[] = ['del', '=', 0];
if(isset($get['type']) && $get['type'] != ''){
$where[] = ['static','=',$get['type']];
}
@@ -38,10 +40,8 @@ class OrderautoLogic{
$where[] = ['status','=',$get['status']];
}
// 执行状态查询
if(isset($get['admin']) && $get['admin']!= ''){
$where[] = ['admin_id','=',$get['admin']];
}
// 如果订单的admin_id不等于空不需要限制支付状态如果admin_id等于空只查询已支付的订单
$where[] = ['', 'exp', Db::raw("(admin_id IS NOT NULL AND admin_id != '') OR pay_status = 1")];
// 订单的来源查询
if(isset($get['pid']) && $get['pid']!= ''){
$where[] = ['channel_id','=',$get['pid']];

View File

@@ -624,6 +624,47 @@ class StaffLogic{
public static function adder($post){
return Db::name('staff')->where('id',$post['id'])->update(['lng'=>$post['store_longitude'],'lat'=>$post['store_latitude']]);
}
// 员工工资导出数据(基于 wages 列表结果,避免重复重算导致超时)
public static function wagesExport($get)
{
// 导出时最多导出 5000 条,且沿用 wages 的统计逻辑
$get['page'] = 1;
$get['limit'] = isset($get['limit']) && (int)$get['limit'] > 0 ? (int)$get['limit'] : 5000;
$data = self::wages($get);
$lists = $data['lists'] ?? [];
// 组装导出数据
$exportTitle = ['员工姓名', '员工电话', '服务总订单', '上午订单', '下午订单', '财务报销', '上午加时', '下午加时', '请假天数', '出勤天数', '罚款金额', '异常订单', '年卡订单', '物料金额'];
$exportData = [];
foreach ($lists as $row) {
$exportData[] = [
$row['name'] ?? '',
$row['mobile'] ?? '',
$row['total_orders'] ?? 0,
$row['sw_orders'] ?? 0,
$row['xw_orders'] ?? 0,
$row['finance'] ?? 0,
$row['sw_addtimes'] ?? 0,
$row['xw_addtimes'] ?? 0,
$row['leaves'] ?? 0,
$row['attendance'] ?? 0,
$row['fine'] ?? 0,
$row['abnormal'] ?? 0,
$row['annual'] ?? 0,
$row['erp_staff'] ?? 0,
];
}
$exportExt = 'xls';
return [
'exportTitle' => $exportTitle,
'exportData' => $exportData,
'exportExt' => $exportExt,
'exportName' => '员工工资-' . date('Y-m-d H:i:s'),
];
}
//获取员工积分记录
public static function points($get){

View File

@@ -200,57 +200,24 @@
<div class="chart-card">
<div class="chart-title">当月目标完成率</div>
<div style="margin-bottom: 20px;">
<div style="font-size: 14px; color: #666; margin-bottom: 10px;">本月销售目标: <span style="color: #4A70F4; font-weight: bold;">10万</span></div>
<div style="font-size: 14px; color: #666; margin-bottom: 10px;">
本月销售目标:
<span style="color: #4A70F4; font-weight: bold;" id="monthly-target-text">--</span>
</div>
<div class="progress-item">
<div class="progress-label">
<span>总体完成率</span>
<span style="color: #4A70F4; font-weight: bold;">84%</span>
<span style="color: #4A70F4; font-weight: bold;" id="overall-completion-text">--</span>
</div>
<div class="progress-bar-container">
<div class="progress-bar" style="width: 84%;"></div>
<div class="progress-bar" id="overall-completion-bar" style="width: 0%;"></div>
</div>
</div>
</div>
<div style="margin-top: 30px;">
<div class="chart-title" style="font-size: 14px; margin-bottom: 15px;">客服目标完成率(N个客服的目标陈列)</div>
<div id="staff-progress-list">
<!-- 客服进度条列表 -->
<div class="progress-item">
<div class="progress-label">
<span>啦啦</span>
<span>销售额: XXX | 百分比: xx% | 同比: xx%</span>
</div>
<div class="progress-bar-container">
<div class="progress-bar" style="width: 0%;"></div>
</div>
</div>
<div class="progress-item">
<div class="progress-label">
<span>小喵</span>
<span>销售额: XXX | 百分比: xx% | 同比: xx%</span>
</div>
<div class="progress-bar-container">
<div class="progress-bar" style="width: 0%;"></div>
</div>
</div>
<div class="progress-item">
<div class="progress-label">
<span>哆哆</span>
<span>销售额: XXX | 百分比: xx% | 同比: xx%</span>
</div>
<div class="progress-bar-container">
<div class="progress-bar" style="width: 0%;"></div>
</div>
</div>
<div class="progress-item">
<div class="progress-label">
<span>大猫</span>
<span>销售额: XXX | 百分比: xx% | 同比: xx%</span>
</div>
<div class="progress-bar-container">
<div class="progress-bar" style="width: 0%;"></div>
</div>
</div>
<!-- 客服进度条列表JS 根据数据库数据渲染) -->
</div>
</div>
</div>
@@ -263,8 +230,8 @@
<div class="layui-col-md6">
<div class="chart-card">
<div class="chart-title">每日销售趋势</div>
<div style="text-align: right; margin-bottom: 10px; color: #f56c6c; font-size: 14px;">
▼ 29.23% 上月同比
<div id="trend-compare-text" style="text-align: right; margin-bottom: 10px; color: #f56c6c; font-size: 14px;">
--
</div>
<div class="chart-container-large" id="daily-sales-trend-chart"></div>
</div>
@@ -296,52 +263,8 @@
<th>渠道</th>
</tr>
</thead>
<tbody>
<tr>
<td>总额</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
</tr>
<tr>
<td>年卡</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
</tr>
<tr>
<td>次卡</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
</tr>
<tr>
<td>单次服务</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
</tr>
<tr>
<td>其他服务</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
</tr>
<tbody id="channel-month-table-body">
<!-- JS 动态渲染渠道月销售详情 -->
</tbody>
</table>
</div>
@@ -365,52 +288,8 @@
<th>龙里</th>
</tr>
</thead>
<tbody>
<tr>
<td>总额</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
</tr>
<tr>
<td>年卡</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
</tr>
<tr>
<td>次卡</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
</tr>
<tr>
<td>单次服务</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
</tr>
<tr>
<td>其他服务</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
<td class="empty-data">-</td>
</tr>
<tbody id="region-month-table-body">
<!-- JS 动态渲染区域月销售详情 -->
</tbody>
</table>
</div>
@@ -441,6 +320,10 @@ layui.config({
newCustomers: parseInt('{$newCustomers|default=0}') || 0
};
// 仪表盘其它统计数据(目标、客服进度、渠道、趋势、区域等)
// 这里直接输出后端已经 json_encode 好的字符串,避免模板语法冲突
var dashboardData = {$dashboardData|raw} || {};
// 渲染统计数据
renderStatistics();
@@ -451,8 +334,13 @@ layui.config({
format: 'yyyy-MM-dd'
});
// 初始化所有图表(仅样式,不填充数据
// 初始化所有图表(使用数据库数据渲染
initCharts();
// 渲染目标完成率和客服进度条
renderTargetsAndStaff();
// 渲染渠道与区域明细表格
renderChannelAndRegionTables();
// 渲染统计数据
function renderStatistics() {
@@ -486,6 +374,99 @@ layui.config({
$('#customers-compare').html(formatCompare(statisticsData.customersCompare));
}
// 渲染销售目标、总体完成率和客服进度条
function renderTargetsAndStaff() {
if (!dashboardData) {
return;
}
// 销售目标与总体完成率
var target = dashboardData.monthlyTarget || 0;
var completion = dashboardData.overallCompletion || 0;
$('#monthly-target-text').text(target > 0 ? (target / 10000).toFixed(2) + ' 万' : '--');
$('#overall-completion-text').text(completion.toFixed ? completion.toFixed(2) + '%' : (completion + '%'));
$('#overall-completion-bar').css('width', (completion > 100 ? 100 : completion) + '%');
// 客服进度条
var list = $('#staff-progress-list');
list.empty();
if (dashboardData.staffProgress && dashboardData.staffProgress.length) {
dashboardData.staffProgress.forEach(function (item) {
var percentText = (item.percent || 0).toFixed(2) + '%';
var yoy = item.yoy || 0;
var yoyHtml;
if (yoy > 0) {
yoyHtml = '同比: <span style="color:#52c41a;">↑ ' + yoy.toFixed(2) + '%</span>';
} else if (yoy < 0) {
yoyHtml = '同比: <span style="color:#ff4d4f;">↓ ' + Math.abs(yoy).toFixed(2) + '%</span>';
} else {
yoyHtml = '同比: <span style="color:#999;">持平</span>';
}
var html = ''
+ '<div class="progress-item">'
+ ' <div class="progress-label">'
+ ' <span>' + (item.name || '未分配') + '</span>'
+ ' <span>销售额: ' + (item.sales || 0) + ' | 百分比: ' + percentText + ' | ' + yoyHtml + '</span>'
+ ' </div>'
+ ' <div class="progress-bar-container">'
+ ' <div class="progress-bar" style="width:' + (item.percent || 0) + '%;"></div>'
+ ' </div>'
+ '</div>';
list.append(html);
});
} else {
list.append('<div style="color:#999;font-size:12px;">暂无客服统计数据</div>');
}
}
// 渠道&区域月销售明细表格渲染(只处理“总额”这一行)
function renderChannelAndRegionTables() {
if (!dashboardData) {
return;
}
// ===== 渠道月销售详情(总额 / 年卡 / 次卡 / 单次 / 其它) =====
var channelBody = $('#channel-month-table-body');
channelBody.empty();
var channelHeaders = ['美团','公众号','抖音','员工','异业','渠道'];
var rowLabels = [
{key: 'total', text: '总额'},
{key: 'year', text: '年卡'},
{key: 'times', text: '次卡'},
{key: 'single',text: '单次服务'},
{key: 'other', text: '其他服务'}
];
var keyToCol = ['meituan','gzh','douyin','staff','yeye','other'];
rowLabels.forEach(function (row) {
var data = (dashboardData.channelDetail && dashboardData.channelDetail[row.key]) || {};
var tr = '<tr><td>' + row.text + '</td>';
keyToCol.forEach(function (colKey) {
var v = parseFloat(data[colKey] || 0).toFixed(2);
tr += '<td>' + v + '</td>';
});
tr += '</tr>';
channelBody.append(tr);
});
// ===== 区域月销售详情(总额 / 年卡 / 次卡 / 单次 / 其它) =====
var regionBody = $('#region-month-table-body');
regionBody.empty();
if (dashboardData.regions && dashboardData.regions.length) {
var regionNames = dashboardData.regions;
rowLabels.forEach(function (row) {
var rowData = (dashboardData.regionDetail && dashboardData.regionDetail[row.key]) || {};
var tr2 = '<tr><td>' + row.text + '</td>';
regionNames.forEach(function (rName) {
var val = parseFloat(rowData[rName] || 0).toFixed(2);
tr2 += '<td>' + val + '</td>';
});
tr2 += '</tr>';
regionBody.append(tr2);
});
}
}
function initCharts() {
// 月客户分析 - 饼图
var customerChart = echarts.init(document.getElementById('customer-analysis-chart'));
@@ -519,7 +500,7 @@ layui.config({
}]
});
// 月销售情况 - 饼图
// 月销售情况 - 饼图(使用数据库汇总结果)
var salesChart = echarts.init(document.getElementById('sales-situation-chart'));
salesChart.setOption({
tooltip: {
@@ -544,16 +525,18 @@ layui.config({
show: true,
formatter: '{b}: {c}'
},
data: [
{value: 8.2, name: '年卡销售', itemStyle: {color: '#4A70F4'}},
{value: 3.2, name: '次卡销售', itemStyle: {color: '#6DD047'}},
{value: 1.4, name: '单次服务', itemStyle: {color: '#F6A23F'}},
{value: 1.2, name: '其他服务', itemStyle: {color: '#87CEEB'}}
]
data: (dashboardData.salesSituation && dashboardData.salesSituation.length)
? dashboardData.salesSituation
: [
{value: 0, name: '单次服务', itemStyle: {color: '#F6A23F'}},
{value: 0, name: '年卡销量', itemStyle: {color: '#4A70F4'}},
{value: 0, name: '次卡销量', itemStyle: {color: '#6DD047'}},
{value: 0, name: '其它服务', itemStyle: {color: '#87CEEB'}}
]
}]
});
// 当月客户渠道分析 - 环形图
// 当月客户渠道分析 - 环形图(使用数据库统计的渠道订单数)
var channelChart = echarts.init(document.getElementById('channel-analysis-chart'));
channelChart.setOption({
tooltip: {
@@ -578,19 +561,13 @@ layui.config({
show: true,
formatter: '{b}: {d}%'
},
data: [
{value: 0, name: '美团'},
{value: 24, name: '公众号-企业客户'},
{value: 0, name: '抖音'},
{value: 0, name: '渠道'},
{value: 0, name: '员工'},
{value: 0, name: '异业'},
{value: 0, name: '普通客户'}
]
data: (dashboardData.channelPie && dashboardData.channelPie.length)
? dashboardData.channelPie
: []
}]
});
// 每日销售趋势 - 折线图
// 每日销售趋势 - 折线图(使用数据库按天汇总的数据)
var trendChart = echarts.init(document.getElementById('daily-sales-trend-chart'));
trendChart.setOption({
tooltip: {
@@ -605,7 +582,7 @@ layui.config({
xAxis: {
type: 'category',
boundaryGap: false,
data: []
data: dashboardData.trendDates || []
},
yAxis: {
type: 'value',
@@ -635,11 +612,21 @@ layui.config({
itemStyle: {
color: '#4A70F4'
},
data: []
data: dashboardData.trendValues || []
}]
});
// 渲染“上月同比”文字
var trendCompare = dashboardData.trendCompare || 0;
var trendTextDom = $('#trend-compare-text');
if (trendCompare > 0) {
trendTextDom.css('color', '#52c41a').html('▲ ' + trendCompare.toFixed(2) + '% 上月同比');
} else if (trendCompare < 0) {
trendTextDom.css('color', '#f56c6c').html('▼ ' + Math.abs(trendCompare).toFixed(2) + '% 上月同比');
} else {
trendTextDom.css('color', '#999').html('持平 上月同比');
}
// 区域月销售额 - 柱状图
// 区域月销售额 - 柱状图(根据地址简单按区域统计)
var regionalChart = echarts.init(document.getElementById('regional-sales-chart'));
regionalChart.setOption({
tooltip: {
@@ -656,7 +643,7 @@ layui.config({
},
xAxis: {
type: 'category',
data: ['区域1', '区域2', '区域3', '区域4', '区域5', '区域6', '区域7', '区域8']
data: dashboardData.regions || []
},
yAxis: {
type: 'value',
@@ -668,7 +655,7 @@ layui.config({
itemStyle: {
color: '#4A70F4'
},
data: [4668, 3775, 2912, 2200, 1259, 700, 403, 0]
data: dashboardData.regionTotals || []
}]
});

View File

@@ -298,43 +298,86 @@
setSelectFirst();
function setSelectFirst(default_id) {
console.log('setSelectFirst 被调用default_id:', default_id);
var category_select_html = '<option value="">请选择分类</option>';
var foundMatch = false;
for (var i in categorys) {
if (categorys[i]['level'] == 1) {
category_select_html += '<option value="' + categorys[i]['id'] + '">' + categorys[i]['name'] + '</option>';
var selected = '';
if (default_id && String(categorys[i]['id']) == String(default_id)) {
selected = ' selected';
foundMatch = true;
console.log('找到匹配的省份:', categorys[i]['name'], 'ID:', categorys[i]['id']);
}
category_select_html += '<option value="' + categorys[i]['id'] + '"' + selected + '>' + categorys[i]['name'] + '</option>';
}
}
$('select[name="first_category_id"]').html(category_select_html);
$('select[name="first_category_id"]').val(default_id);
if (default_id) {
$('select[name="first_category_id"]').val(String(default_id));
console.log('设置省份值:', String(default_id), '是否找到匹配:', foundMatch);
}
form.render('select');
}
function setSelectSecond(default_id, parent_id) {
console.log('setSelectSecond 被调用default_id:', default_id, 'parent_id:', parent_id);
parent_id = parent_id === undefined ? $('select[name="first_category_id"]').val() : parent_id;
if (!parent_id) {
console.log('setSelectSecond: parent_id 为空,返回');
return;
}
parent_id = String(parent_id);
$('select[name="second_category_id"]').html('<option value="">请选择分类</option>');
$('select[name="third_category_id"]').html('<option value="">请选择分类</option>');
var category_select_html = '<option value="">请选择分类</option>';
var foundMatch = false;
for (var i in categorys) {
if (categorys[i]['parent_id'] == parent_id) {
category_select_html += '<option value="' + categorys[i]['id'] + '">' + categorys[i]['name'] + '</option>';
if (String(categorys[i]['parent_id']) == parent_id) {
var selected = '';
if (default_id && String(categorys[i]['id']) == String(default_id)) {
selected = ' selected';
foundMatch = true;
console.log('找到匹配的城市:', categorys[i]['name'], 'ID:', categorys[i]['id']);
}
category_select_html += '<option value="' + categorys[i]['id'] + '"' + selected + '>' + categorys[i]['name'] + '</option>';
}
}
$('select[name="second_category_id"]').html(category_select_html);
$('select[name="second_category_id"]').val(default_id);
if (default_id) {
$('select[name="second_category_id"]').val(String(default_id));
console.log('设置城市值:', String(default_id), '是否找到匹配:', foundMatch);
}
form.render('select');
}
function setSelectThird(default_id, parent_id) {
console.log('setSelectThird 被调用default_id:', default_id, 'parent_id:', parent_id);
parent_id = parent_id === undefined ? $('select[name="second_category_id"]').val() : parent_id;
if (!parent_id) {
console.log('setSelectThird: parent_id 为空,返回');
return;
}
parent_id = String(parent_id);
$('select[name="third_category_id"]').html('<option value="">请选择分类</option>');
var first_category_id = $('select[name="first_category_id"]').val();
var category_select_html = '<option value="">请选择分类</option>';
var foundMatch = false;
for (var i in categorys) {
if (categorys[i]['parent_id'] == parent_id) {
category_select_html += '<option value="' + categorys[i]['id'] + '">' + categorys[i]['name'] + '</option>';
if (String(categorys[i]['parent_id']) == parent_id) {
var selected = '';
if (default_id && String(categorys[i]['id']) == String(default_id)) {
selected = ' selected';
foundMatch = true;
console.log('找到匹配的区县:', categorys[i]['name'], 'ID:', categorys[i]['id']);
}
category_select_html += '<option value="' + categorys[i]['id'] + '"' + selected + '>' + categorys[i]['name'] + '</option>';
}
}
$('select[name="third_category_id"]').html(category_select_html);
$('select[name="third_category_id"]').val(default_id);
if (default_id) {
$('select[name="third_category_id"]').val(String(default_id));
console.log('设置区县值:', String(default_id), '是否找到匹配:', foundMatch);
}
form.render('select');
}
@@ -465,7 +508,7 @@
}
{notempty name='info'}
var goods_info= {$info|raw|default=''};
console.log(goods_info);
console.log('订单数据:', goods_info);
$('input[name="id"]').val(goods_info['id']);
$('input[name="address"]').val(goods_info['address']);
$('input[name="total_amount"]').val(goods_info['total_amount']);
@@ -474,9 +517,89 @@
$('input[name="phone"]').val(goods_info['mobile']);
$('input[name="store_latitude"]').val(goods_info['lng']);
$('input[name="store_longitude"]').val(goods_info['lat']);
setSelectFirst(goods_info['province']);
setSelectSecond(goods_info['city']);
setSelectThird(goods_info['district']);
// 设置地区选择器,根据返回的 province、city、district 字段
// 注意需要检查值是否存在包括0的情况0是有效的ID值
var province_id = '';
var city_id = '';
var district_id = '';
// 检查province字段包括0值
if (goods_info['province'] !== undefined && goods_info['province'] !== null && goods_info['province'] !== '') {
province_id = goods_info['province'];
}
// 检查city字段包括0值
if (goods_info['city'] !== undefined && goods_info['city'] !== null && goods_info['city'] !== '') {
city_id = goods_info['city'];
}
// 检查district字段包括0值
if (goods_info['district'] !== undefined && goods_info['district'] !== null && goods_info['district'] !== '') {
district_id = goods_info['district'];
}
console.log('地区数据:', {
province: goods_info['province'],
city: goods_info['city'],
district: goods_info['district'],
province_id: province_id,
city_id: city_id,
district_id: district_id
});
// 初始化地区选择器的函数
function initRegionSelectors() {
if (province_id !== '') {
// 转换为字符串,确保类型匹配
province_id = String(province_id);
// 先设置省份
setSelectFirst(province_id);
// 等待省份选择器渲染完成后再设置城市
setTimeout(function() {
// 验证省份值是否设置成功
var selectedProvince = $('select[name="first_category_id"]').val();
console.log('已选省份ID:', selectedProvince, '期望:', province_id);
if (city_id !== '' && selectedProvince == province_id) {
city_id = String(city_id);
setSelectSecond(city_id, province_id);
// 等待城市选择器渲染完成后再设置区县
setTimeout(function() {
// 验证城市值是否设置成功
var selectedCity = $('select[name="second_category_id"]').val();
console.log('已选城市ID:', selectedCity, '期望:', city_id);
if (district_id !== '' && selectedCity == city_id) {
district_id = String(district_id);
setSelectThird(district_id, city_id);
setTimeout(function() {
var selectedDistrict = $('select[name="third_category_id"]').val();
console.log('已选区县ID:', selectedDistrict, '期望:', district_id);
// 最后重新渲染一次,确保所有选择器都正确显示
form.render('select');
}, 100);
} else {
form.render('select');
}
}, 300);
} else {
form.render('select');
}
}, 300);
} else {
form.render('select');
}
}
// 延迟执行,确保页面完全加载和选择器初始化完成
setTimeout(function() {
console.log('开始初始化地区选择器...');
initRegionSelectors();
}, 200);
setBrand(goods_info['channel_id']); //部门的修改
setBrandss(goods_info['gord_id']); //部门的修改

View File

@@ -73,12 +73,19 @@
height: 62px;
margin-bottom: 5px;
}
/* 退款状态标红样式 */
.refund-status-row {
background-color: #ffebee !important;
/* 退款状态绿色背景 */
.refunding-row {
background-color: #c8e6c9 !important;
}
.refund-status-row:hover {
background-color: #ffcdd2 !important;
.refunding-row:hover {
background-color: #a5d6a7 !important;
}
/* 同意退款后淡绿色背景 */
.order-status-4-row {
background-color: #e8f5e9 !important;
}
.order-status-4-row:hover {
background-color: #c8e6c9 !important;
}
</style>
@@ -206,6 +213,7 @@
<li data-type="1">已支付</li>
<li data-type="2">已退款</li>
<li data-type="3">拒退款</li>
<li data-type="66">已删除</li>
</ul>
<div class="layui-tab-item layui-show">
@@ -338,7 +346,11 @@
<a class="layui-btn-primary layui-btn-sm" lay-event="channel" style="display: inline-block;">渠道</a>
<a class="layui-btn layui-btn-primary layui-btn-sm operation-btn" lay-event="remarks">备注</a>
<a class="layui-btn-primary layui-btn-sm" style="display: inline-block;" lay-event="allocation"> 分配</a>
{{# if(d.del == 0){ }}
<a class="layui-btn layui-btn-primary layui-btn-sm operation-btn" style="display: inline-block;background-color:#fd4634;color:#fff" lay-event="cancel">删除</a>
{{# } else { }}
<a class="layui-btn layui-btn-primary layui-btn-sm operation-btn" style="display: inline-block;background-color:#1E9FFF;color:#fff" lay-event="recover">恢复</a>
{{# } }}
{{# if(d.order_status == 1){ }}
<a class="layui-btn-primary layui-btn-sm" style="display: inline-block;" lay-event="delivery">发货</a>
{{# } }}
@@ -637,19 +649,36 @@
$($(".layui-table-fixed-r .layui-table-body tbody tr")[index]).height($(val).height());
});
// 如果 refund_status > 0整行标红显示
// 如果 order_status == 4同意退款整行淡绿色显示
// 如果 refund_status > 0 但 order_status != 4退款中整行绿色显示
if (res && res.data && res.data.length > 0) {
res.data.forEach(function(item, index) {
if (item.refund_status && parseInt(item.refund_status) > 0) {
// 给主表格行添加红色背景
var orderStatus = item.order_status ? parseInt(item.order_status) : 0;
var refundStatus = item.refund_status ? parseInt(item.refund_status) : 0;
// 同意退款后order_status == 4显示淡绿色
if (orderStatus == 4) {
// 给主表格行添加淡绿色背景
var $mainRow = $(".layui-table-main tbody tr").eq(index);
$mainRow.addClass('refund-status-row');
$mainRow.addClass('order-status-4-row');
// 给固定列的行也添加色背景
// 给固定列的行也添加淡绿色背景
var $fixedLeftRow = $(".layui-table-fixed-l .layui-table-body tbody tr").eq(index);
var $fixedRightRow = $(".layui-table-fixed-r .layui-table-body tbody tr").eq(index);
$fixedLeftRow.addClass('refund-status-row');
$fixedRightRow.addClass('refund-status-row');
$fixedLeftRow.addClass('order-status-4-row');
$fixedRightRow.addClass('order-status-4-row');
}
// 退款中refund_status > 0 但 order_status != 4显示绿色
else if (refundStatus > 0) {
// 给主表格行添加绿色背景
var $mainRow = $(".layui-table-main tbody tr").eq(index);
$mainRow.addClass('refunding-row');
// 给固定列的行也添加绿色背景
var $fixedLeftRow = $(".layui-table-fixed-l .layui-table-body tbody tr").eq(index);
var $fixedRightRow = $(".layui-table-fixed-r .layui-table-body tbody tr").eq(index);
$fixedLeftRow.addClass('refunding-row');
$fixedRightRow.addClass('refunding-row');
}
});
}
@@ -835,7 +864,7 @@
});
}
//取消订单
// 退款订单
if(obj.event === 'cancelss'){
layer.confirm('确认订单退款吗?', {
btn: ['确认','取消'] //按钮
@@ -860,7 +889,7 @@
}
//取消订单
// 删除订单逻辑删除del 设置为 1
if(obj.event === 'cancel'){
layer.confirm('确定删除订单的数据?', {
btn: ['确认','取消'] //按钮
@@ -882,6 +911,35 @@
});
}
// 恢复订单del 设置为 0
if(obj.event === 'recover'){
layer.confirm('确定恢复该订单吗?', {
btn: ['确认','取消'] //按钮
}, function(){
like.ajax({
url: '{:url("order/recover")}?id='+id
, type: 'get'
, success: function (res) {
if (res.code == 1) {
layui.layer.msg(res.msg, {
offset: '15px'
, icon: 1
, time: 1000
},function () {
table.reload('order-lists');
});
} else {
layui.layer.msg(res.msg || '恢复失败', {
offset: '15px'
, icon: 2
, time: 1500
});
}
},
});
});
}
//商家备注
if(obj.event === 'remarks') {
like.ajax({

View File

@@ -90,7 +90,9 @@
<button class="layui-btn layui-btn-sm layuiadmin-btn-ad layui-btn-primary " lay-submit
lay-filter="user-clear-search">清空查询
</button>
<button class="layui-btn layui-btn-sm layuiadmin-btn-ad layui-btn-normal" lay-submit
lay-filter="export-file">导出
</button>
</div>
</div>
@@ -161,7 +163,7 @@
form.on('submit(export-file)', function(data){
var field = data.field;
$.ajax({
url: '{:url("order/exportFile")}?type=' + listType,
url: '{:url("staff/exportWages")}',
type: 'get',
data: field,
dataType: 'json',
@@ -171,7 +173,7 @@
success: function(res) {
table.exportFile(res.data.exportTitle,res.data.exportData, res.data.exportExt, res.data.exportName);
},
timeout: 15000
timeout: 60000
});
layer.msg('导出中请耐心等待~');
});

View File

@@ -91,8 +91,11 @@ class Order extends ApiBase
$order = OrderLogic::add($this->user_id, $info['data'], $post);
if ($order['code'] == 0) {
$this->_error($order['msg']);
}
return $order;
$this->_success('', $order['data']);
}
@@ -572,6 +575,7 @@ class Order extends ApiBase
public function putday()
{
$this->_error('该时间内无法自主预约,请联系客服');
$post = $this->request->post();
$hourLists = $post['data']['hourLists'] ?? [];
$orderid = $post['data']['id'] ?? 0;

View File

@@ -22,7 +22,8 @@ class Points extends ApiBase
* @return mixed
*/
public function goodslist(){
$lists = PointsLogic::goodslist();
$clsssId = $this->request->get('classify_id');
$lists = PointsLogic::goodslist($clsssId);
$this->_success('获取数据成功',$lists);
}
/**
@@ -38,16 +39,42 @@ class Points extends ApiBase
}
public function goodsSub(){
$data = $this->request->get();
$data['user_id']= $this->user_id;
$user_jf=UserLogic::getUserInfo($this->user_id);
if($user_jf['user_integral']<$data['price']){
$data = $this->request->post();
// 参数校验
if(empty($data) || !is_array($data)){
$this->_error('参数错误');
}
if(empty($data['id']) || empty($data['name']) || !isset($data['price'])){
$this->_error('参数不完整');
}
$data['user_id'] = $this->user_id;
$user_jf = UserLogic::getUserInfo($this->user_id);
if($user_jf['user_integral'] < $data['price']){
$this->_error('积分不足');
}else{
$data = PointsLogic::goodsSub($data);
$this->_success('兑换成功',$data);
$result = PointsLogic::goodsSub($data);
if($result['code'] == 1){
$this->_success('兑换成功');
}else{
$this->_error($result['msg']);
}
}
}
//积分订单列表
public function orderList()
{
$data = $this->request->post();
// 参数校验
if(empty($data) || !is_array($data)){
$this->_error('参数错误');
}
$userId = $this->user_id;
$state = isset($data['state']) ? $data['state'] : null;
$result = PointsLogic::orderList($userId, $state);
$this->_success('获取数据成功',$result);
}
}

View File

@@ -26,7 +26,7 @@ class Share extends ApiBase
public function shareGoods()
{
$id = $this->request->get('id');
$url = $this->request->get('url');
$url = $this->request->get('page');
$client = $this->client;
if ($id && $url) {
$result = ShareLogic::shareGoods($this->user_id, $id, $url, $client);

View File

@@ -38,7 +38,7 @@ class GoodsLogic{
$goods = new Goods();
//品牌筛选
if(isset($get['brand_id']) && $get['brand_id']) {
$where[] = ['brand_id', '=', $get['brand_id']];
$where[] = ['third_category_id', '=', $get['brand_id']];
}
//分类筛选
if(isset($get['category_id']) && $get['category_id']){

View File

@@ -491,8 +491,8 @@ class OrderLogic extends LogicBase
// 拆分后每个订单的金额需要重新计算,这里先验证原始总金额
// 实际拆分时每个订单会独立计算
} else {
if($user_money < $data['order_amount']){
throw new Exception('账户余额不足');
if($user_money < $data['order_amount']){
throw new Exception('账户余额不足');
}
}
}
@@ -556,10 +556,13 @@ class OrderLogic extends LogicBase
// 创建单个订单
$single_goods_lists = $single_order_data['goods_lists'];
if (empty($single_goods_lists)) {
throw new Exception('商品信息获取失败');
}
$single_goods_id = $single_goods_lists[0]['goods_id'];
$order = self::addOrder($user_id, $single_order_data, $order_source, $user_address, $single_goods_id);
$order_id = $order['order_id'];
$order_id = $order['order_id'];
$order_ids[] = $order_id;
self::addOrderGoods($order_id, $single_goods_lists);
@@ -590,6 +593,9 @@ class OrderLogic extends LogicBase
}
$single_goods_lists = $single_order_data['goods_lists'];
if (empty($single_goods_lists)) {
throw new Exception('商品信息获取失败');
}
$single_goods_id = $single_goods_lists[0]['goods_id'];
$order = self::addOrder($user_id, $single_order_data, $order_source, $user_address, $single_goods_id);
@@ -607,30 +613,36 @@ class OrderLogic extends LogicBase
}
} else {
// 普通商品:保持原有逻辑
if (empty($goods_lists)) {
throw new Exception('商品信息获取失败');
}
$goods_id = $goods_lists[0]['goods_id'];
$order = self::addOrder($user_id, $data, $order_source, $user_address, $goods_id);
$order_id = $order['order_id'];
$order_ids[] = $order_id;
self::addOrderGoods($order_id, $goods_lists);
self::addOrderAfter($order_id, $user_id, $type, $data);
//支付方式为余额支付,扣除余额,更新订单状态,支付状态
if ($data['pay_way'] == Pay::BALANCE_PAY || $data['order_amount'] == 0) {
PayNotifyLogic::handle('order', $order['order_sn'], []);
}
self::addOrderGoods($order_id, $goods_lists);
self::addOrderAfter($order_id, $user_id, $type, $data);
//支付方式为余额支付,扣除余额,更新订单状态,支付状态
if ($data['pay_way'] == Pay::BALANCE_PAY || $data['order_amount'] == 0) {
PayNotifyLogic::handle('order', $order['order_sn'], []);
}
// 砍价订单处理
if (isset($post['bargain_launch_id']) and $post['bargain_launch_id'] > 0) {
$bargainLaunchModel = new BargainLaunch();
$bargainLaunchModel->where(['id'=>(int)$post['bargain_launch_id']])
->update(['order_id'=>$order_id, 'status'=>1]);
// 砍价订单处理
if (isset($post['bargain_launch_id']) and $post['bargain_launch_id'] > 0) {
$bargainLaunchModel = new BargainLaunch();
$bargainLaunchModel->where(['id'=>(int)$post['bargain_launch_id']])
->update(['order_id'=>$order_id, 'status'=>1]);
}
}
Db::commit();
return self::dataSuccess('', ['order_id' => $order_ids[0] ?? 0, 'order_ids' => $order_ids, 'type' => 'order']);
if (empty($order_ids)) {
throw new Exception('订单创建失败');
}
return self::dataSuccess('', ['order_id' => $order_ids[0], 'order_ids' => $order_ids, 'type' => 'order']);
} catch (Exception $e) {
Db::rollback();

View File

@@ -1,5 +1,6 @@
<?php
namespace app\api\logic;
use app\api\model\OrderPoints;
use think\Db;
use think\Exception;
use app\common\server\UrlServer;
@@ -9,13 +10,16 @@ class PointsLogic
{
//获取积分的分类
public static function classify(){
return Db::name('printer_type')->select();
return Db::name('printer_type')->where('del',0)->select();
}
//获取到积分的商品列表
public static function goodslist(){
$where=[];
public static function goodslist($clsssId){
$where=[
'brand_id'=>$clsssId,
'del'=>0
];
$goods = Db::name('printer_goods')
->where($where)
->select();
@@ -34,21 +38,83 @@ class PointsLogic
return $data;
}
/**
* 积分商品下单(扣减积分并生成订单)
* @param array $data ['id','name','price','user_id','number'(可选)]
* @return array
*/
public static function goodsSub($data){
$data=[
'name' =>$data['name'],
'goods_id' =>$data['id'],
'price' =>$data['price'],
'number' =>1,
'user_id' =>$data['user_id'],
'create_time'=>time()
];
$insert=Db::name('printer_order')->data($data)->insert();
if($insert){
$user=UserLogic::getUserInfo($data['user_id']);
db::name('user')->where('id',$data['user_id'])->update(['user_integral'=>$user['user_integral']-$data['price']]);
// Db::name('printer_goods')->where('')
}
if(empty($data) || !is_array($data)){
return ['code'=>0,'msg'=>'参数错误'];
}
// 基础校验
if(empty($data['id']) || empty($data['user_id']) || !isset($data['price'])){
return ['code'=>0,'msg'=>'参数不完整'];
}
$number = isset($data['number']) && intval($data['number'])>0 ? intval($data['number']) : 1;
$price = floatval($data['price']);
$needIntegral = $price * $number;
Db::startTrans();
try{
// 加锁读取用户积分
$user = Db::name('user')->where('id',$data['user_id'])->lock(true)->find();
if(!$user){
throw new Exception('用户不存在');
}
if($user['user_integral'] < $needIntegral){
throw new Exception('积分不足');
}
$orderData = [
'name' => $data['name'] ?? '',
'goods_id' => $data['id'],
'price' => $price,
'number' => $number,
'user_id' => $data['user_id'],
'create_time' => time(),
'address_id' => $data['addressId'],
'state' => 1
];
$insert = Db::name('printer_order')->insert($orderData);
if(!$insert){
throw new Exception('下单失败');
}
// 扣减积分
Db::name('user')
->where('id',$data['user_id'])
->setDec('user_integral', $needIntegral);
Db::commit();
return ['code'=>1,'msg'=>'兑换成功'];
}catch (\Exception $e){
Db::rollback();
return ['code'=>0,'msg'=>$e->getMessage()];
}
}
//获取积分订单
public static function orderList($userId, $state = null)
{
$order = new OrderPoints();
$query = $order->with([
'address' => function($query){
$query->where('del',0)->field('id,address');
},
'pointsGoods' => function($query){
$query->where('del',0)->field('id,images');
}
])->where('user_id', $userId);
// 如果传了state参数才添加state条件否则查询全部
if($state !== null && $state !== ''){
$query = $query->where('state', $state);
}
$orderArray = $query->paginate(10);
return $orderArray;
}
}

View File

@@ -77,9 +77,22 @@ class Goods extends Model{
$this->setAttr('price',$goods_item[0]['price']);
$this->setAttr('market_price',$goods_item[0]['market_price']);
//创建规格值ID到商品项ID的映射
$spec_value_to_item = [];
foreach ($goods_item as $item) {
$spec_value_ids = $item['spec_value_ids'];
// spec_value_ids 存储的是规格值ID可能是一个或多个逗号分隔
$spec_value_id_array = explode(',', $spec_value_ids);
foreach ($spec_value_id_array as $spec_value_id) {
$spec_value_to_item[$spec_value_id] = $item['id'];
}
}
//拼接规格
foreach ($spec_value as $item){
if(isset($spec[$item['spec_id']])){
//添加对应的商品项ID
$item['item_id'] = $spec_value_to_item[$item['id']] ?? 0;
$spec[$item['spec_id']]['spec_value'][]= $item;
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace app\api\model;
use think\Model;
class GoodsPoints extends Model
{
protected $name = 'printer_goods';
}

View File

@@ -0,0 +1,24 @@
<?php
namespace app\api\model;
use think\Model;
use think\model\relation\HasOne;
class OrderPoints extends Model
{
protected $name = 'printer_order';
//关联地址
public function address(): HasOne
{
return $this->hasOne(UserAddress::class, 'id', 'address_id');
}
//关联积分商品
public function pointsGoods(): HasOne
{
return $this->hasOne(GoodsPoints::class, 'id', 'goods_id');
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace app\api\model;
use think\Model;
class UserAddress extends Model
{
protected $name = 'user_address';
}

View File

@@ -129,7 +129,9 @@ class OrderRefundLogic
}
$refund_log = Db::name('order_refund')->where(['id' => $refund_id])->find();
if ($order['transaction_id'] == ''){
throw new Exception('微信订单不存在');
}
$data = [
'transaction_id' => $order['transaction_id'],
'refund_sn' => $refund_log['refund_sn'],

View File

@@ -115,27 +115,27 @@ class PayNotifyLogic
//发送通知
Hook::listen('notice', [
'user_id' => $user['id'],
'order_id' => $order['id'],
'scene' => NoticeSetting::ORDER_PAY_NOTICE,
]);
// Hook::listen('notice', [
// 'user_id' => $user['id'],
// 'order_id' => $order['id'],
// 'scene' => NoticeSetting::ORDER_PAY_NOTICE,
// ]);
//短信通知
Hook::listen('sms_send', [
'key' => NoticeSetting::ORDER_PAY_NOTICE,
'mobile' => $order->mobile,
'user_id' => $user->id,
'params' => [
'nickname' => $user->nickname,
'order_sn' => $order->order_sn,
'order_amount' => $order->order_amount,
'time' => $order->create_time,
'total_num' => $order->total_num.'件',
'goods_name' => omit_str(($order->order_goods[0]['goods_name'] ?? '商品'), 8)
]
]);
// Hook::listen('sms_send', [
// 'key' => NoticeSetting::ORDER_PAY_NOTICE,
// 'mobile' => $order->mobile,
// 'user_id' => $user->id,
// 'params' => [
// 'nickname' => $user->nickname,
// 'order_sn' => $order->order_sn,
// 'order_amount' => $order->order_amount,
// 'time' => $order->create_time,
// 'total_num' => $order->total_num.'件',
// 'goods_name' => omit_str(($order->order_goods[0]['goods_name'] ?? '商品'), 8)
// ]
// ]);
$order_contact_mobile = ConfigServer::get('order_message', 'order_contact_mobile');
//平台短信通知

View File

@@ -40,7 +40,7 @@ class Ad extends Model{
self::mobile => [
[
'name' => '商品分类',
'path' => '/pages/sort/sort',
'path' => '/pages/category/index',
'is_tab' => 1,
],
[
@@ -57,7 +57,7 @@ class Ad extends Model{
self::pc => [
[
'name' => '商品分类',
'path' => '/category',
'path' => '/category/index',
'is_tab' => 0,
],
[
@@ -67,7 +67,7 @@ class Ad extends Model{
],
[
'name' => '个人中心',
'path' => '/user/profile',
'path' => '/user/user',
'is_tab' => 0,
],
],

View File

@@ -24,7 +24,7 @@ class Aliyun extends Server
parent::__construct();
$this->config = $config;
}
/**
* 创建并配置 OssClient
* @return OssClient