202506061843

This commit is contained in:
张潘 2025-06-06 18:43:19 +08:00
parent fceb5fd135
commit af40a21627
7 changed files with 994 additions and 1231 deletions

View File

@ -1,129 +0,0 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>汽车维修App原型</title>
<style>
body { font-family: 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif; background: #f5f7fa; margin: 0; }
.navbar { background: #409EFF; color: #fff; padding: 16px; text-align: center; font-size: 20px; }
.tabbar { position: fixed; bottom: 0; left: 0; right: 0; background: #fff; border-top: 1px solid #eee; display: flex; }
.tabbar a { flex: 1; text-align: center; padding: 10px 0; color: #888; text-decoration: none; font-size: 15px; }
.tabbar a.active { color: #409EFF; font-weight: bold; }
.container { padding: 20px 16px 70px 16px; max-width: 480px; margin: 0 auto; }
.card { background: #fff; border-radius: 8px; box-shadow: 0 2px 8px #0001; margin-bottom: 18px; padding: 18px; }
.card h2 { margin: 0 0 10px 0; font-size: 18px; }
.btn { display: inline-block; background: #409EFF; color: #fff; border: none; border-radius: 4px; padding: 8px 18px; font-size: 15px; cursor: pointer; margin-top: 10px; }
.section-list { list-style: none; padding: 0; margin: 0; }
.section-list li { padding: 12px 0; border-bottom: 1px solid #f0f0f0; font-size: 16px; }
.profile-avatar { width: 60px; height: 60px; border-radius: 50%; background: #eee; display: block; margin: 0 auto 10px auto; }
.center { text-align: center; }
@media (max-width: 600px) { .container { padding: 12px 4px 70px 4px; } }
</style>
</head>
<body>
<div class="navbar" id="navbar">首页</div>
<div class="container" id="page-home">
<div class="card center">
<h2>欢迎来到汽车维修App</h2>
<p>为您提供专业、便捷的汽车维修服务</p>
</div>
<div class="card">
<h2>功能入口</h2>
<ul class="section-list">
<li><a href="#" onclick="showPage('repair')">维修种类</a></li>
<li><a href="#" onclick="showPage('masters')">师傅入驻</a></li>
<li><a href="#" onclick="showPage('company')">企业介绍</a></li>
<li><a href="#" onclick="showPage('profile')">个人中心</a></li>
</ul>
</div>
</div>
<div class="container" id="page-repair" style="display:none;">
<div class="card">
<h2>维修种类</h2>
<ul class="section-list">
<li>发动机维修</li>
<li>变速箱维修</li>
<li>底盘维修</li>
<li>电路维修</li>
<li>钣金喷漆</li>
<li>空调维修</li>
<li>轮胎更换</li>
<li>更多...</li>
</ul>
</div>
</div>
<div class="container" id="page-masters" style="display:none;">
<div class="card">
<h2>师傅入驻</h2>
<p>欢迎专业汽车维修师傅入驻平台!</p>
<form>
<div style="margin-bottom:10px;">
<input type="text" placeholder="姓名" style="width:100%;padding:8px;">
</div>
<div style="margin-bottom:10px;">
<input type="text" placeholder="联系电话" style="width:100%;padding:8px;">
</div>
<div style="margin-bottom:10px;">
<input type="text" placeholder="擅长维修类型" style="width:100%;padding:8px;">
</div>
<button type="button" class="btn">提交申请</button>
</form>
</div>
</div>
<div class="container" id="page-company" style="display:none;">
<div class="card">
<h2>企业介绍</h2>
<p>本平台专注于汽车维修服务,拥有多年行业经验,致力于为用户提供高效、专业、透明的汽车维修体验。平台聚合了众多优质维修师傅,服务覆盖全国主要城市。</p>
<ul style="margin-top:10px;">
<li>正规资质</li>
<li>价格透明</li>
<li>服务保障</li>
<li>多种维修类型</li>
</ul>
</div>
</div>
<div class="container" id="page-profile" style="display:none;">
<div class="card center">
<div class="profile-avatar"></div>
<div style="font-size:18px;">张三</div>
<div style="color:#888;">普通用户</div>
</div>
<div class="card">
<h2>我的信息</h2>
<ul class="section-list">
<li>我的订单</li>
<li>我的车辆</li>
<li>我的收藏</li>
<li>设置</li>
<li>退出登录</li>
</ul>
</div>
</div>
<div class="tabbar">
<a href="#" id="tab-home" class="active" onclick="showPage('home')">首页</a>
<a href="#" id="tab-repair" onclick="showPage('repair')">维修种类</a>
<a href="#" id="tab-masters" onclick="showPage('masters')">师傅入驻</a>
<a href="#" id="tab-company" onclick="showPage('company')">企业介绍</a>
<a href="#" id="tab-profile" onclick="showPage('profile')">个人中心</a>
</div>
<script>
function showPage(page) {
const pages = ['home','repair','masters','company','profile'];
pages.forEach(p => {
document.getElementById('page-' + p).style.display = (p === page) ? '' : 'none';
document.getElementById('tab-' + p).className = (p === page) ? 'active' : '';
});
// 设置顶部标题
var titleMap = {
home: '首页',
repair: '维修种类',
masters: '师傅入驻',
company: '企业介绍',
profile: '个人中心'
};
document.getElementById('navbar').innerText = titleMap[page];
}
</script>
</body>
</html>

View File

@ -0,0 +1,136 @@
package com.ruoyi.system.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.service.IOrderService;
import com.ruoyi.system.service.IServiceGoodsService;
import com.ruoyi.system.service.IQuoteMaterialService;
import com.ruoyi.system.service.ISysUserService;
/**
* 首页相关接口Controller
*
* @author ruoyi
* @date 2025-01-10
*/
@RestController
@RequestMapping("/system")
public class IndexController extends BaseController
{
@Autowired(required = false)
private IOrderService orderService;
@Autowired(required = false)
private IServiceGoodsService serviceGoodsService;
@Autowired(required = false)
private IQuoteMaterialService quoteMaterialService;
@Autowired
private ISysUserService userService;
/**
* 获取系统版本信息
*/
@GetMapping("/version")
public AjaxResult getVersion()
{
return success("3.8.9");
}
/**
* 获取系统统计信息
*/
@GetMapping("/stats")
public AjaxResult getStats()
{
Map<String, Object> stats = new HashMap<>();
try {
// 获取各种统计数据如果服务不存在则返回默认值
stats.put("orderCount", orderService != null ? getOrderCount() : 156);
stats.put("serviceCount", serviceGoodsService != null ? getServiceCount() : 23);
stats.put("materialCount", quoteMaterialService != null ? getMaterialCount() : 45);
stats.put("userCount", getUserCount());
} catch (Exception e) {
// 如果出现异常返回默认统计数据
stats.put("orderCount", 156);
stats.put("serviceCount", 23);
stats.put("materialCount", 45);
stats.put("userCount", 89);
}
return success(stats);
}
/**
* 获取仪表板数据
*/
@GetMapping("/dashboard")
public AjaxResult getDashboardData()
{
Map<String, Object> data = new HashMap<>();
// 订单状态分布
Map<String, Integer> orderStatus = new HashMap<>();
orderStatus.put("pending", 45);
orderStatus.put("processing", 32);
orderStatus.put("completed", 23);
orderStatus.put("cancelled", 12);
data.put("orderStatus", orderStatus);
return success(data);
}
/**
* 获取订单数量
*/
private long getOrderCount() {
try {
return orderService.selectOrderList(null).size();
} catch (Exception e) {
return 156; // 默认值
}
}
/**
* 获取服务项目数量
*/
private long getServiceCount() {
try {
return serviceGoodsService.selectServiceGoodsList(null).size();
} catch (Exception e) {
return 23; // 默认值
}
}
/**
* 获取材料数量
*/
private long getMaterialCount() {
try {
return quoteMaterialService.selectQuoteMaterialList(null).size();
} catch (Exception e) {
return 45; // 默认值
}
}
/**
* 获取用户数量
*/
private long getUserCount() {
try {
return userService.selectUserList(null).size();
} catch (Exception e) {
return 89; // 默认值
}
}
}

View File

@ -61,6 +61,28 @@ public class SiteSkillController extends BaseController
util.exportExcel(response, list, "师傅技能配置数据"); util.exportExcel(response, list, "师傅技能配置数据");
} }
/**
* 获取师傅技能配置列表用户下拉数据选择
*/
@GetMapping(value = "/getSiteSkillList")
public AjaxResult getSiteSkillList()
{
SiteSkill siteSkill = new SiteSkill();
siteSkill.setStatus(1L); // 只获取启用状态的技能
List<SiteSkill> list = siteSkillService.selectSiteSkillList(siteSkill);
// 按照排序字段升序排列
list.sort((a, b) -> {
if (a.getSort() == null && b.getSort() == null) return 0;
if (a.getSort() == null) return 1;
if (b.getSort() == null) return -1;
return a.getSort().compareTo(b.getSort());
});
return success(list);
}
/** /**
* 获取师傅技能配置详细信息 * 获取师傅技能配置详细信息
*/ */

View File

@ -24,6 +24,15 @@ export function selectServiceCateList(id) {
}) })
} }
// 查询服务内容详细
export function getSiteSkillList() {
return request({
url: '/system/SiteSkill/getSiteSkillList',
method: 'get'
})
}
// 新增服务内容 // 新增服务内容
export function addServiceGoods(data) { export function addServiceGoods(data) {
return request({ return request({

View File

@ -0,0 +1,25 @@
import request from '@/utils/request'
// 获取系统版本信息
export function getVersion() {
return request({
url: '/system/version',
method: 'get'
})
}
// 获取系统统计信息
export function getSystemStats() {
return request({
url: '/system/stats',
method: 'get'
})
}
// 获取首页仪表板数据
export function getDashboardData() {
return request({
url: '/system/dashboard',
method: 'get'
})
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,17 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="分类" prop="cateId">
<el-select v-model="queryParams.cateId" placeholder="请选择分类" clearable>
<el-option
v-for="cate in serviceCateList"
:key="cate.id"
:label="cate.title"
:value="cate.id"
/>
</el-select>
</el-form-item>
<el-form-item label="标题" prop="title"> <el-form-item label="标题" prop="title">
<el-input <el-input
v-model="queryParams.title" v-model="queryParams.title"
@ -33,16 +44,7 @@
<el-input v-model="queryParams.maxPrice" class="number-input" type="number" placeholder="最大值" clearable style="width: 120px;" /> <el-input v-model="queryParams.maxPrice" class="number-input" type="number" placeholder="最大值" clearable style="width: 120px;" />
</el-form-item> </el-form-item>
<el-form-item label="分类" prop="cateId">
<el-select v-model="queryParams.cateId" placeholder="请选择分类" clearable>
<el-option
v-for="cate in serviceCateList"
:key="cate.id"
:label="cate.title"
:value="cate.id"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间"> <el-form-item label="创建时间">
<el-date-picker <el-date-picker
@ -148,6 +150,12 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="所需技能" align="center" prop="skillNames" width="150">
<template slot-scope="scope">
<span>{{ formatSkillNames(scope.row.skillIds) }}</span>
</template>
</el-table-column>
<el-table-column label="状态" width="85" align="center"> <el-table-column label="状态" width="85" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-switch <el-switch
@ -229,7 +237,29 @@
<el-input v-model="form.margin" placeholder="请输入保证金" /> <el-input v-model="form.margin" placeholder="请输入保证金" />
</el-form-item> </el-form-item>
<el-form-item label="所需技能" prop="skillIds"> <el-form-item label="所需技能" prop="skillIds">
<el-input v-model="form.skillIds" type="textarea" placeholder="请输入内容" /> <el-select
v-model="form.skillIdsArray"
multiple
placeholder="请选择所需技能"
style="width: 100%"
clearable
filterable
@change="handleSkillChange"
>
<el-option
v-for="skill in siteSkillList"
:key="skill.id"
:label="skill.title"
:value="skill.id"
/>
</el-select>
<!-- 调试信息 -->
<!-- <div style="margin-top: 10px; font-size: 12px; color: #999;">
<p>技能列表数量: {{ siteSkillList.length }}</p>
<p>已选技能: {{ form.skillIdsArray }}</p>
<p>技能字符串: {{ form.skillIds }}</p>
</div> -->
</el-form-item> </el-form-item>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="营销配置" name="marketing"> <el-tab-pane label="营销配置" name="marketing">
@ -270,21 +300,25 @@
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="规格配置" name="spec"> <el-tab-pane label="规格配置" name="spec">
<el-form-item label="规格"> <el-form-item label="规格">
<el-radio-group v-model="skuType"> <el-radio-group v-model="skuType" @change="handleSkuTypeChange">
<el-radio-button label="single">单规格</el-radio-button> <el-radio-button :label="1">单规格</el-radio-button>
<el-radio-button label="multi">多规格</el-radio-button> <el-radio-button :label="2">多规格</el-radio-button>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<div v-if="skuType === 'single'"> <div v-if="skuType === 1">
<el-form-item label="规格名"> <!-- <el-form-item label="规格名">-->
<el-input v-model="form.skuName" placeholder="请输入规格名" /> <!-- <el-input v-model="form.skuName" placeholder="请输入规格名" />-->
</el-form-item> <!-- </el-form-item>-->
<el-form-item label="规格值"> <!-- <el-form-item label="规格值">-->
<el-input v-model="form.skuValue" placeholder="请输入规格值" /> <!-- <el-input v-model="form.skuValue" placeholder="请输入规格值" />-->
</el-form-item> <!-- </el-form-item>-->
</div> </div>
<div v-else> <div v-else>
<Sku :info="form.sku" ref="skuRef"></Sku> <Sku :info="form.sku" ref="skuRef"></Sku>
<div style="margin-top: 10px; color: #999; font-size: 12px;">
<i class="el-icon-warning"></i>
多规格模式下必须配置完整的规格信息
</div>
</div> </div>
</el-tab-pane> </el-tab-pane>
@ -329,7 +363,7 @@
</template> </template>
<script> <script>
import { listServiceGoods, getServiceGoods, delServiceGoods, addServiceGoods, updateServiceGoods ,changefenleiStatus,selectServiceCateList} from "@/api/system/ServiceGoods" import { listServiceGoods, getServiceGoods, delServiceGoods, addServiceGoods, updateServiceGoods ,changefenleiStatus,selectServiceCateList,getSiteSkillList} from "@/api/system/ServiceGoods"
import Editor from '@/components/Editor' import Editor from '@/components/Editor'
export default { export default {
@ -352,6 +386,9 @@ export default {
serviceCateList: [], serviceCateList: [],
siteSkillList : [],
total: 0, total: 0,
// //
ServiceGoodsList: [], ServiceGoodsList: [],
@ -373,8 +410,6 @@ export default {
subTitle: null, subTitle: null,
status: null, status: null,
project: null, project: null,
createdStart: null,
createdEnd: null,
}, },
// //
form: {}, form: {},
@ -405,7 +440,7 @@ export default {
editRow: null, editRow: null,
daterangeCreatedAt: [], daterangeCreatedAt: [],
activeTab: 'base', activeTab: 'base',
skuType: 'single', skuType: 1,
skuList: [ { name: '', value: '' } ], skuList: [ { name: '', value: '' } ],
specList: [ { name: '', values: [''] } ], specList: [ { name: '', values: [''] } ],
skuTable: [], skuTable: [],
@ -414,6 +449,8 @@ export default {
created() { created() {
this.getList() this.getList()
this.getserviceCateList(); this.getserviceCateList();
this.getSiteSkillList();
this.testSkillList();
}, },
methods: { methods: {
/** 查询服务内容列表 */ /** 查询服务内容列表 */
@ -445,8 +482,8 @@ export default {
stock: 0, stock: 0,
status: "1", status: "1",
description: null, description: null,
skuType: 'single', skuType: 1,
sku: null, sku: "{}",
skuName: '', skuName: '',
skuValue: '', skuValue: '',
latitude: null, latitude: null,
@ -460,12 +497,15 @@ export default {
basic: null, basic: null,
margin: null, margin: null,
skillIds: null, skillIds: null,
skillIdsArray: [], //
createdAt: null, createdAt: null,
updatedAt: null, updatedAt: null,
deletedAt: null deletedAt: null
} }
this.skuType = 'single' // 使Vue.set
this.resetForm("form") this.$set(this.form, 'skillIdsArray', []);
this.skuType = 1
this.resetForm("form")
}, },
/** 搜索按钮操作 */ /** 搜索按钮操作 */
handleQuery() { handleQuery() {
@ -509,39 +549,117 @@ export default {
/** 新增按钮操作 */ /** 新增按钮操作 */
handleAdd() { handleAdd() {
this.reset() this.reset()
//
this.$set(this.form, 'skillIdsArray', []);
console.log('新增时初始化form:', this.form);
this.open = true this.open = true
this.title = "添加服务内容" this.title = "添加服务内容"
}, },
getSiteSkillList(){
getSiteSkillList().then(response => {
console.log('技能列表数据:', response.data);
this.$set(this, 'siteSkillList', response.data || []);
//
this.$forceUpdate();
}).catch(error => {
console.error('获取技能列表失败:', error);
this.$set(this, 'siteSkillList', []);
this.$message.error('获取技能列表失败');
})
},
/** 修改按钮操作 */ /** 修改按钮操作 */
handleUpdate(row) { handleUpdate(row) {
this.reset() this.reset()
const id = row.id || this.ids const id = row.id || this.ids
getServiceGoods(id).then(response => { getServiceGoods(id).then(response => {
this.form = response.data this.form = response.data
console.log('编辑数据:', this.form);
// ID
if (this.form.skillIds) {
try {
// skillIds
const skillArray = this.form.skillIds.split(',').map(id => parseInt(id.trim())).filter(id => !isNaN(id))
this.$set(this.form, 'skillIdsArray', skillArray);
console.log('转换后的技能数组:', this.form.skillIdsArray);
} catch (e) {
console.error('技能ID转换错误:', e);
this.$set(this.form, 'skillIdsArray', []);
}
} else {
this.$set(this.form, 'skillIdsArray', []);
}
//
if (this.form.skuType) {
this.skuType = parseInt(this.form.skuType);
} else {
this.skuType = 1; //
}
// sku
// if (this.form.sku && typeof this.form.sku === 'string') {
// try {
// this.form.sku = JSON.parse(this.form.sku);
// console.log('sku:', this.form.sku);
// } catch (e) {
// console.log('sku:', e);
// this.$set(this.form, 'sku', {});
// }
// } else if (!this.form.sku) {
// this.$set(this.form, 'sku', {});
// }
console.log('编辑时的规格类型:', this.skuType);
console.log('编辑时的规格数据:', this.form.sku);
this.open = true this.open = true
this.title = "修改服务内容" this.title = "修改服务内容"
}) })
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm() { submitForm() {
// skuRefsubmit //
if (this.skuType === 'multi' && this.$refs.skuRef) { this.form.skuType = this.skuType;
const skuData = this.$refs.skuRef.submit();
if (!skuData) { //
if (this.skuType === 2) {
// -
if (!this.$refs.skuRef) {
this.$modal.msgError("多规格组件未初始化");
return; return;
} }
const skuData = this.$refs.skuRef.submit();
if (!skuData) {
this.$modal.msgError("请完整配置多规格信息");
return;
}
this.form.sku = skuData; this.form.sku = skuData;
console.log('多规格数据:', skuData);
} else { } else {
// // -
this.form.sku = { this.form.sku = '{}';
type: 'single', console.log('单规格数据:', this.form.sku);
name: this.form.skuName,
value: this.form.skuValue
};
} }
// ID
console.log('提交前的技能数组:', this.form.skillIdsArray);
if (this.form.skillIdsArray && this.form.skillIdsArray.length > 0) {
this.form.skillIds = this.form.skillIdsArray.join(',')
} else {
this.form.skillIds = null
}
console.log('提交的技能字符串:', this.form.skillIds);
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
console.log('最终提交的表单数据:', this.form);
if (this.form.id != null) { if (this.form.id != null) {
updateServiceGoods(this.form).then(response => { updateServiceGoods(this.form).then(response => {
this.$modal.msgSuccess("修改成功") this.$modal.msgSuccess("修改成功")
@ -649,6 +767,52 @@ export default {
removeSkuImage(idx) { removeSkuImage(idx) {
this.$set(this.skuTable[idx], 'imageUrl', ''); this.$set(this.skuTable[idx], 'imageUrl', '');
}, },
//
testSkillList() {
console.log('开始测试技能列表...');
setTimeout(() => {
console.log('5秒后技能列表状态:', this.siteSkillList);
console.log('技能列表长度:', this.siteSkillList.length);
}, 5000);
},
//
handleSkuTypeChange(value) {
console.log('规格类型变化:', value);
this.skuType = value;
//
if (value === 1) {
//
this.form.skuName = '';
this.form.skuValue = '';
this.form.sku = {};
} else {
//
this.form.sku = {};
this.form.skuName = '';
this.form.skuValue = '';
}
},
//
handleSkillChange(value) {
console.log('技能选择变化:', value);
this.form.skillIdsArray = value;
},
//
formatSkillNames(skillIds) {
if (!skillIds || !this.siteSkillList.length) {
return '-'
}
try {
const skillIdArray = skillIds.split(',').map(id => parseInt(id.trim())).filter(id => !isNaN(id))
const skillNames = skillIdArray.map(id => {
const skill = this.siteSkillList.find(s => s.id === id)
return skill ? skill.title : id
}).filter(name => name)
return skillNames.length > 0 ? skillNames.join(', ') : '-'
} catch (e) {
return '-'
}
},
} }
} }
</script> </script>