This commit is contained in:
xyc 2025-09-30 09:37:26 +08:00
parent 4923dde629
commit da394abd70
15 changed files with 1377 additions and 983 deletions

View File

@ -88,6 +88,11 @@
console.error('获取用户信息失败', err)
})
}
// #ifdef APP-PLUS
plus.screen.lockOrientation('portrait-primary'); //
plus.navigator.setFullscreen(false);
// #endif
},
onShow: function() {
console.log('App Show')

View File

@ -241,6 +241,7 @@
* 接单
*/
openFile(orderId) {
console.log('执行');
this.$emit('getOrder', orderId);
},
/**

View File

@ -1,6 +1,12 @@
import App from './App'
import uView from "uview-ui";
import config from '@/config'
import config from '@/config';
import {
checkPermi,
checkRole
} from './utils/permission'
Vue.prototype.checkPermi = checkPermi
Vue.prototype.checkRole = checkRole
const baseUrl = config.baseUrl
Vue.prototype.$baseUrl = baseUrl;
const baseImageUrl = config.baseImageUrl

View File

@ -31,7 +31,7 @@
<image src="/static/images/j2.png" mode=""></image>
<view class="">业务管理</view>
</view>
<view class="jg_box" v-if="checkPermi(['repair_statistics_show'])">
<view class="jg_box" v-if="checkPermi(['repair_statistics_show'])" @click="goToPage(3)">
<image src="/static/images/j3.png" mode=""></image>
<view class="">数据统计</view>
</view>
@ -70,23 +70,24 @@
<view class="three1">
<view class="">
<view class="t_size">进厂数</view>
<view class="t_num">{{ bossNum.inCompanyNum }}</view>
<view class="t_num">{{ bossNum.newOrderNum }}</view>
</view>
<image src="/static/images/t1.png" mode=""></image>
</view>
<view class="three2">
<view class="" @click="viewOrder('wxz')">
<view class="">
<view class="t_size">维修中</view>
<view class="t_num">{{ bossNum.workingNum }}</view>
</view>
<image src="/static/images/t2.png" mode=""></image>
</view>
<view class="three3">
<view class="" @click="viewOrder('yjg')">
<view class="">
<view class="t_size">已竣工</view>
<view class="t_num">{{ bossNum.overNum }}</view>
</view>
<image src="/static/images/t3.png" mode=""></image>
<image src="/static/images/t3.png" mode="">
</image>
</view>
</view>
<view class="db_" style="margin: 30rpx auto; " v-if="checkRole(['repair_staff'])">
@ -423,6 +424,11 @@
url: '/pages-business/businessManage/businessManage' // 3. 使
});
break;
case 3: // 2.
uni.navigateTo({
url: '/pages-business/statistics/statistics' // 3. 使
});
break;
case 4:
uni.navigateTo({
url: '/pages-home/msg/message' // 3. 使

File diff suppressed because it is too large Load Diff

View File

@ -25,8 +25,8 @@
汇报内容
</view>
<!-- <u--textarea v-if="type != 'look'" v-model="report.reportContent" placeholder="请输入内容"></u--textarea> -->
<textarea auto-height v-model="report.reportContent" placeholder="请输入内容"></textarea>
<view class="x_"></view>
<textarea maxlength="-1" auto-height v-model="report.reportContent" placeholder="请输入内容"></textarea>
<!-- <view class="x_"></view> -->
<view class="d_b" @click="handleUpload" v-if="type != 'look'">
<view class="">附件</view>
<view class="lan_">上传附件

View File

@ -233,7 +233,7 @@
</picker>
</view>
</view>
<view style="display: flex;align-items: center">
<!-- <view style="display: flex;align-items: center">
<view class="infoItem" style="flex: 1" v-if="cusFromList && cusFromList.length>0">
<text class="label">客户来源</text>
<picker @change="cusFromChange" :value="cusFromIndex" :range="cusFromList"
@ -248,6 +248,12 @@
<view class="uni-input">{{ busiFromList[busiFromIndex].label}}</view>
</picker>
</view>
</view> -->
<view style="display: flex;align-items: center">
<text class="label">渠道/来源</text>
<uni-data-picker :localdata="busiAndCusList" v-model='busIAndCusValue'
popup-title="请选择渠道和来源" :map="{text:'name',value:'name'}"
@change="onBusiAndCuschange"></uni-data-picker>
</view>
<view style="display: flex;align-items: center">
<view class="infoItem" style="flex: 1">
@ -392,7 +398,8 @@
import config from "@/config";
import {
formatTimestamp,
formatTimestampCustom
formatTimestampCustom,
handleTree
} from "@/utils/utils";
import upload from "@/utils/upload";
import {
@ -424,6 +431,7 @@
cusFromIndex: 0,
busiFromList: [],
busiFromIndex: 0,
busiAndCusList: [],
partDisposals: [],
partDisposalIndex: 0,
formData: {
@ -479,6 +487,7 @@
ticketNo: '',
//
pageData: {},
busIAndCusValue: undefined
}
},
watch: {
@ -543,6 +552,7 @@
this.initDict("repair_type")
this.initDict("cus_data_from")
this.initDict("repair_part_disposal")
this.queryBusiAndCus()
},
onShow() {},
methods: {
@ -588,8 +598,6 @@
this.partDisposalIndex = newIndex;
this.formData.partDisposal = this.partDisposals[newIndex].value;
},
async initDict(dictCode) {
let dictArray = getStorageWithExpiry(dictCode);
console.log(dictArray, "partDisposals")
@ -652,6 +660,24 @@
})
}
},
/**
* 获取业务来源和渠道
*/
queryBusiAndCus() {
request({
url: `/admin-api/business/list`,
method: 'GET',
params: {
systemCode: 'repair'
}
}).then(res => {
this.busiAndCusList = handleTree(res.data, 'id', 'pid')
})
},
onBusiAndCuschange(e) {
this.formData.busiFrom = e.detail.value[0].value
this.formData.cusFrom = e.detail.value[1].value
},
buildRepairType() {
if (this.pageData.repairType) {
this.repairTypes.map((item, index) => {
@ -708,7 +734,8 @@
* 创建工单前上传图片
*/
submitUpload() {
if (this.userInfo === null || this.carList.length === 0 || this.selectedProj.length === 0) {
if (this.userInfo === null || this.carList.length === 0 || this.selectedProj.length === 0 || !this.formData
.busiFrom || !this.formData.cusFrom) {
uni.showToast({
title: '请完善信息',
icon: 'none'
@ -721,12 +748,12 @@
//
submit() {
let fileStr = this.fileList.map(item => item.url.replace(config.baseImageUrl, "")).join(",")
if (!this.formData.busiFrom) {
this.formData.busiFrom = this.busiFromList[this.busiFromIndex].value
}
if (!this.formData.cusFrom) {
this.formData.cusFrom = this.cusFromList[this.cusFromIndex].value
}
// if (!this.formData.busiFrom) {
// this.formData.busiFrom = this.busiFromList[this.busiFromIndex].value
// }
// if (!this.formData.cusFrom) {
// this.formData.cusFrom = this.cusFromList[this.cusFromIndex].value
// }
const data = {
userId: this.userInfo.id,
ticketNo: this.ticketNo,
@ -798,9 +825,20 @@
method: 'GET',
params: params
}).then(res => {
if (res.data.records.length > 0) {
if (res.data.records.length == 1) {
this.userInfo = res.data.records[0]
this.getCarList()
} else if (res.data.records.length != 0) {
uni.showActionSheet({
title: '选择客户',
itemList: res.data.records.map(m => m.cusName + m.phoneNumber),
success: ({
tapIndex
}) => {
this.userInfo = res.data.records[tapIndex]
this.getCarList()
}
})
}
})
} else {

View File

@ -55,43 +55,46 @@
class="carImage" mode="aspectFit"></image>
<view class="carHeaderRight">
<text class="carNumber">{{ ticketInfo.carNo }}</text>
<text class="carType">{{ ticketInfo.carBrandName+" " }} <text
<text class="carType">{{ ticketInfo.carBrandName+" " }} <span
v-if="ticketInfo.carInfo && ticketInfo.carInfo.carModel"> -
{{ticketInfo.carInfo.carModel}}</text></text>
{{ticketInfo.carInfo.carModel}}</span></text>
</view>
</view>
<view class="line"></view>
<view class="carBody">
<view style="display: flex;flex-direction: column;">
<view class="infoItem">
<view class="label">车主</view>
<view class="value">{{ ticketInfo.userName }}</view>
<view v-if="checkPermi(['repair:user:look'])">
<view class="infoItem">
<view class="label">车主</view>
<view class="value">{{ ticketInfo.userName }}</view>
</view>
<view class="infoItem">
<text class="label">联系方式</text>
<text class="value">{{ ticketInfo.userMobile }}</text>
</view>
<view class="infoItem">
<text class="label">客户来源</text>
<text class="value">{{ ticketInfo.customerInfo.dataFromText }}</text>
</view>
<view class="infoItem">
<text class="label">性别</text>
<text class="value">{{ ticketInfo.customerInfo.sex === '1' ? '女' : '男' }}</text>
</view>
<view class="infoItem" v-if="ticketInfo.handleName">
<text class="label">经办人</text>
<text class="value">{{ ticketInfo.handleName }}</text>
</view>
<view class="infoItem" v-if="ticketInfo.handleMobile">
<text class="label">经办人电话</text>
<text class="value">{{ ticketInfo.handleMobile }}</text>
</view>
<view class="infoItem">
<text class="label">业务来源</text>
<text class="value">{{ ticketInfo.busiFrom }}</text>
</view>
<view class="line"></view>
</view>
<view class="infoItem">
<text class="label">联系方式</text>
<text class="value">{{ ticketInfo.userMobile }}</text>
</view>
<view class="infoItem">
<text class="label">客户来源</text>
<text class="value">{{ ticketInfo.customerInfo.dataFromText }}</text>
</view>
<view class="infoItem">
<text class="label">性别</text>
<text class="value">{{ ticketInfo.customerInfo.sex === '1' ? '女' : '男' }}</text>
</view>
<view class="infoItem" v-if="ticketInfo.handleName">
<text class="label">经办人</text>
<text class="value">{{ ticketInfo.handleName }}</text>
</view>
<view class="infoItem" v-if="ticketInfo.handleMobile">
<text class="label">经办人电话</text>
<text class="value">{{ ticketInfo.handleMobile }}</text>
</view>
<view class="infoItem">
<text class="label">业务来源</text>
<text class="value">{{ ticketInfo.busiFrom }}</text>
</view>
<view class="line"></view>
<view class="infoItem">
<view class="label">车架号</view>
<view class="value">{{ ticketInfo.carVin }}</view>
@ -102,48 +105,62 @@
</view>
<view class="infoItem">
<view class="label">车辆注册日期</view>
<view class="value">{{ ticketInfo.carRegisterDate }}</view>
<view class="value">{{ formatDate(ticketInfo.carInfo.carRegisterDate) }}</view>
</view>
<view class="infoItem">
<view class="label">车龄()</view>
<view class="value">{{ ticketInfo.carInfo.carYear }}</view>
</view>
<view class="infoItem">
<view class="label">年检到期时间</view>
<view class="value">{{ ticketInfo.nextInspectionDate}}</view>
<view class="label">当前表显里程</view>
<view class="value">{{ ticketInfo.carInfo.mileageTraveled}}</view>
</view>
<view class="infoItem">
<view class="label">下次年检时间</view>
<view class="value">{{ formatDate(ticketInfo.carInfo.nextInspectionDate)}}</view>
</view>
<view class="infoItem">
<view class="label">保险到期时间</view>
<view class="value">{{ ticketInfo.insuranceExpiryDate}}</view>
<view class="value">{{ formatDate(ticketInfo.carInfo.insuranceExpiryDate)}}</view>
</view>
<view class="infoItem">
<!-- <view class="infoItem">
<view class="label">承保险种</view>
<view class="value">{{ ticketInfo.insuranceType}}</view>
</view>
<view class="infoItem">
<view class="label">上年保费</view>
<view class="value">{{ ticketInfo.jiaoqiang}} {{ ticketInfo.shangye}}</view>
</view> -->
<view class="infoItem">
<view class="label">下次保养里程</view>
<view class="value">{{ ticketInfo.carInfo.nextMaintenanceMileage}}</view>
</view>
<view class="infoItem">
<view class="label">最近保养日期</view>
<view class="value">{{ ticketInfo.maintenanceDate}}</view>
</view>
<view class="infoItem">
<view class="label">表显里程</view>
<view class="value">{{ ticketInfo.mileageTraveled}}</view>
</view>
<view class="infoItem">
<view class="label">最近保养公里数</view>
<view class="value">{{ ticketInfo.maintenanceMileage}}</view>
</view>
</view>
<view class="projList">
<view class="projImg" v-if="carImgList.length>0">
<image v-for="(img, imgIndex) in carImgList"
@click="prviewImage(carImgList,imgIndex)" :key="imgIndex"
:src="imgUrlPrex + img.image" class="projImgItem"></image>
<view class="infoItem" style="display: block;">
<view class="label">档案资料</view>
<view class="value">
<view class="projList">
<view class="projImg" v-if="carImgList.length>0">
<image v-for="(img, imgIndex) in carImgList"
@click="prviewImage(carImgList,imgIndex)" :key="imgIndex"
:src="img.image" class="projImgItem"></image>
</view>
</view>
</view>
</view>
<view class="infoItem" v-if="checkPermi(['tickets:car:edit'])">
<view class="label" style="color: rgb(41, 121, 255);" @click="showCarPopup">点击编辑车辆信息
</view>
</view>
</view>
</view>
</view>
</view>
@ -456,6 +473,32 @@
</view>
</view>
</uni-popup>
<uni-popup ref="carPopup" type="center" border-radius="10px 10px 10px 10px" background-color="#fff">
<view class="car-popup-out">
<uni-forms ref="baseForm" :modelValue="carFormData">
<uni-forms-item label="下次年检日期" required>
<picker mode="date" :value="carFormData.nextInspectionDate" :start="startDate" :end="endDate"
@change="bindnextInspectionDateChange">
<view class="uni-input">
{{ carFormData.nextInspectionDate ? carFormData.nextInspectionDate : '选择日期' }}
</view>
</picker>
</uni-forms-item>
<uni-forms-item label="下次保养里程" required>
<uni-easyinput v-model="carFormData.nextMaintenanceMileage" placeholder="请输入" />
</uni-forms-item>
<uni-forms-item label="保险到期时间" required>
<picker mode="date" :value="carFormData.insuranceExpiryDate" :start="startDate" :end="endDate"
@change="bindInsuranceExpiryDateChange">
<view class="uni-input">
{{ carFormData.insuranceExpiryDate ? carFormData.insuranceExpiryDate : '选择日期' }}
</view>
</picker>
</uni-forms-item>
</uni-forms>
<button @click="submitCarForm">确定</button>
</view>
</uni-popup>
<view>
<u-modal :show="show" :title="title" confirmText="电话" cancelText="短信" showCancelButton @cancel="message"
@confirm="phone " closeOnClickOverlay @close="show = false">
@ -487,7 +530,10 @@
setStorageWithExpiry,
getStorageWithExpiry
} from '@/utils/auth'
import config from '@/config'
import config from '@/config';
import {
fixScreen
} from '@/utils/fixScreen.js';
export default {
components: {
VNavigationBar,
@ -526,10 +572,29 @@
repairItemId: "",
itemName: "",
},
//
carFormData: {
nextInspectionDate: undefined,
insuranceExpiryDate: undefined,
nextMaintenanceMileage: undefined,
mileageTraveled: undefined,
},
//
canOpenCus: false,
//
canSeeMoney: false,
listStyles: {
//
border: false,
// 线
dividline: false,
// 线
borderStyle: {
width: 1,
color: 'blue',
radius: 2
}
},
//:working-|done_half-|done-
nowChooseOperate: "",
carInfo: {},
@ -555,7 +620,8 @@
activeProjTabKey: 0,
activePartTabKey: 0,
processList: [{}, {}],
carImgList: []
carImgList: [],
cararchivesPhotos: []
};
},
watch: {
@ -587,8 +653,20 @@
this.refreshData(false)
}
},
onShow() {
//
fixScreen();
},
computed: {
startDate() {
return this.getDate('start');
},
endDate() {
return this.getDate('end');
}
},
methods: {
formatDate,
chooseProjTab(index) {
this.activeProjTabKey = index
},
@ -641,6 +719,67 @@
}
})
},
/**
* 打开编辑车辆弹窗
*/
showCarPopup() {
this.carFormData = this.ticketInfo.carInfo
if (this.carFormData.insuranceExpiryDate) {
this.carFormData.insuranceExpiryDate = formatDate(this.carFormData.insuranceExpiryDate)
}
if (this.carFormData.nextInspectionDate) {
this.carFormData.nextInspectionDate = formatDate(this.carFormData.nextInspectionDate)
}
this.$refs.carPopup.open()
},
/**
* @param {Object} type获取时间
*/
getDate(type) {
const date = new Date();
let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();
if (type === 'start') {
year = year - 10;
} else if (type === 'end') {
year = year + 10;
}
month = month > 9 ? month : '0' + month;
day = day > 9 ? day : '0' + day;
return `${year}-${month}-${day}`;
},
/**
* 修改下次年检时间
* @param {Object} e
*/
bindnextInspectionDateChange(e) {
console.log('e', e);
this.carFormData.nextInspectionDate = e.detail.value
},
bindInsuranceExpiryDateChange(e) {
this.carFormData.insuranceExpiryDate = e.detail.value
},
submitCarForm() {
// nextInspectionDate yyyy-MM-dd
if (this.carFormData.nextInspectionDate) {
this.carFormData.nextInspectionDate = new Date(this.carFormData.nextInspectionDate).getTime()
}
// nextInspectionDate yyyy-MM-dd
if (this.carFormData.insuranceExpiryDate) {
this.carFormData.insuranceExpiryDate = new Date(this.carFormData.insuranceExpiryDate).getTime()
}
request({
url: `/admin-api/base/carMain/update`,
method: 'PUT',
data: this.carFormData
})
this.$refs.carPopup.close()
},
/**
* 监听输入框
*/
@ -669,7 +808,11 @@
prviewImage(imgList, index) {
let urls = []
imgList.forEach(i => {
urls.push(this.imgUrlPrex + i.image)
if (!i.image.includes("http")) {
urls.push(this.imgUrlPrex + i.image)
} else {
urls.push(i.image)
}
})
uni.previewImage({
urls: urls,
@ -782,6 +925,7 @@
}
},
afterRead(file) {
console.log('文件', file);
uni.showLoading({
title: '正在上传中...',
mask: true
@ -1012,8 +1156,11 @@
}
if (this.loginUser.roleCodes.includes("repair_staff")) {
//
const has02 = this.ticketInfo.items.some(item => item.itemType === '02');
console.log('has02', has02);
this.content.push({
text: '配件申请',
// text: '',
text: !has02 ? '是否申请配件' : '是否增加配件',
active: false,
code: "apply"
})
@ -1275,6 +1422,7 @@
}).then((res) => {
let resultObj = res.data
resultObj.statusStr = getOrderStatusText(res.data.ticketsStatus, res.data.isHandover)
//
if (null != resultObj.carInfo.carRegisterDate) {
resultObj.carRegisterDate = formatDate(resultObj.carInfo.carRegisterDate)
@ -1379,8 +1527,17 @@
}
if (resultObj.carInfo.carLicenseImg) {
resultObj.carInfo.carLicenseImg.split(",").map((item) => {
let url = item.includes("http") ? item : this.imgUrlPrex + item;
this.carImgList.push({
image: item
image: url
});
});
}
if (resultObj.carInfo.archivesPhoto) {
resultObj.carInfo.archivesPhoto.split(",").map((item) => {
this.cararchivesPhotos.push({
url: this.$baseImageUrl + item
})
})
}
@ -1457,7 +1614,7 @@
url: '/pages-order/reviewList/reviewList?formData=' + encodeURIComponent(JSON.stringify(
formData))
})
}
},
}
}
</script>
@ -2309,4 +2466,8 @@
background-color: #efefef;
}
}
.car-popup-out {
padding: 30rpx 40rpx;
}
</style>

View File

@ -33,9 +33,9 @@
</view>
</view>
</view>
<view style="text-align: center" v-if="repairList.length==0">
<image class="" src="@/static/images/nothing.png" ></image>
</view>
<view style="text-align: center" v-if="repairList.length==0">
<image class="" src="@/static/images/nothing.png"></image>
</view>
</scroll-view>
</view>
</view>
@ -46,34 +46,38 @@
<view class="submit" v-if="!ticketId" @click="addTwi">确认添加</view>
<view class="submit" v-if="ticketId" @click="openUpload">拍照上传</view>
</view>
<!-- 普通弹窗---打开已选配件 -->
<uni-popup ref="waresPopup" background-color="#fff" :mask-click="false">
<view class="popup-content" style="padding: 15px;">
<view class="dl-avatar-box" style="height: 400px;overflow-y: scroll">
<view v-for="(item, index) in selectedRepairList" :key="index" class="listItem">
<view class="repairName">{{ item.name }}</view>
<view class="repairBottom">
<text class="repairDesc">单位
<text class="repairUnit">{{ item.unitText }}</text>
</text>
<view class="repairBtns">
<u-icon name="minus-circle-fill" size="24" @click="delNum(item)"></u-icon>
<text class="repairNum">{{ item.num }}</text>
<u-icon color="#0174F6" name="plus-circle-fill" size="24"
@click="addNum(item)"></u-icon>
</view>
</view>
</view>
<view style="text-align: center" v-if="selectedRepairList.length==0">
<image class="" src="@/static/images/nothing.png" ></image>
</view>
</view>
<button type="primary" @click="closeWaresPopup">关闭</button>
</view>
</uni-popup>
<!-- 普通弹窗---打开已选配件 -->
<uni-popup ref="waresPopup" background-color="#fff" :mask-click="false">
<view class="popup-content" style="padding: 15px;">
<view class="dl-avatar-box" style="height: 400px;overflow-y: scroll">
<view v-for="(item, index) in selectedRepairList" :key="index" class="listItem">
<view class="repairName">{{ item.name }}</view>
<view class="repairBottom">
<text class="repairDesc">单位
<text class="repairUnit">{{ item.unitText }}</text>
</text>
<view class="repairBtns">
<u-icon name="minus-circle-fill" size="24" @click="delNum(item)"></u-icon>
<text class="repairNum">{{ item.num }}</text>
<u-icon color="#0174F6" name="plus-circle-fill" size="24"
@click="addNum(item)"></u-icon>
</view>
</view>
</view>
<view style="text-align: center" v-if="selectedRepairList.length==0">
<image class="" src="@/static/images/nothing.png"></image>
</view>
</view>
<button type="primary" @click="closeWaresPopup">关闭</button>
</view>
</uni-popup>
<!-- 普通弹窗---拍照上传 -->
<uni-popup ref="popup" background-color="#fff">
<view class="popup-content" style="padding: 15px;">
<view class="dl-avatar-box">
<text>备注</text>
<uni-easyinput v-model="remark" placeholder="请输入备注"></uni-easyinput>
</view>
<view class="dl-avatar-box">
<uni-file-picker :value="fileList" :sizeType="sizeType" @select="afterRead" @delete="deleteFile"
limit="9" title="请上传配件申请单照片最多选择9张图片"></uni-file-picker>
@ -96,7 +100,9 @@
} from "@/utils/auth";
import upload from "@/utils/upload";
import config from "@/config";
import {data} from "uview-ui/libs/mixin/mixin";
import {
data
} from "uview-ui/libs/mixin/mixin";
export default {
components: {
VNavigationBar
@ -124,8 +130,10 @@
isTriggered: false,
userInfo: null,
fileList: [],
//
remark: undefined,
sizeType: ['compressed'],
twId: null
twId: null
};
},
computed: {
@ -138,74 +146,74 @@
onLoad(data) {
this.userInfo = getUserInfo()
this.ticketId = data.ticketId
this.twId = data.twId
this.ifHouse = data.ifHouse
this.twId = data.twId
this.ifHouse = data.ifHouse
},
onShow() {
this.init()
},
methods: {
closeWaresPopup(){
this.$refs.waresPopup.close()
//
this.chooseTab("")
},
/**
* 打开已选择的配件弹出框
*/
openChoosed(){
if(this.selectedRepairList.length==0){
return
}
this.$refs.waresPopup.open("bottom")
},
addTwi(){
if (!this.selectedRepairList || this.selectedRepairList.length === 0){
uni.showToast({
title: '请选择配件!',
icon: 'none'
})
return
}
let dataObj = {
id: this.twId
}
dataObj.items = [...this.selectedRepairList.map(item => {
return {
id: item.id,
count: item.num,
name: item.name
}
})]
if(this.ifHouse){
//
dataObj.ifHouseAdd = true
}else{
//
dataObj.ifHouseAdd = false
}
request({
url: "/admin-api/repair/twi/addTwi",
method: 'post',
data: dataObj
}).then(res => {
uni.showToast({
title: '提交成功!',
icon: 'none'
})
setTimeout(() => {
uni.navigateBack()
}, 700)
})
},
closeWaresPopup() {
this.$refs.waresPopup.close()
//
this.chooseTab("")
},
/**
* 打开已选择的配件弹出框
*/
openChoosed() {
if (this.selectedRepairList.length == 0) {
return
}
this.$refs.waresPopup.open("bottom")
},
addTwi() {
if (!this.selectedRepairList || this.selectedRepairList.length === 0) {
uni.showToast({
title: '请选择配件!',
icon: 'none'
})
return
}
let dataObj = {
id: this.twId
}
dataObj.items = [...this.selectedRepairList.map(item => {
return {
id: item.id,
count: item.num,
name: item.name
}
})]
if (this.ifHouse) {
//
dataObj.ifHouseAdd = true
} else {
//
dataObj.ifHouseAdd = false
}
request({
url: "/admin-api/repair/twi/addTwi",
method: 'post',
data: dataObj
}).then(res => {
uni.showToast({
title: '提交成功!',
icon: 'none'
})
setTimeout(() => {
uni.navigateBack()
}, 700)
})
},
openUpload() {
this.$refs.popup.open("bottom")
},
afterRead(file) {
uni.showLoading({
title: '正在上传中...',
mask:true
});
uni.showLoading({
title: '正在上传中...',
mask: true
});
for (let i = 0; i < file.tempFilePaths.length; i++) {
upload({
url: '/admin-api/infra/file/upload',
@ -214,9 +222,9 @@
this.fileList.push({
url: config.baseImageUrl + res.data
})
if(i==file.tempFilePaths.length-1){
uni.hideLoading()
}
if (i == file.tempFilePaths.length - 1) {
uni.hideLoading()
}
console.log(this.fileList)
})
}
@ -291,7 +299,7 @@
* 分页加载所有配件
*/
pageList() {
let that = this
let that = this
let paramsObj = {
pageNo: this.pageNo,
pageSize: this.pageSize
@ -324,19 +332,19 @@
}
return m
})
console.log(thisDataList,"thisDataList")
console.log(thisDataList, "thisDataList")
// concat n
if (that.pageNo != 1) {
that.repairList = that.repairList.concat(thisDataList)
that.repairList = that.repairList.concat(thisDataList)
} else {
that.repairList = thisDataList
that.repairList = thisDataList
}
//
that.total = res.data.total
that.isTriggered = false
}else{
that.isTriggered = false
}
that.total = res.data.total
that.isTriggered = false
} else {
that.isTriggered = false
}
})
},
addNum(repair) {
@ -390,34 +398,37 @@
})
dataObj.items = itemList
}
if (this.fileList.length > 0){
dataObj.images = this.fileList.map(item => {
console.log(item)
return item.path.replace(config.baseImageUrl, '')
}).join(",")
}
if (this.fileList.length > 0) {
dataObj.images = this.fileList.map(item => {
console.log(item)
return item.path.replace(config.baseImageUrl, '')
}).join(",")
}
if (this.remark) {
dataObj.remark = this.remark
}
}
request({
url: '/admin-api/repair/tw/update',
method: 'POST',
data:dataObj
}).then((res) => {
console.log(res)
if (res.code == 200) {
uni.showToast({
title: '提交成功!',
icon: 'none'
})
setTimeout(() => {
uni.navigateBack()
}, 700)
}else{
uni.showToast({
title: '提交失败!',
icon: 'none'
})
}
})
request({
url: '/admin-api/repair/tw/update',
method: 'POST',
data: dataObj
}).then((res) => {
console.log(res)
if (res.code == 200) {
uni.showToast({
title: '提交成功!',
icon: 'none'
})
setTimeout(() => {
uni.navigateBack()
}, 700)
} else {
uni.showToast({
title: '提交失败!',
icon: 'none'
})
}
})
// if(this.selectedRepairList.length>0){
// let itemList = []
// this.selectedRepairList.map((item)=>{
@ -608,39 +619,40 @@
color: #FFFFFF;
}
}
.listItem {
padding: 30rpx 0;
border-bottom: 2rpx solid #DDDDDD;
&:last-child {
border-bottom: none;
}
.listItem {
padding: 30rpx 0;
border-bottom: 2rpx solid #DDDDDD;
.repairName {
font-size: 32rpx;
color: #333333;
margin-bottom: 20rpx;
}
&:last-child {
border-bottom: none;
}
.repairBottom {
display: flex;
align-items: center;
justify-content: space-between;
}
.repairName {
font-size: 32rpx;
color: #333333;
margin-bottom: 20rpx;
}
.repairDesc {
font-size: 28rpx;
color: #858BA0;
}
.repairBottom {
display: flex;
align-items: center;
justify-content: space-between;
}
.repairUnit {
color: #333333;
}
.repairDesc {
font-size: 28rpx;
color: #858BA0;
}
.repairBtns {
display: flex;
align-items: center;
column-gap: 10rpx;
}
}
</style>
.repairUnit {
color: #333333;
}
.repairBtns {
display: flex;
align-items: center;
column-gap: 10rpx;
}
}
</style>

View File

@ -81,6 +81,13 @@
"style": {
"navigationBarTitleText": ""
}
},
{
"path" : "pages/white/white",
"style" :
{
"navigationBarTitleText" : ""
}
}
],
"subPackages": [{
@ -345,12 +352,11 @@
{
"root": "pages-detail",
"pages": [{
"path": "detail/detail",
"style": {
"navigationBarTitleText": "详情页"
}
"path": "detail/detail",
"style": {
"navigationBarTitleText": "详情页"
}
]
}]
},
{
"root": "pages-business",
@ -368,7 +374,7 @@
}
},
{
"path" : "white/white",
"path" : "statistics/statistics",
"style" :
{
"navigationBarTitleText" : ""

View File

@ -1,5 +1,7 @@
## 2.0.102024-06-07
- 优化 uni-app x 中size 属性的类型
## 2.0.122025-08-26
- 优化 uni-app x 下 size 类型问题
## 2.0.112025-08-18
- 修复 图标点击事件返回
## 2.0.92024-01-12
fix: 修复图标大小默认值错误的问题
## 2.0.82023-12-14

View File

@ -1,91 +1,91 @@
<template>
<text class="uni-icons" :style="styleObj">
<slot>{{unicode}}</slot>
</text>
<text class="uni-icons" :style="styleObj">
<slot>{{unicode}}</slot>
</text>
</template>
<script>
import { fontData, IconsDataItem } from './uniicons_file'
import { fontData, IconsDataItem } from './uniicons_file'
/**
* Icons 图标
* @description 用于展示 icon 图标
* @tutorial https://ext.dcloud.net.cn/plugin?id=28
* @property {Number,String} size 图标大小
* @property {String} type 图标图案,参考示例
* @property {String} color 图标颜色
* @property {String} customPrefix 自定义图标
* @event {Function} click 点击 Icon 触发事件
*/
export default {
name: "uni-icons",
props: {
type: {
type: String,
default: ''
},
color: {
type: String,
default: '#333333'
},
size: {
/**
* Icons 图标
* @description 用于展示 icon 图标
* @tutorial https://ext.dcloud.net.cn/plugin?id=28
* @property {Number} size 图标大小
* @property {String} type 图标图案,参考示例
* @property {String} color 图标颜色
* @property {String} customPrefix 自定义图标
* @event {Function} click 点击 Icon 触发事件
*/
export default {
name: "uni-icons",
props: {
type: {
type: String,
default: ''
},
color: {
type: String,
default: '#333333'
},
size: {
type: [Number, String],
default: 16
},
fontFamily: {
type: String,
default: ''
}
},
data() {
return {};
},
computed: {
unicode() : string {
let codes = fontData.find((item : IconsDataItem) : boolean => { return item.font_class == this.type })
if (codes !== null) {
return codes.unicode
}
return ''
},
iconSize() : string {
const size = this.size
if (typeof size == 'string') {
const reg = /^[0-9]*$/g
return reg.test(size as string) ? '' + size + 'px' : '' + size;
// return '' + this.size
}
return this.getFontSize(size as number)
},
styleObj() : UTSJSONObject {
if (this.fontFamily !== '') {
return { color: this.color, fontSize: this.iconSize, fontFamily: this.fontFamily }
}
return { color: this.color, fontSize: this.iconSize }
}
},
created() { },
methods: {
/**
* 字体大小
*/
getFontSize(size : number) : string {
return size + 'px';
},
},
}
},
fontFamily: {
type: String,
default: ''
}
},
data() {
return {};
},
computed: {
unicode() : string {
let codes = fontData.find((item : IconsDataItem) : boolean => { return item.font_class == this.type })
if (codes !== null) {
return codes.unicode
}
return ''
},
iconSize() : string {
const size = this.size
if (typeof size == 'string') {
const reg = /^[0-9]*$/g
return reg.test(size as string) ? '' + size + 'px' : '' + size;
// return '' + this.size
}
return this.getFontSize(size as number)
},
styleObj() : UTSJSONObject {
if (this.fontFamily !== '') {
return { color: this.color, fontSize: this.iconSize, fontFamily: this.fontFamily }
}
return { color: this.color, fontSize: this.iconSize }
}
},
created() { },
methods: {
/**
* 字体大小
*/
getFontSize(size : number) : string {
return size + 'px';
},
},
}
</script>
<style scoped>
@font-face {
font-family: UniIconsFontFamily;
src: url('./uniicons.ttf');
}
@font-face {
font-family: UniIconsFontFamily;
src: url('./uniicons.ttf');
}
.uni-icons {
font-family: UniIconsFontFamily;
font-size: 18px;
font-style: normal;
color: #333;
}
.uni-icons {
font-family: UniIconsFontFamily;
font-size: 18px;
font-style: normal;
color: #333;
}
</style>

View File

@ -85,8 +85,8 @@
}
},
methods: {
_onClick() {
this.$emit('click')
_onClick(e) {
this.$emit('click', e)
}
}
}
@ -107,4 +107,4 @@
text-decoration: none;
text-align: center;
}
</style>
</style>

View File

@ -1,7 +1,7 @@
{
"id": "uni-icons",
"displayName": "uni-icons 图标",
"version": "2.0.10",
"version": "2.0.12",
"description": "图标组件,用于展示移动端常见的图标,可自定义颜色、大小。",
"keywords": [
"uni-ui",
@ -11,12 +11,14 @@
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": "^3.2.14"
"HBuilderX": "^3.2.14",
"uni-app": "^4.08",
"uni-app-x": "^4.61"
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
@ -34,56 +36,76 @@
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
"type": "component-vue"
"type": "component-vue",
"darkmode": "x",
"i18n": "x",
"widescreen": "x"
},
"uni_modules": {
"dependencies": ["uni-scss"],
"dependencies": [
"uni-scss"
],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y",
"alipay": "n"
"tcb": "x",
"aliyun": "x",
"alipay": "x"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y",
"app-uvue": "y"
"uni-app": {
"vue": {
"vue2": "√",
"vue3": "√"
},
"web": {
"safari": "√",
"chrome": "√"
},
"app": {
"vue": "√",
"nvue": "-",
"android": {
"extVersion": "",
"minVersion": "29"
},
"ios": "√",
"harmony": "√"
},
"mp": {
"weixin": "√",
"alipay": "√",
"toutiao": "√",
"baidu": "√",
"kuaishou": "-",
"jd": "-",
"harmony": "-",
"qq": "√",
"lark": "-"
},
"quickapp": {
"huawei": "√",
"union": "√"
}
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y",
"钉钉": "y",
"快手": "y",
"飞书": "y",
"京东": "y"
},
"快应用": {
"华为": "y",
"联盟": "y"
},
"Vue": {
"vue2": "y",
"vue3": "y"
"uni-app-x": {
"web": {
"safari": "√",
"chrome": "√"
},
"app": {
"android": {
"extVersion": "",
"minVersion": "29"
},
"ios": "√",
"harmony": "√"
},
"mp": {
"weixin": "√"
}
}
}
}
}
}
}

View File

@ -333,6 +333,9 @@ export function builderOrder(order) {
}
export function formatDate(timestamp) {
if (!timestamp) {
return ''
}
// 将时间戳转换为Date对象
const date = new Date(timestamp);
// 获取年月日时分秒
@ -503,4 +506,96 @@ export function formatDateCus(date) {
const m = (date.getMonth() + 1).toString().padStart(2, '0')
const d = date.getDate().toString().padStart(2, '0')
return `${y}-${m}-${d}`
}
/**
* 将扁平数组转换为树形结构并支持按 sort 字段排序
* @param {Array} data 源数据
* @param {String} id 节点ID字段名默认为 'id'
* @param {String} parentId 父节点ID字段名默认为 'parentId'
* @param {String} children 子节点字段名默认为 'children'
* @param {Number|String} rootId 根节点ID值默认为最小的parentId或0
* @param {String} sortKey 排序字段名默认为 'sort'
* @returns {Array} 树形结构数据
*/
export function handleTree(data, id, parentId, children, rootId, sortKey) {
// 参数默认值处理
id = id || 'id';
parentId = parentId || 'parentId';
children = children || 'children';
sortKey = sortKey || 'sort';
// 自动计算根节点ID取最小的parentId若无则用0
rootId = rootId || Math.min(...data.map(item => item[parentId])) || 0;
// 深拷贝源数据以避免污染原数组
const cloneData = JSON.parse(JSON.stringify(data));
// 先对所有数据进行排序(确保父节点在前)
cloneData.sort((a, b) => {
const aSort = a[sortKey] ?? 0; // 使用空值合并运算符处理undefined
const bSort = b[sortKey] ?? 0;
return aSort - bSort; // 升序排序
});
// 构建哈希表加速查找
const nodeMap = {};
cloneData.forEach(item => {
nodeMap[item[id]] = item;
item[children] = []; // 初始化children数组
});
// 构建树形结构
const tree = [];
cloneData.forEach(item => {
if (item[parentId] === rootId) {
// 根节点直接加入结果
tree.push(item);
} else {
// 非根节点找到父节点并插入
const parent = nodeMap[item[parentId]];
parent?.[children]?.push(item);
}
});
// 递归排序所有子节点
const sortChildren = (nodes) => {
nodes.forEach(node => {
if (node[children]?.length) {
node[children].sort((a, b) => {
const aSort = a[sortKey] ?? 0;
const bSort = b[sortKey] ?? 0;
return aSort - bSort;
});
sortChildren(node[children]);
}
});
};
sortChildren(tree);
return tree.length ? tree : data; // 空树时返回原数据
}
/**
* 将树形结构数据转成 uniapp multiSelector picker 可用的二维数组
* @param {Array} tree 树形结构数据
* @param {String} labelKey 节点显示字段默认为 'name'
* @param {String} childrenKey 子节点字段默认为 'children'
* @returns {Array} picker二维数组例如 [[一级], [二级], [三级]...]
*/
export function toPickerData(tree, labelKey = 'name', childrenKey = 'children') {
const result = []
function buildColumns(nodes, level = 0) {
if (!nodes || !nodes.length) return
// 当前层级的所有 name
result[level] = nodes.map(n => n[labelKey])
// 默认取第一个子节点继续递归
if (nodes[0][childrenKey] && nodes[0][childrenKey].length) {
buildColumns(nodes[0][childrenKey], level + 1)
}
}
buildColumns(tree, 0)
return result
}