chore: 移除废弃的增项服务模块并升级服务架构
- 删除 Addon 相关控制器、模型、语言包和视图文件 - 新增服务类型支持一口价属性配置 - 新增系统监控、用户资料、订单评价等后端管理页面 - 新增数据库表结构及索引优化脚本 - 更新应用版本号至 1.0.44 - 更新小程序应用标识 - 完善 .gitignore 配置
这个提交包含在:
@@ -26,7 +26,6 @@ class Service extends Backend
|
||||
{
|
||||
parent::_initialize();
|
||||
$this->model = new \app\admin\model\Service;
|
||||
$this->view->assign("priceTypeList", $this->model->getPriceTypeList());
|
||||
$this->view->assign("statusList", $this->model->getStatusList());
|
||||
|
||||
// 获取统一服务字典表(fa_service_type,不绑定单一类目,主服务与增项服务同源)
|
||||
@@ -66,7 +65,7 @@ class Service extends Backend
|
||||
}
|
||||
// 一次性批量查询当前页商品的细分规格,避免 N+1 查询
|
||||
$allSpecs = Db::name('service_spec')
|
||||
->field('id,service_id,name,description')
|
||||
->field('id,service_id,name,base_price,description')
|
||||
->where('service_id', 'in', $serviceIds)
|
||||
->where('status', 'normal')
|
||||
->order('weigh desc, id asc')
|
||||
@@ -77,7 +76,8 @@ class Service extends Backend
|
||||
if (!isset($specMap[$sid])) {
|
||||
$specMap[$sid] = [];
|
||||
}
|
||||
$specMap[$sid][] = $sp['name'];
|
||||
$spPrice = (float)$sp['base_price'];
|
||||
$specMap[$sid][] = $spPrice > 0 ? ($sp['name'] . '(¥' . round($spPrice) . ')') : $sp['name'];
|
||||
}
|
||||
foreach ($rows as &$r) {
|
||||
$sid = (int)$r['id'];
|
||||
@@ -125,7 +125,7 @@ class Service extends Backend
|
||||
$serviceId = $this->model->id;
|
||||
|
||||
// 处理商品规格列表
|
||||
$this->syncSpecs($serviceId, $this->request->post('specs/a', []), isset($params['base_price']) ? (float)$params['base_price'] : 0);
|
||||
$this->syncSpecs($serviceId, $this->request->post('specs/a', []));
|
||||
|
||||
Db::commit();
|
||||
} catch (ValidateException|PDOException|Exception $e) {
|
||||
@@ -168,7 +168,7 @@ class Service extends Backend
|
||||
$result = $row->allowField(true)->save($params);
|
||||
|
||||
// 同步处理商品规格列表
|
||||
$this->syncSpecs($row->id, $this->request->post('specs/a', []), isset($params['base_price']) ? (float)$params['base_price'] : (float)$row->base_price);
|
||||
$this->syncSpecs($row->id, $this->request->post('specs/a', []));
|
||||
|
||||
Db::commit();
|
||||
} catch (ValidateException|PDOException|Exception $e) {
|
||||
@@ -220,20 +220,75 @@ class Service extends Backend
|
||||
if (isset($params['service_types_raw'])) {
|
||||
if (is_string($params['service_types_raw'])) {
|
||||
$parsedTypes = json_decode($params['service_types_raw'], true) ?: [];
|
||||
$params['service_types'] = $params['service_types_raw'];
|
||||
} else {
|
||||
$parsedTypes = is_array($params['service_types_raw']) ? $params['service_types_raw'] : [];
|
||||
$params['service_types'] = json_encode($parsedTypes, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
unset($params['service_types_raw']);
|
||||
|
||||
if (empty($parsedTypes)) {
|
||||
throw new ValidateException('请至少开启 1 项主服务');
|
||||
}
|
||||
|
||||
$dictSupportMap = Db::name('service_type')->column('support_fixed', 'code');
|
||||
$hasDefault = false;
|
||||
foreach ($parsedTypes as &$pt) {
|
||||
$code = isset($pt['code']) ? (string)$pt['code'] : '';
|
||||
$supportFixed = isset($dictSupportMap[$code])
|
||||
? (int)$dictSupportMap[$code]
|
||||
: (isset($pt['support_fixed']) ? (int)$pt['support_fixed'] : 1);
|
||||
$price = ($supportFixed === 1 && isset($pt['price'])) ? round((float)$pt['price'], 2) : 0.00;
|
||||
$pt['price'] = $price;
|
||||
$pt['support_fixed'] = $supportFixed;
|
||||
if ($supportFixed === 1 && !empty($pt['is_default']) && !$hasDefault) {
|
||||
$pt['is_default'] = 1;
|
||||
$hasDefault = true;
|
||||
} else {
|
||||
$pt['is_default'] = 0;
|
||||
}
|
||||
}
|
||||
unset($pt);
|
||||
|
||||
if (!$hasDefault && !empty($parsedTypes)) {
|
||||
foreach ($parsedTypes as &$ptDef) {
|
||||
if ((int)$ptDef['support_fixed'] === 1) {
|
||||
$ptDef['is_default'] = 1;
|
||||
$hasDefault = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
unset($ptDef);
|
||||
if (!$hasDefault) {
|
||||
$parsedTypes[0]['is_default'] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
$params['service_types'] = json_encode(array_values($parsedTypes), JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
if (isset($params['addons_raw'])) {
|
||||
$params['addons'] = is_string($params['addons_raw']) ? $params['addons_raw'] : json_encode($params['addons_raw'], JSON_UNESCAPED_UNICODE);
|
||||
$parsedAddons = is_string($params['addons_raw'])
|
||||
? (json_decode($params['addons_raw'], true) ?: [])
|
||||
: (is_array($params['addons_raw']) ? $params['addons_raw'] : []);
|
||||
unset($params['addons_raw']);
|
||||
$cleanAddons = [];
|
||||
foreach ($parsedAddons as $idx => $ad) {
|
||||
$adName = isset($ad['name']) ? trim((string)$ad['name']) : '';
|
||||
$adPrice = isset($ad['price']) ? round((float)$ad['price'], 2) : 0.00;
|
||||
if ($adName === '' || $adPrice <= 0) {
|
||||
continue;
|
||||
}
|
||||
$cleanAddons[] = [
|
||||
'id' => isset($ad['id']) ? (int)$ad['id'] : ($idx + 1),
|
||||
'code' => isset($ad['code']) ? (string)$ad['code'] : ('addon_' . ($idx + 1)),
|
||||
'name' => $adName,
|
||||
'unit' => !empty($ad['unit']) ? (string)$ad['unit'] : '份',
|
||||
'price' => $adPrice,
|
||||
];
|
||||
}
|
||||
$params['addons'] = json_encode($cleanAddons, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
// 自动从关联的主服务(优先默认主服务或“安装”)同步底层 base_price 与 price_type,商品无需单独填价格
|
||||
// 自动从关联的主服务(优先默认首选主服务)同步底层 base_price 与 price_type
|
||||
if (!empty($parsedTypes)) {
|
||||
$defItem = $parsedTypes[0];
|
||||
foreach ($parsedTypes as $pt) {
|
||||
@@ -251,9 +306,9 @@ class Service extends Backend
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步商品规格型号表(规格不设独立商品价格,仅标识具体施工标的物型号)
|
||||
* 同步商品规格型号表(支持特殊规格单独设价覆盖,留空或0则沿用商品默认服务价)
|
||||
*/
|
||||
protected function syncSpecs($serviceId, $specsInput, $defaultBasePrice = 0.00)
|
||||
protected function syncSpecs($serviceId, $specsInput)
|
||||
{
|
||||
if (empty($serviceId)) return;
|
||||
$now = time();
|
||||
@@ -264,6 +319,9 @@ class Service extends Backend
|
||||
$name = trim(isset($item['name']) ? $item['name'] : '');
|
||||
if ($name === '') continue;
|
||||
$specDesc = isset($item['description']) ? trim($item['description']) : '';
|
||||
$specPrice = (isset($item['base_price']) && is_numeric($item['base_price']) && (float)$item['base_price'] > 0)
|
||||
? round((float)$item['base_price'], 2)
|
||||
: 0.00;
|
||||
$specId = isset($item['id']) ? (int)$item['id'] : 0;
|
||||
$weigh = max(0, 100 - $idx * 5);
|
||||
$idx++;
|
||||
@@ -271,7 +329,7 @@ class Service extends Backend
|
||||
if ($specId > 0) {
|
||||
Db::name('service_spec')->where('id', $specId)->where('service_id', $serviceId)->update([
|
||||
'name' => $name,
|
||||
'base_price' => $defaultBasePrice,
|
||||
'base_price' => $specPrice,
|
||||
'description' => $specDesc,
|
||||
'weigh' => $weigh,
|
||||
'updatetime' => $now,
|
||||
@@ -281,7 +339,7 @@ class Service extends Backend
|
||||
$newId = Db::name('service_spec')->insertGetId([
|
||||
'service_id' => $serviceId,
|
||||
'name' => $name,
|
||||
'base_price' => $defaultBasePrice,
|
||||
'base_price' => $specPrice,
|
||||
'description' => $specDesc,
|
||||
'weigh' => $weigh,
|
||||
'status' => 'normal',
|
||||
|
||||
在新工单中引用
屏蔽一个用户