bonus-material-app/src/pages/repair/equipAssessment/num-operate.vue

1100 lines
33 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- 数量出库 -->
<view class="page-container">
<uni-row :gutter="24" class="search-form">
<uni-col :span="6">
<view class="search" @click="saveNumAll">
定损完成
</view>
</uni-col>
</uni-row>
<view class="table-list-item">
<uni-row :gutter="24">
<uni-col :span="6">物资名称</uni-col>
<uni-col :span="18"
><view class="cont">{{ queryParams.typeName }}</view>
</uni-col>
</uni-row>
<uni-row :gutter="24">
<uni-col :span="6">物资类型</uni-col>
<uni-col :span="18"
><view class="cont">{{ queryParams.type }}</view>
</uni-col>
</uni-row>
<uni-row :gutter="24">
<uni-col :span="6">退料数量</uni-col>
<uni-col :span="18"
><view class="cont">{{
queryParams.typeRepairNum
}}</view>
</uni-col>
</uni-row>
</view>
<scroll-view scroll-y style="padding-bottom: 20rpx">
<!-- 定损 -->
<view class="table-list-item">
<h2 style="padding: 4rpx 0; font-weight: bold">定损</h2>
<uni-forms ref="baseForm" label-align="right">
<div v-for="(item, index) in partItems" :key="index">
<uni-forms-item label="定损数量">
<uni-easyinput
placeholder="请填写定损数量"
v-model="item.repairNum"
type="number"
:clearable="false"
@input="repairCheckNum1(index)"
/>
</uni-forms-item>
<uni-forms-item label="配件类型">
<treeSelect style="width: 100%;height: 90rpx;" ref="treeSelectRef"
:options="partTreeData" @change="partTreeChange" :index="index" @clear="clearPart" :defaultProps="defaultProps" ></treeSelect>
</uni-forms-item>
<uni-forms-item label="配件数量">
<uni-easyinput
placeholder="配件数量"
v-model="item.partNum"
type="number"
:clearable="false"
@input="partCheckNum(item)"
/>
</uni-forms-item>
<uni-forms-item label="配件单价">
<div style="width: 100%; display: flex">
<uni-easyinput
v-model="item.partPrice"
placeholder="请输入配件单价"
type="number"
:clearable="false"
@input="costCheckNum(item)"
/>
<div class="operation-btns">
<span class="add" @click="addPart">增加</span>
<span class="remove" @click="delPart(index)">删除</span>
</div>
</div>
</uni-forms-item>
</div>
</uni-forms>
</view>
<!-- -->
<view class="table-list-item">
<!-- 维修人员 -->
<h2 style="padding: 4rpx 0; font-weight: bold">定损信息</h2>
<uni-forms ref="baseForm" label-align="right">
<uni-forms-item label="维修人员">
<uni-data-select :localdata="repairPersonData" v-model="repairPerson" :clear="false" placeholder="请选择维修人员" />
</uni-forms-item>
<uni-forms-item label="费用合计">
<uni-easyinput placeholder="请填写费用合计" maxlength="50" v-model="costAll" disabled/>
</uni-forms-item>
<uni-forms-item label="备注">
<uni-easyinput placeholder="请填写备注" maxlength="50" v-model="remark"/>
</uni-forms-item>
<!-- <uni-forms-item label="附件">
<div class="upload" @click="uploadImg" v-if="imgBeseUrl==''">+</div>
<div class="upload" @click="uploadImg" v-else>
<image :src="imgBeseUrl" style="width: 160rpx;height: 160rpx;" mode=""></image>
</div>
</uni-forms-item> -->
<uni-forms-item label="附件">
<div class="upload-container">
<div class="upload" @click="uploadImg2" v-if="imgList2.length < 3">+</div>
<div class="image-preview" v-for="(img, index) in imgList2" :key="index">
<image :src="img.url" mode="aspectFill"></image>
<view class="delete-btn" @click.stop="deleteImage2(index)">×</view>
<PreviewImg :imgUrl="img.url" />
</div>
</div>
</uni-forms-item>
</uni-forms>
</view>
</scroll-view>
<!-- 返厂维修 -->
<!-- <view class="table-list-item">
<h2 style="padding: 4rpx 0; font-weight: bold">返厂维修</h2>
<uni-forms ref="baseForm" label-align="right">
<uni-forms-item label="维修数量">
<uni-easyinput
placeholder="请输入维修数量"
v-model="formMiddle.repairNum"
type="number"
:clearable="false"
@input="repairCheckNum2"
/>
</uni-forms-item>
<uni-forms-item label="物资厂家">
<uni-data-select
:localdata="partsMillList"
v-model="formMiddle.supplierId"
placeholder="请选择物资厂家"
/>
</uni-forms-item>
<div v-for="(item, index) in partItemsMiddle" :key="index">
<uni-forms-item label="配件名称">
<uni-easyinput placeholder="配件名称" v-model="item.partName" />
</uni-forms-item>
<uni-forms-item label="是否收费">
<uni-data-select
:localdata="isChargeList"
v-model="item.partType"
placeholder="请选择是否收费"
/>
</uni-forms-item>
<uni-forms-item label="配件数量">
<uni-easyinput
v-model="item.partNum"
placeholder="请输入配件数量"
type="number"
:clearable="false"
@input="partCheckNum(item)"
/>
</uni-forms-item>
<uni-forms-item label="金额">
<div style="width: 100%; display: flex">
<uni-easyinput
v-model="item.partPrice"
placeholder="请输入金额"
type="number"
:clearable="false"
@input="costCheckNum(item)"
/>
<div class="operation-btns">
<span class="add" @click="addMidPart">+</span>
<span class="remove" @click="delMidPart(index)">-</span>
</div>
</div>
</uni-forms-item>
</div>
</uni-forms>
</view> -->
<!-- 维修报废 -->
<!-- <view class="table-list-item">
<h2 style="padding: 4rpx 0; font-weight: bold">维修报废</h2>
<uni-forms ref="baseForm" label-align="right">
<uni-forms-item label="报废数量">
<uni-easyinput
placeholder="请填写报废数量"
v-model="formRight.scrapNum"
type="number"
:clearable="false"
@input="repairCheckNum3"
/>
</uni-forms-item>
<uni-forms-item label="报废原因">
<uni-easyinput
placeholder="请填写报废原因" maxlength="50"
v-model="formRight.scrapReason"
/>
</uni-forms-item>
<uni-forms-item label="损坏原因">
<uni-data-select v-model="formRight.scrapType"
:localdata="damageReasonList"
placeholder="请选择损坏原因"
/>
</uni-forms-item>
<uni-forms-item label="附件">
<div class="upload-container">
<div class="upload" @click="uploadImg2" v-if="imgList2.length < 3">+</div>
<div class="image-preview" v-for="(img, index) in imgList2" :key="index">
<image :src="img.url" mode="aspectFill"></image>
<view class="delete-btn" @click.stop="deleteImage2(index)">×</view>
</div>
</div>
</uni-forms-item>
</uni-forms>
</view>
</scroll-view> -->
</view>
</template>
<script setup>
import { computed, ref } from 'vue'
import { partTypeTreeList, getSupplierList, getRepairerListApi, saveRepairRow } from '@/services/repair/repair.js'
import {
saveLossAssessmentRow
} from '@/services/repair/equipAssessment.js'
import { baseURL } from '@/utils/http'
import treeSelect from '../tree-select/tselectTwo2.vue';
import { onLoad } from '@dcloudio/uni-app'
import { decryptWithSM4, encryptWithSM4, hashWithSM3AndSalt } from '@/utils/sm'
import PreviewImg from '@/components/PreviewImg/index.vue'
// const query = defineProps() // 获取上级页面传递的路由参数
// const queryParams = JSON.parse(query.queryParams)
// 浮点数运算辅助函数
const floatUtils = {
// 加法,避免精度问题
add: (...nums) => {
return parseFloat(nums.reduce((sum, num) => {
const value = Number(num || 0);
if (isNaN(value)) return sum;
return parseFloat((sum + value).toFixed(6));
}, 0).toFixed(6));
},
// 减法,避免精度问题
subtract: (a, b) => {
const aVal = Number(a || 0);
const bVal = Number(b || 0);
if (isNaN(aVal) || isNaN(bVal)) return 0;
return parseFloat((aVal - bVal).toFixed(6));
},
// 比较是否相等(考虑浮点数误差)
isEqual: (a, b) => {
const aVal = Number(a);
const bVal = Number(b);
if (isNaN(aVal) || isNaN(bVal)) return false;
return Math.abs(aVal - bVal) < 1e-10;
},
// 格式化数字,避免极小值
format: (num) => {
const value = Number(num);
if (isNaN(value)) return 0;
const formatted = parseFloat(value.toFixed(6));
return Math.abs(formatted) < 1e-10 ? 0 : formatted;
},
// 乘法,避免精度问题
multiply: (a, b) => {
const aVal = Number(a || 0);
const bVal = Number(b || 0);
if (isNaN(aVal) || isNaN(bVal)) return 0;
return parseFloat((aVal * bVal).toFixed(6));
},
// 检查数值是否为空或0
isEmptyOrZero: (num) => {
const value = Number(num);
if (isNaN(value)) return true;
return Math.abs(value) < 1e-10;
},
// 检查数值是否为空
isEmpty: (num) => {
// 检查是否为 null 或 undefined
if (num === null || num === undefined) {
return true;
}
// 检查是否为空字符串
if (typeof num === 'string' && num.trim() === '') {
return true;
}
// 转换为数字
const value = Number(num);
// 检查是否为 NaN
if (isNaN(value)) {
return true;
}
// 检查是否为 0根据需求0 可能视为空或非空)
// 这里返回 false因为 0 是一个有效的数字值
return false;
},
};
const queryParams = ref({})
const rowData = ref({})
onLoad((options) => {
queryParams.value = JSON.parse(options.queryParams)
rowData.value = JSON.parse(options.queryParams)
})
const { userInfo } = JSON.parse(uni.getStorageSync('member'))
//获取维修人员
const repairPersonData = ref([])
const repairPerson = ref("")
const getRepairerListData = async () => {
const res = await getRepairerListApi({})
console.log(res)
repairPersonData.value = res.data.map((item) => {
let obj = {
value: item.userId,
text: item.repairer,
}
return obj
})
// 如果 userInfo.userId 在repairPersonData.value 数组中说明是维修人员,则默认选中, 否则默认选中第一个
if (
repairPersonData.value &&
repairPersonData.value.findIndex((v) => v.value === userInfo.userId) > -1
) {
repairPerson.value = userInfo.userId
} else {
repairPerson.value = repairPersonData.value[0].value
}
}
getRepairerListData()
const remark = ref("") //备注
const costAll = ref("") //费用合计
const imgBeseUrl = ref("") //图片展示
const bmFileInfos = ref([])//图片数组
//配件树
const partTreeData = ref([])
const defaultProps = ref({
id: 'id',
children: 'children',
label: 'label'
})
const getPartTreeData = async () => {
const res = await partTypeTreeList({})
console.log("yyyyyyyyy",res)
partTreeData.value = res.data;
}
getPartTreeData()
// 配件清除
const clearPart = (index) =>{
partItems.value[index].partId=""
}
const treeSelectRef = ref([])
//配件选中
const partTreeChange = (val, index) => {
console.log(val);
const isHas = partItems.value.findIndex(v => v.partId === val.id);
if (isHas > -1) { // 不可选择相同的配件
console.log(isHas);
treeSelectRef.value[index].clearInput();
partItems.value[index].partId = "";
partItems.value[index].partNum = 0;
partItems.value[index].partPrice = 0;
} else {
partItems.value[index].partId = val.id;
partItems.value[index].partNum = 0;
partItems.value[index].partPrice = val.buyPrice
}
};
//内部维修
const formLeft = ref({
repairNum: 0,
})
const partItems = ref([{ partNum: '', partType: 0, partId: '',partPrice:'',repairNum:0}])
const addPart = () => {
partItems.value.push({ partNum: '', partType: 0, partId: '', partPrice:'',repairNum:0})
calculateCostAll();
}
const delPart = (index) => {
if (partItems.value.length > 1) {
partItems.value.splice(index, 1)
calculateCostAll();
}
}
const partIds = ref([])
const imgBeseUrl2 = ref("") //图片展示
const imgList2 = ref([]) // 图片列表,用于回显
const fileData = ref({fileList:[]})
//上传
const uploadImg2 = () => {
uni.showActionSheet({
itemList: ['拍照', '从相册选择'],
success: (res) => {
if (res.tapIndex === 0) {
getCameraFj()
} else if (res.tapIndex === 1) {
// 从相册选择
getPhotoFj()
}
},
fail: (err) => {
console.error('操作菜单选择失败:', err)
},
})
}
const generateRandomString = (length) => {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
// 附件拍照
const getCameraFj = () => {
navigator.camera.getPicture(onCameraSuccessFj, onCameraErrorFj, {
quality: 50,
destinationType: window.Camera.DestinationType.DATA_URL,
sourceType: window.Camera.PictureSourceType.CAMERA,
})
}
// 附件从相册选择
const getPhotoFj = () => {
navigator.camera.getPicture(onCameraSuccessFj, onCameraErrorFj, {
quality: 50,
destinationType: window.Camera.DestinationType.DATA_URL,
sourceType: window.Camera.PictureSourceType.SAVEDPHOTOALBUM,
})
}
const onCameraErrorFj = (message) => {
console.log(message)
}
const onCameraSuccessFj = (file) => {
uploadSignUrlFj(file)
}
const uploadSignUrlFj = (file) => {
const base64Data = file
uni.request({
url: '/file/uploadBase64',
method: 'POST',
data: {
base64File:base64Data,
fileName: `${generateRandomString(10)}_${Date.now()}.png`,
fileType: 'image/png'
},
success: (uploadRes) => {
if(!uploadRes.data.code){
uploadRes = JSON.parse(decryptWithSM4(uploadRes.data))
}else{
uploadRes = uploadRes.data
}
if (uploadRes.code && uploadRes.code == 200) {
imgList2.value.push({
url: uploadRes.data.url, // Show local path first
serverUrl: uploadRes.data.url // Store server URL
})
// bmFileInfos.value.push({
// name: uploadRes.data.name,
// url: uploadRes.data.url,
// taskType: '10'
// })
uni.showToast({ title: '上传成功', icon: 'none' })
} else {
uni.showToast({ title: '上传失败', icon: 'none' })
}
},
fail: (err) => {
console.error('上传失败', err)
uni.showToast({ title: '上传失败', icon: 'none' })
}
})
}
//删除图片
const deleteImage2 = (index) => {
imgList2.value.splice(index, 1)
fileData.value.fileList.splice(index, 1)
}
// 验证配件数据
const validateParts = () => {
let isValid = true;
let errorMessage = "";
for (let i = 0; i < partItems.value.length; i++) {
const item = partItems.value[i];
// 检查配件单价不为空时配件数量不能为空或0
const partPrice = floatUtils.format(item.partPrice);
const partNum = floatUtils.format(item.partNum);
// 如果配件单价有值不为0
if (!floatUtils.isEmptyOrZero(partPrice)) {
// 配件数量为空或0
if (floatUtils.isEmptyOrZero(partNum)) {
isValid = false;
errorMessage = `${i + 1}行配件单价已填写,请填写配件数量!`;
break;
}
}
// 如果配件数量有值不为0
if (!floatUtils.isEmptyOrZero(partNum)) {
// 配件单价为空或0
if (floatUtils.isEmpty(partPrice)) {
isValid = false;
errorMessage = `${i + 1}行配件数量已填写,请填写配件单价!`;
break;
}
}
// // 检查配件类型是否选择(如果配件数量或单价有值)
// if ((!floatUtils.isEmptyOrZero(partNum) || !floatUtils.isEmptyOrZero(partPrice)) && !item.partId) {
// isValid = false;
// errorMessage = `第${i + 1}行请选择配件类型!`;
// break;
// }
}
if (!isValid) {
uni.showToast({ title: errorMessage, icon: 'none' });
}
return isValid;
}
//数量维修保存
const saveNumAll = async () => {
console.log(rowData.value)
if(repairPerson.value==""){
uni.showToast({ title: '请先选择维修人员!', icon: 'none' })
}
// else if(partItems.value.some(item => Number(item.repairNum) === 0)){
// uni.showToast({ title: '存在定损数量为 0 的项,请检查!', icon: 'none' })
// }
// else if(partItems.value.findIndex(v => v.partId == '')>-1){
// uni.showToast({ title: '请选择配件!', icon: 'none' })
// }else if(partItems.value.some(item => Number(item.partNum) === 0)){
// uni.showToast({ title: '存在配件数量为 0 的项,请检查!', icon: 'none' })
// }
else {
// 验证配件数据
if (!validateParts()) {
return;
}
uni.showLoading({
title: '提交中...',
mask: true
})
try {
//维修人员
rowData.value.repairDeviceList[0].repairList=[
{
repairer:repairPerson.value,
remark:remark.value,
fileList:fileData.value.fileList
}
]
//提交
for (let i = 0; i < partItems.value.length; i++) {
rowData.value.repairDeviceList[0].numberInRepairPartList.push({
partType: partItems.value[i].partType,
partId: partItems.value[i].partId,
partNum: partItems.value[i].partNum,
partPrice: partItems.value[i].partPrice,
dsNum:partItems.value[i].repairNum,
})
}
console.log("yyyyyyyyyy",rowData.value)
const response = await saveLossAssessmentRow(rowData.value.repairDeviceList)
// 隐藏Loading
uni.hideLoading()
if (response.code == 200) {
uni.showToast({ title: '定损成功', icon: 'none' })
setTimeout(() => {
uni.navigateBack({
delta: 1, // 返回到已存在的页面
})
}, 1000)
} else {
uni.showToast({
title: response.msg || '提交失败',
icon: 'none'
})
}
// saveLossAssessmentRow(rowData.value.repairDeviceList).then(async (response) => {
// console.log("yxxxxxyyyy",response)
// if (response.code === 200) {
// uni.showToast({ title: '定损成功', icon: 'none' })
// setTimeout(() => {
// uni.navigateBack({
// delta: 1, // 返回到已存在的页面
// })
// }, 1000)
// }
// })
} catch (error) {
// 隐藏Loading
uni.hideLoading()
console.error('定损提交失败:', error)
uni.showToast({
title: '网络错误,请重试',
icon: 'none'
})
}
}
}
// 计算可使用的最大定损数量
// const maxRepairNum = computed(() => {
// return queryParams.value.typeRepairNum - queryParams.value.typeRepairedNum - queryParams.value.typeScrapNum;
// });
const maxRepairNum = computed(() => {
const total = floatUtils.subtract(
queryParams.value.typeRepairNum,
floatUtils.add(queryParams.value.typeRepairedNum, queryParams.value.typeScrapNum)
);
return floatUtils.format(total);
});
// 计算当前所有定损数量之和
// const currentTotalRepairNum = computed(() => {
// let total = 0;
// partItems.value.forEach(item => {
// total += Number(item.repairNum) || 0;
// });
// return total;
// });
const currentTotalRepairNum = computed(() => {
return partItems.value.reduce((sum, item) => {
return floatUtils.add(sum, item.repairNum || 0);
}, 0);
});
// 数量框change事件
const repairCheckNum1 = (index) => {
setTimeout(() => {
const item = partItems.value[index];
// 使用辅助函数格式化输入值
const originalValue = item.repairNum;
const cleanedValue = Number(String(originalValue).replace(/[^\d.]/g, ''));
const formattedValue = floatUtils.format(cleanedValue);
item.repairNum = formattedValue < 0 ? 0 : formattedValue;
// 计算当前所有项的总和
const currentTotal = partItems.value.reduce((sum, it, idx) => {
const value = idx === index ? item.repairNum : (it.repairNum || 0);
return floatUtils.add(sum, value);
}, 0);
const maxNum = maxRepairNum.value;
if (currentTotal > maxNum && !floatUtils.isEqual(currentTotal, maxNum)) {
uni.showToast({
title: '已达到当前物资最大定损数量!',
icon: 'none',
});
// 计算超出的部分
const excess = floatUtils.subtract(currentTotal, maxNum);
// 从当前项中减去超出的部分
const newValue = floatUtils.format(
floatUtils.subtract(item.repairNum, excess)
);
// 确保新值不会变成负数
item.repairNum = Math.max(0, newValue);
}
// 重新计算费用合计
calculateCostAll();
// item.repairNum = Number(String(item.repairNum).replace(/[^\d.]/g, ''));
// if (Number(item.repairNum) < 0) {
// item.repairNum = 0;
// }
//
// if (currentTotalRepairNum.value > maxRepairNum.value) {
// uni.showToast({
// title: '已达到当前物资最大定损数量!',
// icon: 'none',
// });
// // 计算需要减少的数量
// const excess = currentTotalRepairNum.value - maxRepairNum.value;
// // 从当前修改的项中减去超出的部分
// item.repairNum = Math.max(0, item.repairNum - excess);
// }
//
// // 重新计算费用合计
// calculateCostAll();
}, 500);
};
// 配件框change事件
const partCheckNum = (item) => {
setTimeout(() => {
item.partNum = Number(String(item.partNum).replace(/[^\d.]/g, ''))
// 重新计算费用合计
calculateCostAll();
}, 500)
}
// 金额框change事件
const costCheckNum = (item) => {
setTimeout(() => {
item.partPrice = Number(String(item.partPrice).replace(/[^\d.]/g, ''))
// 重新计算费用合计
calculateCostAll();
}, 500)
}
// 计算费用合计
const calculateCostAll = () => {
let totalCost = 0;
partItems.value.forEach(item => {
totalCost += item.partNum * item.partPrice;
});
costAll.value = totalCost.toFixed(2); // 保留两位小数
}
</script>
<style lang="scss" scoped>
.upload-container {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.upload {
width: 160rpx;
height: 160rpx;
background-color: #f7f8fa;
border: 2rpx dashed #d9d9d9;
border-radius: 12rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 48rpx;
color: #bfbfbf;
transition: all 0.3s ease;
}
.image-preview {
width: 160rpx;
height: 160rpx;
position: relative;
border-radius: 12rpx;
overflow: hidden;
}
.image-preview image {
width: 100%;
height: 100%;
}
.delete-btn {
position: absolute;
top: 0;
right: 0;
width: 40rpx;
height: 40rpx;
background-color: rgba(0, 0, 0, 0.5);
color: white;
display: flex;
justify-content: center;
align-items: center;
border-bottom-left-radius: 12rpx;
font-size: 32rpx;
line-height: 32rpx;
}
.uploading-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
display: flex;
justify-content: center;
align-items: center;
color: white;
font-size: 24rpx;
}
.page-container {
display: flex;
height: 100vh;
padding: 24rpx;
flex-direction: column;
background-color: #f7f8fa;
// 基本信息卡片
.table-list-item {
background-color: #fff;
border-radius: 20rpx;
padding: 24rpx;
margin-bottom: 24rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
// 标题样式
h2 {
font-size: 32rpx;
font-weight: 600;
color: #262626;
margin-bottom: 24rpx;
position: relative;
padding-left: 24rpx;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 6rpx;
height: 28rpx;
background: #3784fb;
border-radius: 6rpx;
}
}
// 信息行
.uni-row {
padding: 16rpx 0;
font-size: 28rpx;
border-bottom: 2rpx solid #f5f5f5;
&:last-child {
border-bottom: none;
}
.uni-col-6 {
color: #8c8c8c;
}
.cont {
color: #262626;
}
}
// 表单样式
:deep(.uni-forms-item) {
padding: 24rpx 0;
margin-bottom: 0;
border-bottom: 2rpx solid #f5f5f5;
&:last-child {
border-bottom: none;
}
.uni-forms-item__label {
color: #8c8c8c;
}
.uni-easyinput__content {
background-color: #f7f8fa;
border: 2rpx solid #e8e8e8;
border-radius: 12rpx;
height: 88rpx;
padding: 0 24rpx;
transition: all 0.3s ease;
&:focus-within {
border-color: #3784fb;
box-shadow: 0 0 0 2rpx rgba(55, 132, 251, 0.1);
}
}
// 下拉选择框样式
.uni-data-select {
.uni-select {
border: 2rpx solid #e8e8e8;
border-radius: 12rpx;
height: 88rpx;
padding: 0 24rpx;
transition: all 0.3s ease;
&:focus-within {
border-color: #3784fb;
box-shadow: 0 0 0 2rpx rgba(55, 132, 251, 0.1);
}
}
}
}
}
// 操作按钮组
.search-form {
margin-bottom: 24rpx;
background: #fff !important;
border-radius: 20rpx !important;
padding: 24rpx !important;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
.search {
height: 88rpx;
line-height: 88rpx;
text-align: center;
color: #fff;
font-size: 28rpx;
font-weight: 600;
border-radius: 12rpx;
transition: all 0.3s ease;
background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%);
box-shadow: 0 6rpx 20rpx rgba(46, 204, 113, 0.2);
&:active {
transform: scale(0.98);
opacity: 0.9;
}
}
}
// 加减按钮
.operation-btns {
display: flex;
align-items: center;
gap: 16rpx;
margin-left: 24rpx;
span {
width: 90rpx;
height: 48rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8rpx;
font-size: 32rpx;
transition: all 0.3s ease;
&:active {
transform: scale(0.95);
opacity: 0.8;
}
// 添加按钮
&.add {
color: #2ecc71;
background-color: rgba(46, 204, 113, 0.1);
}
// 删除按钮
&.remove {
color: #e74c3c;
background-color: rgba(231, 76, 60, 0.1);
}
}
}
}
// 加载提示文字
.loading-text {
text-align: center;
font-size: 28rpx;
color: #666;
padding: 20rpx 0;
}
.outbound-btn {
width: 70%;
margin: 25rpx auto;
height: 65rpx;
line-height: 65rpx;
text-align: center;
background-color: #19be6b;
border-radius: 12rpx;
color: #fff;
}
// 上传区域样式
.upload {
width: 160rpx;
height: 160rpx;
background-color: #f7f8fa;
border: 2rpx dashed #d9d9d9;
border-radius: 12rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 48rpx;
color: #bfbfbf;
transition: all 0.3s ease;
&:active {
background-color: #f0f0f0;
border-color: #3784fb;
}
image {
width: 100%;
height: 100%;
border-radius: 12rpx;
object-fit: cover;
}
}
.my-confirm-notice {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 998;
/* 这里防止当用户长按屏幕,出现的黑色背景色块,以及 iPhone 横平时字体的缩放问题 */
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
display: flex;
align-items: center;
}
.confirm-content-wrap1 {
position: relative;
left: 0;
right: 0;
// width: 60%;
width: 90%;
height: 247px;
margin: 0 auto;
background-color: #FFFFFF;
border-radius: 10px;
z-index: 999;
user-select: none;
}
.content_margin {
padding: 15px 0px 15px 0px;
}
.flex_row_center {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.label_text {
font-size: 28rpx;
color: #555555;
}
.inputStyle {
border: #bababa 0.5px solid;
width: 169px;
height: 34px;
box-sizing: border-box;
font-size: 13px;
padding: 3px 2px;
}
.top_level {
position: fixed;
z-index: 100;
width: 90%;
}
.ly_tree_style {
border: #F5F5F5 1px solid;
width: 169px;
}
</style>