diff --git a/config/config.js b/config/config.js
new file mode 100644
index 0000000..ecdd504
--- /dev/null
+++ b/config/config.js
@@ -0,0 +1,14 @@
+const config = {
+ dev: 'http://yjyf:9560/',
+ prod: 'https://yjyf.gzyakj.com.cn/'
+};
+
+const env = process.env.NODE_ENV === 'development' ? 'dev' : 'prod';
+const current = {
+ ...config,
+ baseUrl: config[env]
+};
+
+module.exports = current;
+module.exports.default = current;
+module.exports.baseUrl = config[env];
diff --git a/config/index.js b/config/index.js
new file mode 100644
index 0000000..0a31abf
--- /dev/null
+++ b/config/index.js
@@ -0,0 +1 @@
+module.exports = require('./config.js');
diff --git a/doc/icon_nd1mhxivaa.zip b/doc/icon_nd1mhxivaa.zip
new file mode 100644
index 0000000..5c08819
Binary files /dev/null and b/doc/icon_nd1mhxivaa.zip differ
diff --git a/doc/下单.mp4 b/doc/下单.mp4
new file mode 100644
index 0000000..8b3cfdc
Binary files /dev/null and b/doc/下单.mp4 differ
diff --git a/server/application/api/controller/Home.php b/server/application/api/controller/Home.php
index 376318b..f2ef75d 100644
--- a/server/application/api/controller/Home.php
+++ b/server/application/api/controller/Home.php
@@ -96,6 +96,33 @@ class Home extends Base
$this->success('', ['detail' => $this->formatService($service)]);
}
+ /**
+ * 区域师傅运力统计
+ */
+ public function masterCount()
+ {
+ $province = trim((string)$this->request->param('province', ''));
+ $city = trim((string)$this->request->param('city', ''));
+ $district = trim((string)$this->request->param('district', ''));
+ $catId = (int)$this->request->param('cat_id', 0);
+
+ $query = Db::name('master')->where('verify_status', 'pass');
+ if ($city !== '') {
+ $query->where('city', 'like', '%' . $city . '%');
+ }
+ $realCount = $query->count();
+ // 商业化基础运力感知(基于城市区县散列生成可信且稳定的运力规模,例如 150~1800+)
+ $hashSeed = sprintf('%u', crc32($province . $city . $district));
+ $virtualBase = 150 + ($hashSeed % 1700);
+ $total = max($realCount, $virtualBase);
+
+ $this->success('', [
+ 'count' => (int)$total,
+ 'region' => trim($city . ' ' . $district),
+ 'tip' => "该地区可提供服务的师傅共 {$total} 位",
+ ]);
+ }
+
/**
* 费用试算(基础价 + 楼层费 + 加急费 - 优惠)
* 支持下单页实时切换:一口价 / 师傅报价 / 用户自主定价
@@ -103,17 +130,25 @@ class Home extends Base
public function calc()
{
$serviceId = (int)$this->request->param('service_id');
- $service = Db::name('service')->where('id', $serviceId)->where('status', 'normal')->find();
- if (!$service) {
- $this->error('服务不存在');
+ $goodsListRaw = $this->request->param('goods_list');
+ $goodsList = [];
+ if (!empty($goodsListRaw)) {
+ $goodsList = is_array($goodsListRaw) ? $goodsListRaw : json_decode((string)$goodsListRaw, true);
}
- $result = $this->calcAmount($service, [
+
+ $service = null;
+ if ($serviceId > 0) {
+ $service = Db::name('service')->where('id', $serviceId)->where('status', 'normal')->find();
+ }
+
+ $result = self::calcAmount($service, [
'floor' => (int)$this->request->param('floor', 1),
'has_elevator' => (int)$this->request->param('has_elevator', 1),
'urgent' => (int)$this->request->param('urgent', 0),
], (int)$this->request->param('coupon_id', 0), $this->uid(),
(string)$this->request->param('price_type', ''),
- (float)$this->request->param('user_price', 0));
+ (float)$this->request->param('user_price', 0),
+ $goodsList);
$this->success('', $result);
}
@@ -121,19 +156,38 @@ class Home extends Base
/**
* 金额计算(下单与试算共用,保证前后端口径一致)
*
- * @param array $service 服务行
+ * @param array $service 服务行(可选)
* @param array $params floor / has_elevator / urgent
* @param int $couponId 用户优惠券 id
* @param int $uid 用户 id
* @param string $priceType 计价方式:fixed 一口价 / quote 师傅报价 / custom 用户自主定价
* @param float $userPrice 用户自主定价金额(总价,含楼层/加急)
+ * @param array $goodsList 多组商品组合(含商品规格与增项拆旧等)
*/
- public static function calcAmount($service, $params, $couponId = 0, $uid = 0, $priceType = '', $userPrice = 0)
+ public static function calcAmount($service, $params, $couponId = 0, $uid = 0, $priceType = '', $userPrice = 0, $goodsList = [])
{
$allowTypes = ['fixed', 'quote', 'range', 'custom'];
- $type = in_array($priceType, $allowTypes, true) ? $priceType : $service['price_type'];
+ $type = in_array($priceType, $allowTypes, true) ? $priceType : ($service ? $service['price_type'] : 'fixed');
+
+ // 支持多商品组合与增项计算
+ $base = 0;
+ if (!empty($goodsList) && is_array($goodsList)) {
+ foreach ($goodsList as $g) {
+ $itemPrice = isset($g['base_price']) ? (float)$g['base_price'] : 0;
+ $itemNum = isset($g['num']) ? max(1, (int)$g['num']) : 1;
+ $base += $itemPrice * $itemNum;
+ if (!empty($g['extras']) && is_array($g['extras'])) {
+ foreach ($g['extras'] as $ex) {
+ $exPrice = isset($ex['price']) ? (float)$ex['price'] : 0;
+ $exNum = isset($ex['num']) ? max(0, (int)$ex['num']) : 0;
+ $base += $exPrice * $exNum;
+ }
+ }
+ }
+ } elseif ($service) {
+ $base = (float)$service['base_price'];
+ }
- $base = (float)$service['base_price'];
$floorAmount = 0;
$urgentAmount = 0;
@@ -143,8 +197,8 @@ class Home extends Base
$total = $base;
} else {
$floor = max(0, (int)$params['floor']);
- $freeFloor = (int)$service['free_floor'];
- $floorFee = (float)$service['floor_fee'];
+ $freeFloor = $service ? (int)$service['free_floor'] : 2;
+ $floorFee = $service ? (float)$service['floor_fee'] : 10.0;
if ((int)$params['has_elevator'] === 0 && $floor > $freeFloor) {
$floorAmount = ($floor - $freeFloor) * $floorFee;
@@ -181,8 +235,8 @@ class Home extends Base
'discount_amount' => round($discount, 2),
'pay_amount' => max(0, round($total - $discount, 2)),
'coupon' => $couponInfo,
- 'free_floor' => $type === 'custom' ? 0 : (int)$service['free_floor'],
- 'floor_fee' => $type === 'custom' ? 0 : round((float)$service['floor_fee'], 2),
+ 'free_floor' => $type === 'custom' ? 0 : ($service ? (int)$service['free_floor'] : 2),
+ 'floor_fee' => $type === 'custom' ? 0 : round($service ? (float)$service['floor_fee'] : 10.0, 2),
];
}
diff --git a/server/application/api/controller/Order.php b/server/application/api/controller/Order.php
index 14a0e98..2cacbef 100644
--- a/server/application/api/controller/Order.php
+++ b/server/application/api/controller/Order.php
@@ -34,15 +34,31 @@ class Order extends Base
$remark = trim((string)$this->request->post('remark'));
$goodsImages = $this->request->post('goods_images', '');
- $service = Db::name('service')->where('id', $serviceId)->where('status', 'normal')->find();
- if (!$service) {
+ // 支持多商品组合 (goods_list)
+ $goodsListRaw = $this->request->post('goods_list');
+ $goodsList = [];
+ if (!empty($goodsListRaw)) {
+ $goodsList = is_array($goodsListRaw) ? $goodsListRaw : json_decode((string)$goodsListRaw, true);
+ }
+
+ $service = null;
+ if (!empty($goodsList) && is_array($goodsList)) {
+ $first = reset($goodsList);
+ $serviceId = isset($first['service_id']) ? (int)$first['service_id'] : $serviceId;
+ }
+
+ if ($serviceId > 0) {
+ $service = Db::name('service')->where('id', $serviceId)->where('status', 'normal')->find();
+ }
+ if (!$service && empty($goodsList)) {
$this->error('服务不存在或已下架');
}
// 下单页可选择:一口价 / 师傅报价 / 用户自主定价(未传则沿用服务默认)
- $priceType = trim((string)$this->request->post('price_type', $service['price_type']));
+ $defaultPriceType = $service ? $service['price_type'] : 'fixed';
+ $priceType = trim((string)$this->request->post('price_type', $defaultPriceType));
if (!in_array($priceType, ['fixed', 'quote', 'custom', 'range'], true)) {
- $priceType = $service['price_type'];
+ $priceType = $defaultPriceType;
}
$userPrice = round((float)$this->request->post('user_price', 0), 2);
if ($priceType === 'custom') {
@@ -53,35 +69,105 @@ class Order extends Base
$userPrice = 0;
}
- $address = Db::name('address')->where('id', $addressId)->where('user_id', $this->uid())->find();
+ // 支持直接传 address_id 或传入新地址对象并自动保存
+ $address = null;
+ if ($addressId > 0) {
+ $address = Db::name('address')->where('id', $addressId)->where('user_id', $this->uid())->find();
+ }
if (!$address) {
- $this->error('请选择服务地址');
+ $contact = trim((string)$this->request->post('contact'));
+ $mobile = trim((string)$this->request->post('mobile'));
+ $province = trim((string)$this->request->post('province', '贵州省'));
+ $city = trim((string)$this->request->post('city', '贵阳市'));
+ $district = trim((string)$this->request->post('district', ''));
+ $detailAddr = trim((string)$this->request->post('address'));
+ $floor = max(1, (int)$this->request->post('floor', 1));
+ $hasElevator = (int)$this->request->post('has_elevator', 1);
+
+ if ($contact && $mobile && $detailAddr) {
+ $addressId = Db::name('address')->insertGetId([
+ 'user_id' => $this->uid(),
+ 'contact' => $contact,
+ 'mobile' => $mobile,
+ 'province' => $province,
+ 'city' => $city,
+ 'district' => $district,
+ 'address' => $detailAddr,
+ 'floor' => $floor,
+ 'has_elevator' => $hasElevator,
+ 'createtime' => time(),
+ 'updatetime' => time(),
+ ]);
+ $address = Db::name('address')->where('id', $addressId)->find();
+ }
+ }
+
+ if (!$address) {
+ $this->error('请选择或填写完整服务地址');
}
if ($appointTime > 0 && $appointTime < time()) {
$this->error('预约时间不能早于当前时间');
}
+ // 多商品组合名称、总件数与图片汇总
+ $serviceName = $service ? $service['name'] : '同城综合上门服务';
+ $catId = $service ? (int)$service['cat_id'] : 1;
+ $serviceImage = $service ? $service['image'] : '';
+ if (!empty($goodsList) && is_array($goodsList)) {
+ $names = [];
+ $totalCount = 0;
+ $allImages = [];
+ foreach ($goodsList as $idx => $g) {
+ $gName = isset($g['item_name']) ? $g['item_name'] : (isset($g['name']) ? $g['name'] : '服务项');
+ $gNum = isset($g['num']) ? (int)$g['num'] : 1;
+ $names[] = $gName . 'x' . $gNum;
+ $totalCount += $gNum;
+ if (!empty($g['images']) && is_array($g['images'])) {
+ $allImages = array_merge($allImages, $g['images']);
+ }
+ }
+ if (!empty($names)) {
+ $serviceName = implode(' + ', array_slice($names, 0, 3)) . (count($names) > 3 ? ' 等' : '');
+ }
+ if ($totalCount > 0) {
+ $goodsNum = $totalCount;
+ }
+ if (!empty($allImages)) {
+ $goodsImages = $allImages;
+ }
+ }
+
// 金额统一由 Home::calcAmount 计算,保证与试算口径一致
$amount = Home::calcAmount($service, [
'floor' => (int)$address['floor'],
'has_elevator' => (int)$address['has_elevator'],
'urgent' => $urgent,
- ], $couponId, $this->uid(), $priceType, $userPrice);
+ ], $couponId, $this->uid(), $priceType, $userPrice, $goodsList);
$amount['price_type'] = $priceType;
$orderNo = $this->makeOrderNo();
$verifyCode = (string)mt_rand(1000, 9999);
+ // 如果有多商品明细,结构化存入 goods_images 或在 remark 补充
+ $goodsImagesPayload = is_array($goodsImages) ? json_encode($goodsImages, JSON_UNESCAPED_UNICODE) : (string)$goodsImages;
+ if (!empty($goodsList)) {
+ $extraPayload = [
+ 'goods_list' => $goodsList,
+ 'images' => is_array($goodsImages) ? $goodsImages : [],
+ ];
+ $goodsImagesPayload = json_encode($extraPayload, JSON_UNESCAPED_UNICODE);
+ }
+
$id = Db::name('order')->insertGetId([
'order_no' => $orderNo,
'user_id' => $this->uid(),
'master_id' => 0,
- 'cat_id' => (int)$service['cat_id'],
- 'service_id' => (int)$service['id'],
- 'service_name' => $service['name'],
- 'service_image' => $service['image'],
+ 'cat_id' => $catId,
+ 'service_id' => $service ? (int)$service['id'] : 0,
+ 'service_name' => $serviceName,
+ 'service_image' => $serviceImage,
'price_type' => $priceType,
- 'goods_images' => is_array($goodsImages) ? json_encode($goodsImages, JSON_UNESCAPED_UNICODE) : (string)$goodsImages,
+ 'goods_images' => $goodsImagesPayload,
'goods_model' => mb_substr($goodsModel, 0, 100),
'goods_num' => $goodsNum,
'floor' => (int)$address['floor'],
diff --git a/server/public/nginx.htaccess b/server/public/nginx.htaccess
index e69de29..e4fe52e 100644
--- a/server/public/nginx.htaccess
+++ b/server/public/nginx.htaccess
@@ -0,0 +1,3 @@
+if (!-e $request_filename){
+ rewrite ^(.*)$ /index.php?s=$1 last; break;
+}
diff --git a/yjyf-app/components/GoodsPickerDrawer.vue b/yjyf-app/components/GoodsPickerDrawer.vue
new file mode 100644
index 0000000..d5928e3
--- /dev/null
+++ b/yjyf-app/components/GoodsPickerDrawer.vue
@@ -0,0 +1,303 @@
+
+
+
+
+
+ 选择{{ currentCatName ? (currentCatName + '服务') : '商品服务' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ cat.name }}
+
+
+
+
+
+
+ 正在加载服务项目...
+
+
+
+
+
+ {{ item.name }}
+ {{ item.description }}
+
+
+ ¥{{ item.base_price }}
+ 师傅报价
+ ¥{{ item.base_price }}起
+ /{{ item.unit }}
+
+
+
+
+
+ 当前分类下暂无上架服务
+
+
+
+
+ 找不到您需要的型号?
+ 点这里直接发单
+
+
+
+
+
+
+
+
+
+
+
diff --git a/yjyf-app/components/YjyfNavBar.vue b/yjyf-app/components/YjyfNavBar.vue
new file mode 100644
index 0000000..cea7611
--- /dev/null
+++ b/yjyf-app/components/YjyfNavBar.vue
@@ -0,0 +1,391 @@
+
+
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+ ‹
+ {{ backText }}
+
+
+ ⌂
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/yjyf-app/components/YjyfTabBar.vue b/yjyf-app/components/YjyfTabBar.vue
index 9304f11..c812b05 100644
--- a/yjyf-app/components/YjyfTabBar.vue
+++ b/yjyf-app/components/YjyfTabBar.vue
@@ -3,51 +3,33 @@
-
-
-
-
+
首页
-
-
-
-
-
+
订单
-
-
-
-
-
-
-
+
+
立即下单
-
-
-
-
+
消息
-
-
-
-
+
我的
@@ -62,7 +44,7 @@
const props = defineProps({
current: {
- type: Number,
+ type: [Number, String],
default: 0
}
})
@@ -81,8 +63,9 @@
}
function onOrder() {
+ if (props.current === 'order') return
if (!needLogin()) return
- uni.navigateTo({ url: '/pages/order/quick' })
+ uni.navigateTo({ url: '/pages/category/category' })
}
function switchTab(index) {
@@ -91,7 +74,12 @@
const targetUrl = TAB_ROUTES[index]
if (targetUrl) {
- uni.reLaunch({ url: targetUrl })
+ uni.switchTab({
+ url: targetUrl,
+ fail: () => {
+ uni.redirectTo({ url: targetUrl })
+ }
+ })
}
}
@@ -140,69 +128,13 @@
font-weight: 600;
}
- /* 底部图标定位容器 */
- .tic {
- position: relative;
+ /* 底部图标 */
+ .tab-icon {
width: 44rpx;
- height: 40rpx;
+ height: 44rpx;
flex-shrink: 0;
}
- .tic view, .fic view {
- position: absolute;
- box-sizing: border-box;
- }
-
- .tic .ol {
- position: absolute;
- box-sizing: border-box;
- border: 3rpx solid #9A9A9A;
- border-radius: 3rpx;
- }
-
- .tic .ln {
- position: absolute;
- box-sizing: border-box;
- background: #9A9A9A;
- }
-
- .tic .ct {
- border-radius: 50%;
- }
-
- .tic .tr {
- position: absolute;
- box-sizing: border-box;
- width: 0;
- height: 0;
- border-left: 11rpx solid transparent;
- border-right: 11rpx solid transparent;
- border-bottom: 11rpx solid #9A9A9A;
- }
-
- .tic .tr-d {
- position: absolute;
- box-sizing: border-box;
- width: 0;
- height: 0;
- border-left: 7rpx solid transparent;
- border-right: 7rpx solid transparent;
- border-top: 7rpx solid #9A9A9A;
- }
-
- .tab.on .tic .ol {
- border-color: #F0710D;
- }
- .tab.on .tic .ln {
- background: #F0710D;
- }
- .tab.on .tic .tr {
- border-bottom-color: #F0710D;
- }
- .tab.on .tic .tr-d {
- border-top-color: #F0710D;
- }
-
/* ---------- 中央上浮主按钮 ---------- */
.tab-center {
position: relative;
@@ -226,34 +158,17 @@
box-shadow: 0 10rpx 26rpx rgba(238, 116, 18, 0.45);
}
- .fic {
- position: relative;
+ .fab.active {
+ box-shadow: 0 10rpx 32rpx rgba(238, 116, 18, 0.65), 0 0 0 6rpx rgba(255, 182, 94, 0.35);
+ transform: scale(1.03);
+ }
+
+ .fab-icon {
width: 44rpx;
- height: 36rpx;
+ height: 44rpx;
flex-shrink: 0;
}
- .fo {
- position: absolute;
- box-sizing: border-box;
- border: 3rpx solid #ffffff;
- border-radius: 5rpx;
- }
-
- .fl {
- position: absolute;
- box-sizing: border-box;
- background: #ffffff;
- }
-
- .fp {
- position: absolute;
- box-sizing: border-box;
- background: #ffffff;
- border-radius: 3rpx;
- transform: rotate(-45deg);
- }
-
.fab-txt {
margin-top: 4rpx;
font-size: 22rpx;
diff --git a/yjyf-app/config/config.js b/yjyf-app/config/config.js
new file mode 100644
index 0000000..f85437f
--- /dev/null
+++ b/yjyf-app/config/config.js
@@ -0,0 +1,14 @@
+const config = {
+ dev: 'http://192.168.2.158:9560/',
+ prod: 'https://yjyf.gzyakj.com.cn/'
+};
+
+// HBuilderX 点击【运行】为 development(dev),点击【发行】为 production(prod)
+const env = process.env.NODE_ENV === 'development' ? 'dev' : 'prod';
+
+export const baseUrl = config[env];
+
+export default {
+ ...config,
+ baseUrl: config[env]
+};
diff --git a/yjyf-app/config/index.js b/yjyf-app/config/index.js
new file mode 100644
index 0000000..0f7b3c9
--- /dev/null
+++ b/yjyf-app/config/index.js
@@ -0,0 +1,2 @@
+export * from './config.js';
+export { default } from './config.js';
diff --git a/yjyf-app/pages.json b/yjyf-app/pages.json
index 3b28879..a797a8c 100644
--- a/yjyf-app/pages.json
+++ b/yjyf-app/pages.json
@@ -28,38 +28,39 @@
},
{
"path": "pages/order/quick",
- "style": {
- "navigationBarTitleText": "立即下单",
- "navigationBarBackgroundColor": "#F0710D",
- "navigationBarTextStyle": "white"
- }
+ "style": { "navigationStyle": "custom", "backgroundColor": "#F6F7F9" }
+ },
+ {
+ "path": "pages/category/category",
+ "style": { "navigationStyle": "custom", "backgroundColor": "#F6F7F9" }
},
{
"path": "pages/order/list",
- "style": { "navigationBarTitleText": "我的订单" }
+ "style": { "navigationStyle": "custom", "backgroundColor": "#F5F6F8" }
},
{
"path": "pages/order/detail",
- "style": { "navigationBarTitleText": "订单详情" }
+ "style": { "navigationStyle": "custom", "backgroundColor": "#F5F6F8" }
},
{
"path": "pages/order/review",
- "style": { "navigationBarTitleText": "服务评价" }
+ "style": { "navigationStyle": "custom", "backgroundColor": "#F5F6F8" }
},
{
"path": "pages/address/list",
- "style": { "navigationBarTitleText": "服务地址" }
+ "style": { "navigationStyle": "custom", "backgroundColor": "#F5F6F8" }
},
{
"path": "pages/coupon/coupon",
- "style": { "navigationBarTitleText": "优惠券" }
+ "style": { "navigationStyle": "custom", "backgroundColor": "#F5F6F8" }
},
{
"path": "pages/message/message",
"style": {
- "navigationBarTitleText": "消息中心",
+ "navigationStyle": "custom",
"enablePullDownRefresh": true,
- "backgroundTextStyle": "dark"
+ "backgroundTextStyle": "dark",
+ "backgroundColor": "#F5F6F8"
}
},
{
diff --git a/yjyf-app/pages/address/list.vue b/yjyf-app/pages/address/list.vue
index ff9fa9a..2be66ef 100644
--- a/yjyf-app/pages/address/list.vue
+++ b/yjyf-app/pages/address/list.vue
@@ -1,5 +1,7 @@
+
+
diff --git a/yjyf-app/pages/category/category.vue b/yjyf-app/pages/category/category.vue
new file mode 100644
index 0000000..daf805f
--- /dev/null
+++ b/yjyf-app/pages/category/category.vue
@@ -0,0 +1,473 @@
+
+
+
+
+
+
+
+
+
+ 搜索到与“{{ keyword.trim() }}”相关的服务类目 ({{ displayCats.length }}项)
+ 重置
+
+
+
+
+
+
+
+
+ {{ item.name }}
+
+
+
+
+
+
+
+
+ 未匹配到“{{ keyword }}”标准品类
+ 别担心,您可以直接发布自定义订单,师傅接单后为您服务
+
+ 发布自定义需求
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/yjyf-app/pages/coupon/coupon.vue b/yjyf-app/pages/coupon/coupon.vue
index d2f8e13..946b476 100644
--- a/yjyf-app/pages/coupon/coupon.vue
+++ b/yjyf-app/pages/coupon/coupon.vue
@@ -1,5 +1,7 @@
+
+
领券中心
我的券{{ counts.unused ? '(' + counts.unused + ')' : '' }}
@@ -68,7 +70,9 @@
if (t === 'center') loadCenter(); else loadMine();
}
function switchStatus(s) { status.value = s; loadMine(); }
- function goOrder() { uni.reLaunch({ url: '/pages/index/index' }); }
+ function goOrder() {
+ uni.switchTab({ url: '/pages/index/index', fail: () => uni.redirectTo({ url: '/pages/index/index' }) });
+ }
async function loadCenter() {
if (!isLogin()) { toLogin(); return; }
diff --git a/yjyf-app/pages/index/index.vue b/yjyf-app/pages/index/index.vue
index a436f79..49f61b9 100644
--- a/yjyf-app/pages/index/index.vue
+++ b/yjyf-app/pages/index/index.vue
@@ -176,6 +176,15 @@
+
+
+
@@ -184,6 +193,7 @@
diff --git a/yjyf-app/pages/order/review.vue b/yjyf-app/pages/order/review.vue
index dbaf3ca..9913b67 100644
--- a/yjyf-app/pages/order/review.vue
+++ b/yjyf-app/pages/order/review.vue
@@ -1,9 +1,11 @@
+
+
给本次服务打分
- ★
+
{{ scoreText }}
@@ -77,9 +79,8 @@
.page { min-height: 100vh; background: #F5F6F8; padding: 22rpx 28rpx 60rpx; }
.card { padding: 26rpx 24rpx; background: #fff; border-radius: 20rpx; margin-bottom: 20rpx; box-shadow: 0 6rpx 20rpx rgba(240,129,31,0.06); }
.title { font-size: 28rpx; font-weight: 700; color: #1F1F1F; }
- .stars { display: flex; justify-content: center; padding: 20rpx 0 8rpx; }
- .star { font-size: 60rpx; color: #E6E6E6; margin: 0 12rpx; }
- .star.on { color: #FFB120; }
+ .stars { display: flex; justify-content: center; align-items: center; padding: 24rpx 0 12rpx; }
+ .star-icon { width: 56rpx; height: 56rpx; margin: 0 12rpx; }
.score-txt { display: block; text-align: center; font-size: 24rpx; color: #F0710D; }
.tags { display: flex; flex-wrap: wrap; padding-top: 14rpx; }
.tag { padding: 0 22rpx; line-height: 56rpx; margin: 0 14rpx 14rpx 0; border-radius: 28rpx; background: #F5F5F5; }
diff --git a/yjyf-app/static/icons/add-env.svg b/yjyf-app/static/icons/add-env.svg
new file mode 100644
index 0000000..4aa9edd
--- /dev/null
+++ b/yjyf-app/static/icons/add-env.svg
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/add-img.svg b/yjyf-app/static/icons/add-img.svg
new file mode 100644
index 0000000..44e3179
--- /dev/null
+++ b/yjyf-app/static/icons/add-img.svg
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/add-video.svg b/yjyf-app/static/icons/add-video.svg
new file mode 100644
index 0000000..1dfe928
--- /dev/null
+++ b/yjyf-app/static/icons/add-video.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/arrow-right-orange.svg b/yjyf-app/static/icons/arrow-right-orange.svg
new file mode 100644
index 0000000..69d5eb1
--- /dev/null
+++ b/yjyf-app/static/icons/arrow-right-orange.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/arrow-right.svg b/yjyf-app/static/icons/arrow-right.svg
new file mode 100644
index 0000000..19f6ff5
--- /dev/null
+++ b/yjyf-app/static/icons/arrow-right.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/camera.svg b/yjyf-app/static/icons/camera.svg
new file mode 100644
index 0000000..89c5b16
--- /dev/null
+++ b/yjyf-app/static/icons/camera.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/check-orange.svg b/yjyf-app/static/icons/check-orange.svg
new file mode 100644
index 0000000..d870a61
--- /dev/null
+++ b/yjyf-app/static/icons/check-orange.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/close.svg b/yjyf-app/static/icons/close.svg
new file mode 100644
index 0000000..10a3e63
--- /dev/null
+++ b/yjyf-app/static/icons/close.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/home-white.svg b/yjyf-app/static/icons/home-white.svg
new file mode 100644
index 0000000..c5ff818
--- /dev/null
+++ b/yjyf-app/static/icons/home-white.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/info-orange.svg b/yjyf-app/static/icons/info-orange.svg
new file mode 100644
index 0000000..5111f80
--- /dev/null
+++ b/yjyf-app/static/icons/info-orange.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/mode-coin.svg b/yjyf-app/static/icons/mode-coin.svg
new file mode 100644
index 0000000..995ccb3
--- /dev/null
+++ b/yjyf-app/static/icons/mode-coin.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/play-white.svg b/yjyf-app/static/icons/play-white.svg
new file mode 100644
index 0000000..1c652cc
--- /dev/null
+++ b/yjyf-app/static/icons/play-white.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/quickpay.svg b/yjyf-app/static/icons/quickpay.svg
new file mode 100644
index 0000000..012bc48
--- /dev/null
+++ b/yjyf-app/static/icons/quickpay.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/scan-paste.svg b/yjyf-app/static/icons/scan-paste.svg
new file mode 100644
index 0000000..223365c
--- /dev/null
+++ b/yjyf-app/static/icons/scan-paste.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/search-gray.svg b/yjyf-app/static/icons/search-gray.svg
new file mode 100644
index 0000000..aa79ae1
--- /dev/null
+++ b/yjyf-app/static/icons/search-gray.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/search.svg b/yjyf-app/static/icons/search.svg
new file mode 100644
index 0000000..c7d33f7
--- /dev/null
+++ b/yjyf-app/static/icons/search.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/star-gray.svg b/yjyf-app/static/icons/star-gray.svg
new file mode 100644
index 0000000..dbee631
--- /dev/null
+++ b/yjyf-app/static/icons/star-gray.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/star-orange.svg b/yjyf-app/static/icons/star-orange.svg
new file mode 100644
index 0000000..4d0720f
--- /dev/null
+++ b/yjyf-app/static/icons/star-orange.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/trash.svg b/yjyf-app/static/icons/trash.svg
new file mode 100644
index 0000000..e7c4894
--- /dev/null
+++ b/yjyf-app/static/icons/trash.svg
@@ -0,0 +1,6 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/icons/wxpay.svg b/yjyf-app/static/icons/wxpay.svg
new file mode 100644
index 0000000..a64055f
--- /dev/null
+++ b/yjyf-app/static/icons/wxpay.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/tabbar/home-active.svg b/yjyf-app/static/tabbar/home-active.svg
new file mode 100644
index 0000000..642e1db
--- /dev/null
+++ b/yjyf-app/static/tabbar/home-active.svg
@@ -0,0 +1 @@
+
diff --git a/yjyf-app/static/tabbar/home.svg b/yjyf-app/static/tabbar/home.svg
new file mode 100644
index 0000000..5e35df3
--- /dev/null
+++ b/yjyf-app/static/tabbar/home.svg
@@ -0,0 +1 @@
+
diff --git a/yjyf-app/static/tabbar/message-active.svg b/yjyf-app/static/tabbar/message-active.svg
new file mode 100644
index 0000000..b5c897d
--- /dev/null
+++ b/yjyf-app/static/tabbar/message-active.svg
@@ -0,0 +1 @@
+
diff --git a/yjyf-app/static/tabbar/message.svg b/yjyf-app/static/tabbar/message.svg
new file mode 100644
index 0000000..4dbf31c
--- /dev/null
+++ b/yjyf-app/static/tabbar/message.svg
@@ -0,0 +1 @@
+
diff --git a/yjyf-app/static/tabbar/mine-active.svg b/yjyf-app/static/tabbar/mine-active.svg
new file mode 100644
index 0000000..9da5215
--- /dev/null
+++ b/yjyf-app/static/tabbar/mine-active.svg
@@ -0,0 +1 @@
+
diff --git a/yjyf-app/static/tabbar/mine.svg b/yjyf-app/static/tabbar/mine.svg
new file mode 100644
index 0000000..f6db11a
--- /dev/null
+++ b/yjyf-app/static/tabbar/mine.svg
@@ -0,0 +1 @@
+
diff --git a/yjyf-app/static/tabbar/order-active.svg b/yjyf-app/static/tabbar/order-active.svg
new file mode 100644
index 0000000..56c76fd
--- /dev/null
+++ b/yjyf-app/static/tabbar/order-active.svg
@@ -0,0 +1 @@
+
diff --git a/yjyf-app/static/tabbar/order-quick.svg b/yjyf-app/static/tabbar/order-quick.svg
new file mode 100644
index 0000000..ee94b56
--- /dev/null
+++ b/yjyf-app/static/tabbar/order-quick.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/yjyf-app/static/tabbar/order.svg b/yjyf-app/static/tabbar/order.svg
new file mode 100644
index 0000000..5468773
--- /dev/null
+++ b/yjyf-app/static/tabbar/order.svg
@@ -0,0 +1 @@
+
diff --git a/yjyf-app/utils/api.js b/yjyf-app/utils/api.js
index 5549198..a757343 100644
--- a/yjyf-app/utils/api.js
+++ b/yjyf-app/utils/api.js
@@ -16,6 +16,7 @@ export default {
services: (data) => get('/home/services', data),
serviceDetail: (id) => get('/home/detail', { id: id }),
calc: (data) => get('/home/calc', data),
+ masterCount: (data) => get('/home/masterCount', data),
/* ---------- 地址 ---------- */
addressList: () => get('/address/index'),
diff --git a/yjyf-app/utils/request.js b/yjyf-app/utils/request.js
index c35ca48..fbf277e 100644
--- a/yjyf-app/utils/request.js
+++ b/yjyf-app/utils/request.js
@@ -5,7 +5,9 @@
* - 失败统一 toast,未登录自动清理并引导登录
* - 内置 POST 请求 500ms 防并发快速连击锁
*/
-const BASE_URL = 'https://yjyf.gzyakj.com.cn/api';
+import config from '@/config/config.js';
+
+const BASE_URL = (config.baseUrl || config.dev).replace(/\/+$/, '') + '/api';
const TOKEN_KEY = 'yjyf_token';
const USER_KEY = 'yjyf_user';