feat(admin): 重构服务管理模块新增增值服务功能

- 新增增值服务管理模块,支持按类目筛选绑定
- 新增工项服务定价和规格独立定价功能
- 优化前端订单页增值服务展示逻辑
- 升级版本号至1.0.19
这个提交包含在:
YuanWen
2026-11-04 16:14:44 +08:00
父节点 78d45eea74
当前提交 127b606e75
共有 50 个文件被更改,包括 4149 次插入 和 197 次删除

查看文件

@@ -92,11 +92,25 @@ class Master extends Base
if (!$master) {
$this->success('未入驻', ['applied' => false]);
}
$skills = Db::name('master_skill')->alias('s')
$skillsRaw = Db::name('master_skill')->alias('s')
->join('service_cat c', 'c.id = s.cat_id', 'LEFT')
->field('s.cat_id,c.name,c.icon')
->field('s.cat_id,s.skill_id,s.skill_name,s.category,s.is_custom,c.name as cat_name,c.icon')
->where('s.master_id', $master['id'])
->select();
$skills = [];
foreach ($skillsRaw as $sr) {
$name = !empty($sr['skill_name']) ? $sr['skill_name'] : ($sr['cat_name'] ?? '');
if ($name) {
$skills[] = [
'cat_id' => (int)$sr['cat_id'],
'skill_id' => (int)$sr['skill_id'],
'name' => $name,
'category' => $sr['category'] ?: '服务技能',
'is_custom' => (int)$sr['is_custom'],
'icon' => $sr['icon'] ?? ''
];
}
}
$todo = Db::name('order')->where('master_id', $master['id'])
->where('status', 'in', [OrderStatus::ACCEPTED, OrderStatus::SCHEDULED, OrderStatus::ARRIVED, OrderStatus::WORKING])
@@ -915,4 +929,160 @@ class Master extends Base
$this->success('', $data);
}
/**
* 获取技能字典树与师傅当前选定状态
* @ApiMethod (GET)
*/
public function skillDict()
{
$master = $this->masterInfo();
$masterId = $master ? (int)$master['id'] : 0;
// 1. 获取所有正常启用的字典项
$dictList = Db::name('skill_dict')
->where('status', 'normal')
->order('weigh desc, id asc')
->select();
// 2. 按大类分组
$groups = [];
$categoryOrder = ['安装维修', '建筑装修', '物流运输', '汽车服务', '家政服务', '便民服务'];
foreach ($categoryOrder as $cat) {
$groups[$cat] = [];
}
foreach ($dictList as $item) {
$cat = $item['category'];
if (!isset($groups[$cat])) {
$groups[$cat] = [];
}
$groups[$cat][] = [
'id' => (int)$item['id'],
'name' => $item['name'],
'category' => $item['category'],
'source' => $item['source'],
];
}
$tree = [];
foreach ($groups as $catName => $items) {
if (!empty($items)) {
$tree[] = [
'category' => $catName,
'items' => $items
];
}
}
// 3. 当前师傅已勾选的技能
$selectedNames = [];
$customText = '';
if ($masterId > 0) {
$mySkills = Db::name('master_skill')->where('master_id', $masterId)->select();
$customArr = [];
foreach ($mySkills as $ms) {
$sName = !empty($ms['skill_name']) ? $ms['skill_name'] : '';
if ($ms['is_custom'] == 1) {
$customArr[] = $sName;
} else if ($sName) {
$selectedNames[] = $sName;
}
}
$customText = implode(' ', $customArr);
}
$this->success('ok', [
'tree' => $tree,
'selected_skills' => $selectedNames,
'custom_text' => $customText,
]);
}
/**
* 保存师傅服务技能与自定义输入技能
* @ApiMethod (POST)
*/
public function saveSkills()
{
$master = $this->requireMaster();
$selectedSkills = (array)$this->request->post('selected_skills/a', []);
$customText = trim((string)$this->request->post('custom_text', ''));
// 1. 处理自定义输入的技能
$customNames = [];
if (!empty($customText)) {
$parts = preg_split('/[,,\s]+/u', $customText);
foreach ($parts as $p) {
$p = trim($p);
if (!empty($p) && !in_array($p, $customNames) && !in_array($p, $selectedSkills)) {
$customNames[] = $p;
}
}
}
if (empty($selectedSkills) && empty($customNames)) {
$this->error('请至少选择或输入一项服务技能');
}
// 2. 清理当前师傅原有的技能
Db::name('master_skill')->where('master_id', $master['id'])->delete();
// 3. 写入字典勾选的技能
$dictRows = Db::name('skill_dict')->where('name', 'in', $selectedSkills)->select();
$dictMap = [];
foreach ($dictRows as $dr) {
$dictMap[$dr['name']] = $dr;
}
$now = time();
foreach ($selectedSkills as $sName) {
$dict = $dictMap[$sName] ?? null;
Db::name('master_skill')->insert([
'master_id' => $master['id'],
'cat_id' => 0,
'skill_id' => $dict ? $dict['id'] : 0,
'skill_name' => $sName,
'category' => $dict ? $dict['category'] : '服务技能',
'is_custom' => 0,
'cert_image' => '',
'status' => 'normal',
'createtime' => $now
]);
}
// 4. 处理自定义输入的技能(沉淀入库到 skill_dict 且归属当前师傅)
foreach ($customNames as $cName) {
$exist = Db::name('skill_dict')->where('name', $cName)->find();
if (!$exist) {
$skillDictId = Db::name('skill_dict')->insertGetId([
'category' => '其他技能',
'name' => $cName,
'source' => 'custom',
'master_id' => $master['id'],
'weigh' => 0,
'status' => 'normal',
'createtime' => $now,
'updatetime' => $now
]);
} else {
$skillDictId = $exist['id'];
}
Db::name('master_skill')->insert([
'master_id' => $master['id'],
'cat_id' => 0,
'skill_id' => $skillDictId,
'skill_name' => $cName,
'category' => '其他技能',
'is_custom' => 1,
'cert_image' => '',
'status' => 'normal',
'createtime' => $now
]);
}
$this->success('服务技能保存成功');
}
}