feat(admin): 重构服务管理模块新增增值服务功能
- 新增增值服务管理模块,支持按类目筛选绑定 - 新增工项服务定价和规格独立定价功能 - 优化前端订单页增值服务展示逻辑 - 升级版本号至1.0.19
这个提交包含在:
@@ -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('服务技能保存成功');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户