- 新增师傅端路由和页面配置,切换登录后默认跳转到师傅大厅 - 新增服务分类图标上传功能和增项服务管理模块 - 新增订单、申诉、结算等模型关联关系及后台控制器 - 新增师傅端TabBar组件和消息页面跳转逻辑 - 新增文件上传接口和服务计算逻辑 - 新增各类SVG图标和空状态提示
336 行
20 KiB
HTML
336 行
20 KiB
HTML
<form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
|
|
|
|
<div class="nav-tabs-custom" style="box-shadow: none;">
|
|
<ul class="nav nav-tabs">
|
|
<li class="active"><a href="#tab-basic" data-toggle="tab"><i class="fa fa-info-circle text-primary"></i> 基础信息</a></li>
|
|
<li><a href="#tab-service-types" data-toggle="tab"><i class="fa fa-wrench text-warning"></i> 工项服务定价</a></li>
|
|
<li><a href="#tab-specs" data-toggle="tab"><i class="fa fa-cubes text-success"></i> 规格独立一口价</a></li>
|
|
<li><a href="#tab-addons" data-toggle="tab"><i class="fa fa-plus-square text-danger"></i> 增项施工服务绑定</a></li>
|
|
</ul>
|
|
|
|
<div class="tab-content" style="padding: 15px 0;">
|
|
<!-- Tab 1: 基础信息 -->
|
|
<div class="tab-pane active" id="tab-basic">
|
|
<div class="form-group">
|
|
<label class="control-label col-xs-12 col-sm-2">所属类目:</label>
|
|
<div class="col-xs-12 col-sm-8">
|
|
<input id="c-cat_id" data-rule="required" min="0" data-source="service/cat/index" class="form-control selectpage" name="row[cat_id]" type="text" value="{$row.cat_id|htmlentities}">
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="control-label col-xs-12 col-sm-2">服务/商品名称:</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 class="control-label col-xs-12 col-sm-2">主图:</label>
|
|
<div class="col-xs-12 col-sm-8">
|
|
<div class="input-group">
|
|
<input id="c-image" class="form-control" size="50" 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 plupload" data-input-id="c-image" data-mimetype="image/gif,image/jpeg,image/png,image/jpg,image/bmp,image/webp" data-multiple="false" data-preview-id="p-image"><i class="fa fa-upload"></i> 上传</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> 选择</button></span>
|
|
</div>
|
|
<span class="msg-box n-right" for="c-image"></span>
|
|
</div>
|
|
<ul class="row list-inline plupload-preview" id="p-image"></ul>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="control-label col-xs-12 col-sm-2">计价模式:</label>
|
|
<div class="col-xs-12 col-sm-8">
|
|
<select id="c-price_type" data-rule="required" class="form-control selectpicker" name="row[price_type]">
|
|
{foreach name="priceTypeList" item="vo"}
|
|
<option value="{$key}" {in name="key" value="$row.price_type"}selected{/in}>{$vo}</option>
|
|
{/foreach}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="control-label col-xs-12 col-sm-2">基准一口价/参考价(元):</label>
|
|
<div class="col-xs-12 col-sm-8">
|
|
<input id="c-base_price" data-rule="required" class="form-control" step="0.01" name="row[base_price]" type="number" value="{$row.base_price|htmlentities}">
|
|
<span class="help-block text-muted"><i class="fa fa-info-circle"></i> 作为该商品的通用基准价(若各工项未单独定价时默认采用此价)</span>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="control-label col-xs-12 col-sm-2">计价单位:</label>
|
|
<div class="col-xs-12 col-sm-8">
|
|
<input id="c-unit" data-rule="required" class="form-control" name="row[unit]" type="text" value="{$row.unit|htmlentities}" placeholder="如:件、台、套、次">
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="control-label col-xs-12 col-sm-2">步梯楼层费(元/层):</label>
|
|
<div class="col-xs-12 col-sm-8">
|
|
<input id="c-floor_fee" data-rule="required" class="form-control" step="0.01" name="row[floor_fee]" type="number" value="{$row.floor_fee|htmlentities}">
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="control-label col-xs-12 col-sm-2">免费楼层数:</label>
|
|
<div class="col-xs-12 col-sm-8">
|
|
<input id="c-free_floor" data-rule="required" class="form-control" name="row[free_floor]" type="number" value="{$row.free_floor|htmlentities}">
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="control-label col-xs-12 col-sm-2">服务简介说明:</label>
|
|
<div class="col-xs-12 col-sm-8">
|
|
<textarea id="c-description" class="form-control" rows="3" name="row[description]">{$row.description|htmlentities}</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-8">
|
|
<input id="c-weigh" data-rule="required" 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">状态:</label>
|
|
<div class="col-xs-12 col-sm-8">
|
|
<div class="radio">
|
|
{foreach name="statusList" item="vo"}
|
|
<label for="row[status]-{$key}"><input id="row[status]-{$key}" name="row[status]" type="radio" value="{$key}" {in name="key" value="$row.status"}checked{/in} /> {$vo}</label>
|
|
{/foreach}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tab 2: 工项服务定价 -->
|
|
<div class="tab-pane" id="tab-service-types">
|
|
<div class="alert alert-info-light">
|
|
<i class="fa fa-info-circle"></i> 勾选此商品支持的服务工项(如安装、维修、拆旧等),并可为每个工项设定独立一口价。
|
|
</div>
|
|
<table class="table table-bordered table-striped" id="service-types-table">
|
|
<thead>
|
|
<tr class="active">
|
|
<th style="width: 60px; text-align: center;">启用</th>
|
|
<th style="width: 120px;">工项标识</th>
|
|
<th style="width: 160px;">工项显示名称</th>
|
|
<th style="width: 140px;">工项一口价(元)</th>
|
|
<th style="width: 80px; text-align: center;">默认勾选</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php
|
|
$defaultTypes = [
|
|
'install' => ['name' => '安装', 'price' => $row['base_price'], 'default' => 1],
|
|
'repair' => ['name' => '维修', 'price' => round($row['base_price'] * 0.7, 2), 'default' => 0],
|
|
'remove' => ['name' => '拆旧', 'price' => round($row['base_price'] * 0.5, 2), 'default' => 0],
|
|
'deliver' => ['name' => '送货到家', 'price' => 50.00, 'default' => 0],
|
|
'deliver_install' => ['name' => '送货到家并安装', 'price' => $row['base_price'] + 50.00, 'default' => 0],
|
|
'measure' => ['name' => '坑距测量(含拆旧)', 'price' => 40.00, 'default' => 0],
|
|
'maintain' => ['name' => '保养', 'price' => 60.00, 'default' => 0],
|
|
];
|
|
$savedMap = [];
|
|
foreach ($serviceTypes as $st) {
|
|
if (isset($st['code'])) {
|
|
$savedMap[$st['code']] = $st;
|
|
}
|
|
}
|
|
?>
|
|
{foreach name="defaultTypes" item="cfg" key="code"}
|
|
<?php
|
|
$isCheck = !empty($savedMap) ? isset($savedMap[$code]) : true;
|
|
$curName = isset($savedMap[$code]['name']) ? $savedMap[$code]['name'] : $cfg['name'];
|
|
$curPrice = isset($savedMap[$code]['price']) ? $savedMap[$code]['price'] : $cfg['price'];
|
|
$isDef = isset($savedMap[$code]['is_default']) ? $savedMap[$code]['is_default'] : $cfg['default'];
|
|
?>
|
|
<tr>
|
|
<td style="text-align: center; vertical-align: middle;">
|
|
<input type="checkbox" class="st-enable" data-code="{$code}" {if $isCheck}checked{/if}>
|
|
</td>
|
|
<td style="vertical-align: middle;"><code>{$code}</code></td>
|
|
<td>
|
|
<input type="text" class="form-control input-sm st-name" data-code="{$code}" value="{$curName}">
|
|
</td>
|
|
<td>
|
|
<div class="input-group input-group-sm">
|
|
<span class="input-group-addon">¥</span>
|
|
<input type="number" step="0.01" class="form-control st-price" data-code="{$code}" value="{$curPrice}">
|
|
</div>
|
|
</td>
|
|
<td style="text-align: center; vertical-align: middle;">
|
|
<input type="radio" name="st_default_radio" class="st-default" data-code="{$code}" {if $isDef}checked{/if}>
|
|
</td>
|
|
</tr>
|
|
{/foreach}
|
|
</tbody>
|
|
</table>
|
|
<input type="hidden" name="row[service_types_raw]" id="service_types_raw" value="">
|
|
</div>
|
|
|
|
<!-- Tab 3: 规格独立定价 -->
|
|
<div class="tab-pane" id="tab-specs">
|
|
<div class="alert alert-success-light">
|
|
<i class="fa fa-info-circle"></i> 为该商品增设不同规格(如:单眼灶/双眼灶、普通坐便器/智能马桶),并分别设置规格基准一口价。
|
|
</div>
|
|
<table class="table table-bordered table-striped" id="specs-table">
|
|
<thead>
|
|
<tr class="active">
|
|
<th style="width: 200px;">规格名称</th>
|
|
<th style="width: 150px;">规格独立一口价(元)</th>
|
|
<th>规格施工描述</th>
|
|
<th style="width: 80px; text-align: center;">操作</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="specs-tbody">
|
|
{foreach name="specs" item="sp" key="idx"}
|
|
<tr data-id="{$sp.id}">
|
|
<td>
|
|
<input type="hidden" name="specs[{$idx}][id]" value="{$sp.id}">
|
|
<input type="text" name="specs[{$idx}][name]" class="form-control input-sm" value="{$sp.name|htmlentities}" placeholder="如:智能一体机">
|
|
</td>
|
|
<td>
|
|
<div class="input-group input-group-sm">
|
|
<span class="input-group-addon">¥</span>
|
|
<input type="number" step="0.01" name="specs[{$idx}][base_price]" class="form-control" value="{$sp.base_price}">
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<input type="text" name="specs[{$idx}][description]" class="form-control input-sm" value="{$sp.description|htmlentities}" placeholder="施工要求说明">
|
|
</td>
|
|
<td style="text-align: center;">
|
|
<button type="button" class="btn btn-xs btn-danger btn-del-spec"><i class="fa fa-trash"></i></button>
|
|
</td>
|
|
</tr>
|
|
{/foreach}
|
|
</tbody>
|
|
</table>
|
|
<button type="button" class="btn btn-sm btn-success" id="btn-add-spec"><i class="fa fa-plus"></i> 添加新规格</button>
|
|
</div>
|
|
|
|
<!-- Tab 4: 增项服务绑定 -->
|
|
<div class="tab-pane" id="tab-addons">
|
|
<div class="alert alert-danger-light">
|
|
<i class="fa fa-info-circle"></i> 从系统增项库中勾选该商品允许加选的增项服务(如马桶勾选拆旧/改坑距,油烟机勾选打孔),并可为该商品定制专属单价(留空则默认按全局价)。
|
|
</div>
|
|
<table class="table table-bordered table-striped" id="addons-table">
|
|
<thead>
|
|
<tr class="active">
|
|
<th style="width: 60px; text-align: center;">绑定</th>
|
|
<th style="width: 180px;">增项名称</th>
|
|
<th style="width: 90px; text-align: center;">单位</th>
|
|
<th style="width: 140px;">平台全局指导价</th>
|
|
<th style="width: 180px;">针对本商品专属单价(元)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php
|
|
$assignedMap = [];
|
|
foreach ($assignedAddons as $ad) {
|
|
if (isset($ad['id'])) {
|
|
$assignedMap[$ad['id']] = $ad;
|
|
}
|
|
}
|
|
?>
|
|
{foreach name="addonsPool" item="ad"}
|
|
<?php
|
|
$isBind = isset($assignedMap[$ad['id']]);
|
|
$customPrice = $isBind && isset($assignedMap[$ad['id']]['price']) ? $assignedMap[$ad['id']]['price'] : $ad['default_price'];
|
|
?>
|
|
<tr>
|
|
<td style="text-align: center; vertical-align: middle;">
|
|
<input type="checkbox" class="ad-bind" data-id="{$ad.id}" data-name="{$ad.name}" data-unit="{$ad.unit}" {if $isBind}checked{/if}>
|
|
</td>
|
|
<td style="vertical-align: middle;">
|
|
<strong>{$ad.name}</strong>
|
|
</td>
|
|
<td style="text-align: center; vertical-align: middle;">
|
|
<span class="badge">{$ad.unit}</span>
|
|
</td>
|
|
<td style="vertical-align: middle; color: #888;">
|
|
¥{$ad.default_price}
|
|
</td>
|
|
<td>
|
|
<div class="input-group input-group-sm">
|
|
<span class="input-group-addon">¥</span>
|
|
<input type="number" step="0.01" class="form-control ad-price" data-id="{$ad.id}" value="{$customPrice}" placeholder="覆盖单价">
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{/foreach}
|
|
</tbody>
|
|
</table>
|
|
<input type="hidden" name="row[addons_raw]" id="addons_raw" value="">
|
|
</div>
|
|
</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" id="btn-submit-service">{:__('OK')}</button>
|
|
<button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
<script>
|
|
// 动态组装工项与增项 JSON
|
|
function collectServiceConfig() {
|
|
// 1. 收集工项
|
|
var serviceTypes = [];
|
|
$('#service-types-table tbody tr').each(function () {
|
|
var $row = $(this);
|
|
var $enable = $row.find('.st-enable');
|
|
if ($enable.is(':checked')) {
|
|
var code = $enable.data('code');
|
|
var name = $row.find('.st-name').val();
|
|
var price = parseFloat($row.find('.st-price').val()) || 0;
|
|
var isDef = $row.find('.st-default').is(':checked') ? 1 : 0;
|
|
serviceTypes.push({
|
|
code: code,
|
|
name: name,
|
|
price: price,
|
|
is_default: isDef
|
|
});
|
|
}
|
|
});
|
|
$('#service_types_raw').val(JSON.stringify(serviceTypes));
|
|
|
|
// 2. 收集增项
|
|
var addons = [];
|
|
$('#addons-table tbody tr').each(function () {
|
|
var $row = $(this);
|
|
var $bind = $row.find('.ad-bind');
|
|
if ($bind.is(':checked')) {
|
|
var id = parseInt($bind.data('id'), 10);
|
|
var name = $bind.data('name');
|
|
var unit = $bind.data('unit');
|
|
var price = parseFloat($row.find('.ad-price').val()) || 0;
|
|
addons.push({
|
|
id: id,
|
|
name: name,
|
|
unit: unit,
|
|
price: price
|
|
});
|
|
}
|
|
});
|
|
$('#addons_raw').val(JSON.stringify(addons));
|
|
}
|
|
|
|
// 监听表单提交事件,在提交前组装 JSON
|
|
$(document).on('submit', '#edit-form', function () {
|
|
collectServiceConfig();
|
|
});
|
|
|
|
// 动态添加规格
|
|
var specIndex = 1000;
|
|
$(document).on('click', '#btn-add-spec', function () {
|
|
specIndex++;
|
|
var html = '<tr>' +
|
|
'<td><input type="text" name="specs[' + specIndex + '][name]" class="form-control input-sm" placeholder="规格名称(如:四眼炒灶)"></td>' +
|
|
'<td><div class="input-group input-group-sm"><span class="input-group-addon">¥</span><input type="number" step="0.01" name="specs[' + specIndex + '][base_price]" class="form-control" value="0.00"></div></td>' +
|
|
'<td><input type="text" name="specs[' + specIndex + '][description]" class="form-control input-sm" placeholder="施工说明"></td>' +
|
|
'<td style="text-align:center;"><button type="button" class="btn btn-xs btn-danger btn-del-spec"><i class="fa fa-trash"></i></button></td>' +
|
|
'</tr>';
|
|
$('#specs-tbody').append(html);
|
|
});
|
|
|
|
// 删除规格
|
|
$(document).on('click', '.btn-del-spec', function () {
|
|
$(this).closest('tr').remove();
|
|
});
|
|
</script>
|