|
|
|
|
@ -4,16 +4,48 @@
|
|
|
|
|
|
|
|
|
|
<view class="container">
|
|
|
|
|
<u-form :model="form" ref="uForm" :label-width="200" :error-type="['message', 'border-bottom']">
|
|
|
|
|
<u-form-item label="日期" prop="date" label-position="left">
|
|
|
|
|
<u-input v-model="form.date" disabled type="text"></u-input>
|
|
|
|
|
</u-form-item>
|
|
|
|
|
<u-form-item label="客户" prop="customer_name" label-position="left">
|
|
|
|
|
<u-input v-model="form.customer_name" disabled type="text"></u-input>
|
|
|
|
|
</u-form-item>
|
|
|
|
|
<u-form-item label="护理员" required prop="nurse_name" label-position="left">
|
|
|
|
|
<u-input v-model="form.nurse_name" type="text" placeholder="请输入护理员"></u-input>
|
|
|
|
|
<u-form-item label="日期" prop="date" label-position="left">
|
|
|
|
|
<u-input v-model="form.date" disabled type="text"></u-input>
|
|
|
|
|
</u-form-item>
|
|
|
|
|
<u-form-item :required="item.type==='checkbox'?false:true" v-for="(item,index) in form.forms" :label="item.ask" :prop="index" label-position="top">
|
|
|
|
|
<u-form-item label="客户" prop="customer_name" label-position="left">
|
|
|
|
|
<u-input v-model="form.customer_name" disabled type="text"></u-input>
|
|
|
|
|
</u-form-item>
|
|
|
|
|
<!-- 联系方式 -->
|
|
|
|
|
<u-form-item label="联系方式" label-position="left">
|
|
|
|
|
<u-input v-model="editCustomer.phone" type="text" placeholder="请输入联系方式"></u-input>
|
|
|
|
|
</u-form-item>
|
|
|
|
|
<!-- 状态 单选组 0正常 1死亡 -->
|
|
|
|
|
<u-form-item label="状态" label-position="left">
|
|
|
|
|
<u-radio-group v-model="editCustomer.is_dead" active-color="#1479FF">
|
|
|
|
|
<u-radio :name="0">正常</u-radio>
|
|
|
|
|
<u-radio :name="1" style="margin-left: 24rpx;">死亡</u-radio>
|
|
|
|
|
</u-radio-group>
|
|
|
|
|
</u-form-item>
|
|
|
|
|
<!-- 默认地址 显示 default=1 的一条,仅显示 address;提供获取位置按钮更新/新增 -->
|
|
|
|
|
<u-form-item label="默认地址" label-position="left">
|
|
|
|
|
<view>
|
|
|
|
|
<view v-if="defaultCustomerAddress">
|
|
|
|
|
<view style="word-break: break-all;">{{ defaultCustomerAddress.address || '' }}</view>
|
|
|
|
|
<view style="margin-top: 12rpx; display: flex; align-items: center;">
|
|
|
|
|
<u-button size="mini" type="primary" @click="updateDefaultCustomerAddress">获取位置</u-button>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view v-else>
|
|
|
|
|
<view style="display: flex; align-items: center;">
|
|
|
|
|
<u-button size="mini" type="primary" @click="createDefaultCustomerAddress">获取位置</u-button>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</u-form-item>
|
|
|
|
|
|
|
|
|
|
<view style="display: flex; align-items: center;margin-top: 20rpx;justify-content: center;">
|
|
|
|
|
<u-button size="medium" type="primary" style="margin-left: 12rpx;" @click="saveCustomerInfo">更新用户信息</u-button>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<u-form-item label="护理员" prop="nurse_name" label-position="left">
|
|
|
|
|
<u-input v-model="form.nurse_name" type="text" placeholder="请输入护理员"></u-input>
|
|
|
|
|
</u-form-item>
|
|
|
|
|
<u-form-item :required="item.type==='checkbox'?false:true" v-for="(item,index) in form.forms" :key="index" :label="item.ask" :prop="index" label-position="top">
|
|
|
|
|
<u-checkbox-group v-if="item.type==='checkbox'" ref="serve" @change="e => checkboxChange(e)">
|
|
|
|
|
<u-checkbox v-for="(item1, index1) in item.options" :key="index1" :name="item1.name"
|
|
|
|
|
v-model="item1.checked">
|
|
|
|
|
@ -27,12 +59,12 @@
|
|
|
|
|
</u-form-item>
|
|
|
|
|
<u-form-item label="对护理员哪些方面要求改进" prop="tip" label-position="top">
|
|
|
|
|
<u-input v-model="form.tip" type="textarea"></u-input>
|
|
|
|
|
</u-form-item>
|
|
|
|
|
<u-form-item label="对护理员有哪些方面肯定" prop="sure" label-position="top">
|
|
|
|
|
<u-input v-model="form.sure" type="textarea"></u-input>
|
|
|
|
|
</u-form-item>
|
|
|
|
|
<u-form-item label="备注" prop="remark" label-position="top">
|
|
|
|
|
<u-input v-model="form.remark" type="textarea"></u-input>
|
|
|
|
|
</u-form-item>
|
|
|
|
|
<u-form-item label="对护理员有哪些方面肯定" prop="sure" label-position="top">
|
|
|
|
|
<u-input v-model="form.sure" type="textarea"></u-input>
|
|
|
|
|
</u-form-item>
|
|
|
|
|
<u-form-item label="备注" prop="remark" label-position="top">
|
|
|
|
|
<u-input v-model="form.remark" type="textarea"></u-input>
|
|
|
|
|
</u-form-item>
|
|
|
|
|
<u-form-item label="回访图片">
|
|
|
|
|
<u-upload ref="uUpload" :custom-btn="true" :action="action" :file-list="fileList"
|
|
|
|
|
@ -81,7 +113,7 @@
|
|
|
|
|
import QQMapWX from '@/libs/qqmap-wx-jssdk.js'
|
|
|
|
|
import {
|
|
|
|
|
ROOTPATH
|
|
|
|
|
} from "@/common/config"
|
|
|
|
|
} from "@/common/config"
|
|
|
|
|
import moment from "@/libs/moment.min";
|
|
|
|
|
export default {
|
|
|
|
|
data() {
|
|
|
|
|
@ -91,8 +123,14 @@
|
|
|
|
|
id: "",
|
|
|
|
|
type: "add",
|
|
|
|
|
detail: {},
|
|
|
|
|
customerInfo: {},
|
|
|
|
|
editCustomer: {
|
|
|
|
|
phone: '',
|
|
|
|
|
is_dead: 0,
|
|
|
|
|
customer_address: []
|
|
|
|
|
},
|
|
|
|
|
form: {
|
|
|
|
|
customer_id: "",
|
|
|
|
|
customer_id: "",
|
|
|
|
|
customer_name:'',
|
|
|
|
|
date: '',
|
|
|
|
|
nurse_name: '',
|
|
|
|
|
@ -123,7 +161,7 @@
|
|
|
|
|
score: ''
|
|
|
|
|
}, {
|
|
|
|
|
ask: '告知客户可以提供的服务项目及本次上门服务的时长(5分)',
|
|
|
|
|
max: 3,
|
|
|
|
|
max: 5,
|
|
|
|
|
min: 0,
|
|
|
|
|
score: ''
|
|
|
|
|
}, {
|
|
|
|
|
@ -142,8 +180,8 @@
|
|
|
|
|
min: 0,
|
|
|
|
|
score: ''
|
|
|
|
|
}, {
|
|
|
|
|
ask: '工单服务项目能保质保量完成(质量标准参考入户检查表)(50分)',
|
|
|
|
|
max: 50,
|
|
|
|
|
ask: '工单服务项目能保质保量完成(质量标准参考入户检查表)(30分)',
|
|
|
|
|
max: 30,
|
|
|
|
|
min: 0,
|
|
|
|
|
score: ''
|
|
|
|
|
}, {
|
|
|
|
|
@ -224,15 +262,15 @@
|
|
|
|
|
address: "",
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
rules: {
|
|
|
|
|
nurse_name: [
|
|
|
|
|
{
|
|
|
|
|
required: true,
|
|
|
|
|
type: 'string',
|
|
|
|
|
message: '请填写护理员姓名',
|
|
|
|
|
trigger: ['change','blur']
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
rules: {
|
|
|
|
|
// nurse_name: [
|
|
|
|
|
// {
|
|
|
|
|
// required: true,
|
|
|
|
|
// type: 'string',
|
|
|
|
|
// message: '请填写护理员姓名',
|
|
|
|
|
// trigger: ['change','blur']
|
|
|
|
|
// }
|
|
|
|
|
// ],
|
|
|
|
|
sign_image_id: [{
|
|
|
|
|
validator: (rule, value, callback) => {
|
|
|
|
|
if (this.vuex_sign_image || value) {
|
|
|
|
|
@ -263,23 +301,91 @@
|
|
|
|
|
deep: true, // 深度监听
|
|
|
|
|
immediate: true // 初始化时立即执行一次
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onLoad(option) {
|
|
|
|
|
this.form.customer_id = option.customer_id;
|
|
|
|
|
this.id = option.id;
|
|
|
|
|
this.type = option.id ? 'edit' : 'add';
|
|
|
|
|
if (this.type === 'edit') {
|
|
|
|
|
this.getDetail()
|
|
|
|
|
}else{
|
|
|
|
|
this.form.date = moment().format('YYYY-MM-DD')
|
|
|
|
|
this.form.customer_name = option.customer_name?option.customer_name:''
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onReady() {
|
|
|
|
|
this.load();
|
|
|
|
|
this.$refs.uForm.setRules(this.rules);
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
onLoad(option) {
|
|
|
|
|
this.form.customer_id = option.customer_id;
|
|
|
|
|
this.id = option.id;
|
|
|
|
|
this.type = option.id ? 'edit' : 'add';
|
|
|
|
|
if (this.type === 'edit') {
|
|
|
|
|
this.getDetail()
|
|
|
|
|
}else{
|
|
|
|
|
this.form.date = moment().format('YYYY-MM-DD')
|
|
|
|
|
this.form.customer_name = option.customer_name?option.customer_name:''
|
|
|
|
|
}
|
|
|
|
|
if (this.form.customer_id) {
|
|
|
|
|
this.getCustomerInfo()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onReady() {
|
|
|
|
|
this.load();
|
|
|
|
|
this.$refs.uForm.setRules(this.rules);
|
|
|
|
|
},
|
|
|
|
|
computed: {
|
|
|
|
|
defaultCustomerAddress(){
|
|
|
|
|
const idx = this.editCustomer.customer_address.findIndex(i => Number(i.default) === 1)
|
|
|
|
|
return idx > -1 ? this.editCustomer.customer_address[idx] : null
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
async getCustomerInfo(){
|
|
|
|
|
try{
|
|
|
|
|
const res = await this.$u.api.adminCustomerInfo({ id: this.form.customer_id })
|
|
|
|
|
this.customerInfo = res
|
|
|
|
|
// 初始化可编辑数据
|
|
|
|
|
this.editCustomer.phone = res.phone || ''
|
|
|
|
|
this.editCustomer.is_dead = Number(res.is_dead || 0)
|
|
|
|
|
this.editCustomer.customer_address = Array.isArray(res.customer_address) ? JSON.parse(JSON.stringify(res.customer_address)) : []
|
|
|
|
|
}catch(e){
|
|
|
|
|
console.error('adminCustomerInfo error', e)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
defaultAddrIndex() {
|
|
|
|
|
return this.editCustomer.customer_address.findIndex(i => Number(i.default) === 1)
|
|
|
|
|
},
|
|
|
|
|
// 获取定位并更新默认地址(已有默认地址)
|
|
|
|
|
async updateDefaultCustomerAddress(){
|
|
|
|
|
try{
|
|
|
|
|
const res = await uni.getLocation({ type: 'gcj02', isHighAccuracy: true })
|
|
|
|
|
const location = Array.isArray(res) ? res[1] : res
|
|
|
|
|
if(!location) throw new Error('定位失败')
|
|
|
|
|
await new Promise((resolve, reject) => {
|
|
|
|
|
this.qqmapsdk.reverseGeocoder({
|
|
|
|
|
location: { latitude: location.latitude, longitude: location.longitude },
|
|
|
|
|
success: (r) => resolve(r),
|
|
|
|
|
fail: (err) => reject(err)
|
|
|
|
|
})
|
|
|
|
|
}).then(geo => {
|
|
|
|
|
const idx = this.defaultAddrIndex()
|
|
|
|
|
const addr = geo.result.address + (geo.result.formatted_addresses?.recommend || '')
|
|
|
|
|
// 如果已存在默认地址,先移除该条(避免携带旧的 id)
|
|
|
|
|
if (idx > -1) {
|
|
|
|
|
this.editCustomer.customer_address.splice(idx, 1)
|
|
|
|
|
}
|
|
|
|
|
// 插入新的默认地址,且不包含 id 字段
|
|
|
|
|
this.editCustomer.customer_address.push({ address: addr, lat: location.latitude, lng: location.longitude, default: 1 })
|
|
|
|
|
uni.showToast({ icon: 'none', title: '位置已更新' })
|
|
|
|
|
})
|
|
|
|
|
}catch(e){
|
|
|
|
|
uni.showToast({ icon: 'none', title: '定位失败' })
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 无默认地址时创建
|
|
|
|
|
async createDefaultCustomerAddress(){
|
|
|
|
|
await this.updateDefaultCustomerAddress()
|
|
|
|
|
},
|
|
|
|
|
saveCustomerInfo(){
|
|
|
|
|
const payload = {
|
|
|
|
|
...this.customerInfo,
|
|
|
|
|
id: this.form.customer_id,
|
|
|
|
|
is_dead: this.editCustomer.is_dead,
|
|
|
|
|
phone: this.editCustomer.phone,
|
|
|
|
|
customer_address_list: this.editCustomer.customer_address
|
|
|
|
|
}
|
|
|
|
|
this.$u.api.adminCustomerSave(payload).then(()=>{
|
|
|
|
|
uni.showToast({ icon:'success', title:'已更新' })
|
|
|
|
|
this.getCustomerInfo()
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
showimg(url) {
|
|
|
|
|
if (url)
|
|
|
|
|
@ -338,132 +444,132 @@
|
|
|
|
|
let arr = e.filter(i => i?.trim())
|
|
|
|
|
console.log("arr", e, arr)
|
|
|
|
|
// this.$set(item, 'score', arr)
|
|
|
|
|
},
|
|
|
|
|
blurInput(item){
|
|
|
|
|
console.log("blur",item)
|
|
|
|
|
if(!this.validateNumberRange(item.score,item.min,item.max)){
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "请输入正确的分值",
|
|
|
|
|
icon: "none"
|
|
|
|
|
})
|
|
|
|
|
item.score = 0
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 计算总分
|
|
|
|
|
calculateTotalScore(form) {
|
|
|
|
|
// 处理 forms 不存在或非数组的情况
|
|
|
|
|
if (!Array.isArray(this.form.forms)) {
|
|
|
|
|
this.form.total_score = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 检查是否存在任何一个选项的 checked 为 true
|
|
|
|
|
const hasCheckedOption = this.form.forms.some(item => {
|
|
|
|
|
// 如果 item.options 存在且包含 checked 为 true 的项
|
|
|
|
|
return Array.isArray(item.options) &&
|
|
|
|
|
item.options.some(option => option.checked === true);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 如果存在 checked 为 true 的选项,直接返回 0 分
|
|
|
|
|
if (hasCheckedOption) {
|
|
|
|
|
this.form.total_score = 0;
|
|
|
|
|
this.form.forms.map(item=>item.score=0)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 否则,正常累加所有项的分数
|
|
|
|
|
const total = this.form.forms.reduce((sum, item) => {
|
|
|
|
|
// 将 item.score 转换为数字,非数字默认 0
|
|
|
|
|
const score = Number(item.score) || 0;
|
|
|
|
|
return sum + score;
|
|
|
|
|
}, 0);
|
|
|
|
|
|
|
|
|
|
this.form.total_score = total;
|
|
|
|
|
},
|
|
|
|
|
// 判断是否为有效数子
|
|
|
|
|
validateNumberRange(value, min, max) {
|
|
|
|
|
// 步骤1:判断值是否为有效数字(处理字符串形式的数字)
|
|
|
|
|
let num;
|
|
|
|
|
|
|
|
|
|
// 如果已经是数字类型,直接使用
|
|
|
|
|
if (typeof value === 'number') {
|
|
|
|
|
num = value;
|
|
|
|
|
}
|
|
|
|
|
// 如果是字符串,尝试转换为数字
|
|
|
|
|
else if (typeof value === 'string') {
|
|
|
|
|
// 去除首尾空格
|
|
|
|
|
const trimmed = value.trim();
|
|
|
|
|
|
|
|
|
|
// 使用 parseFloat 转换,并验证是否完全匹配数字格式
|
|
|
|
|
num = parseFloat(trimmed);
|
|
|
|
|
|
|
|
|
|
// 如果转换后不是NaN,且字符串完全等于转换后的数字字符串(确保没有多余字符)
|
|
|
|
|
if (isNaN(num) || trimmed !== String(num)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 其他类型(如 null、object 等)直接判定为无效
|
|
|
|
|
else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 步骤2:检查数字是否在范围内(包含边界)
|
|
|
|
|
return num >= min && num <= max;
|
|
|
|
|
},
|
|
|
|
|
/**
|
|
|
|
|
* 验证表单数据
|
|
|
|
|
* @param {Array} forms - 表单数据数组
|
|
|
|
|
* @returns {Object} - 验证结果 { isValid: Boolean, errorMsg: String }
|
|
|
|
|
*/
|
|
|
|
|
validateForm(forms) {
|
|
|
|
|
// 1. 检查是否存在特殊项(包含 options 且有 checked=true)
|
|
|
|
|
const specialItem = forms.find(item =>
|
|
|
|
|
Array.isArray(item.options) &&
|
|
|
|
|
item.options.some(option => option.checked === true)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 如果存在特殊项被勾选,直接返回总分0
|
|
|
|
|
if (specialItem) {
|
|
|
|
|
forms.map(item=>item.score = 0)
|
|
|
|
|
return { isValid: true, totalScore: 0, errorMsg: '' };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. 验证其他项的分数是否有效(在 min 和 max 之间)
|
|
|
|
|
for (const item of forms) {
|
|
|
|
|
// 跳过特殊项
|
|
|
|
|
if (Array.isArray(item.options)) continue;
|
|
|
|
|
|
|
|
|
|
const { score, min, max } = item;
|
|
|
|
|
const parsedScore = parseFloat(score);
|
|
|
|
|
|
|
|
|
|
// 检查分数是否为有效数字
|
|
|
|
|
if (isNaN(parsedScore) || !isFinite(parsedScore)) {
|
|
|
|
|
return { isValid: false, totalScore: 0, errorMsg: `请输入有效的分数:${item.ask}` };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查分数是否在范围内
|
|
|
|
|
if (parsedScore < min || parsedScore > max) {
|
|
|
|
|
return { isValid: false, totalScore: 0, errorMsg: `分数超出范围:${item.ask} (${min}-${max}分)` };
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 3. 计算总分(当所有项都有效时)
|
|
|
|
|
const totalScore = forms.reduce((sum, item) => {
|
|
|
|
|
// 跳过特殊项(已处理)
|
|
|
|
|
if (Array.isArray(item.options)) return sum;
|
|
|
|
|
|
|
|
|
|
// 累加有效分数
|
|
|
|
|
return sum + parseFloat(item.score);
|
|
|
|
|
}, 0);
|
|
|
|
|
|
|
|
|
|
return { isValid: true, totalScore, errorMsg: '' };
|
|
|
|
|
},
|
|
|
|
|
blurInput(item){
|
|
|
|
|
console.log("blur",item)
|
|
|
|
|
if(!this.validateNumberRange(item.score,item.min,item.max)){
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: "请输入正确的分值",
|
|
|
|
|
icon: "none"
|
|
|
|
|
})
|
|
|
|
|
item.score = 0
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 计算总分
|
|
|
|
|
calculateTotalScore(form) {
|
|
|
|
|
// 处理 forms 不存在或非数组的情况
|
|
|
|
|
if (!Array.isArray(this.form.forms)) {
|
|
|
|
|
this.form.total_score = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 检查是否存在任何一个选项的 checked 为 true
|
|
|
|
|
const hasCheckedOption = this.form.forms.some(item => {
|
|
|
|
|
// 如果 item.options 存在且包含 checked 为 true 的项
|
|
|
|
|
return Array.isArray(item.options) &&
|
|
|
|
|
item.options.some(option => option.checked === true);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 如果存在 checked 为 true 的选项,直接返回 0 分
|
|
|
|
|
if (hasCheckedOption) {
|
|
|
|
|
this.form.total_score = 0;
|
|
|
|
|
this.form.forms.map(item=>item.score=0)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 否则,正常累加所有项的分数
|
|
|
|
|
const total = this.form.forms.reduce((sum, item) => {
|
|
|
|
|
// 将 item.score 转换为数字,非数字默认 0
|
|
|
|
|
const score = Number(item.score) || 0;
|
|
|
|
|
return sum + score;
|
|
|
|
|
}, 0);
|
|
|
|
|
|
|
|
|
|
this.form.total_score = total;
|
|
|
|
|
},
|
|
|
|
|
// 判断是否为有效数子
|
|
|
|
|
validateNumberRange(value, min, max) {
|
|
|
|
|
// 步骤1:判断值是否为有效数字(处理字符串形式的数字)
|
|
|
|
|
let num;
|
|
|
|
|
|
|
|
|
|
// 如果已经是数字类型,直接使用
|
|
|
|
|
if (typeof value === 'number') {
|
|
|
|
|
num = value;
|
|
|
|
|
}
|
|
|
|
|
// 如果是字符串,尝试转换为数字
|
|
|
|
|
else if (typeof value === 'string') {
|
|
|
|
|
// 去除首尾空格
|
|
|
|
|
const trimmed = value.trim();
|
|
|
|
|
|
|
|
|
|
// 使用 parseFloat 转换,并验证是否完全匹配数字格式
|
|
|
|
|
num = parseFloat(trimmed);
|
|
|
|
|
|
|
|
|
|
// 如果转换后不是NaN,且字符串完全等于转换后的数字字符串(确保没有多余字符)
|
|
|
|
|
if (isNaN(num) || trimmed !== String(num)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 其他类型(如 null、object 等)直接判定为无效
|
|
|
|
|
else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 步骤2:检查数字是否在范围内(包含边界)
|
|
|
|
|
return num >= min && num <= max;
|
|
|
|
|
},
|
|
|
|
|
/**
|
|
|
|
|
* 验证表单数据
|
|
|
|
|
* @param {Array} forms - 表单数据数组
|
|
|
|
|
* @returns {Object} - 验证结果 { isValid: Boolean, errorMsg: String }
|
|
|
|
|
*/
|
|
|
|
|
validateForm(forms) {
|
|
|
|
|
// 1. 检查是否存在特殊项(包含 options 且有 checked=true)
|
|
|
|
|
const specialItem = forms.find(item =>
|
|
|
|
|
Array.isArray(item.options) &&
|
|
|
|
|
item.options.some(option => option.checked === true)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 如果存在特殊项被勾选,直接返回总分0
|
|
|
|
|
if (specialItem) {
|
|
|
|
|
forms.map(item=>item.score = 0)
|
|
|
|
|
return { isValid: true, totalScore: 0, errorMsg: '' };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. 验证其他项的分数是否有效(在 min 和 max 之间)
|
|
|
|
|
for (const item of forms) {
|
|
|
|
|
// 跳过特殊项
|
|
|
|
|
if (Array.isArray(item.options)) continue;
|
|
|
|
|
|
|
|
|
|
const { score, min, max } = item;
|
|
|
|
|
const parsedScore = parseFloat(score);
|
|
|
|
|
|
|
|
|
|
// 检查分数是否为有效数字
|
|
|
|
|
if (isNaN(parsedScore) || !isFinite(parsedScore)) {
|
|
|
|
|
return { isValid: false, totalScore: 0, errorMsg: `请输入有效的分数:${item.ask}` };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查分数是否在范围内
|
|
|
|
|
if (parsedScore < min || parsedScore > max) {
|
|
|
|
|
return { isValid: false, totalScore: 0, errorMsg: `分数超出范围:${item.ask} (${min}-${max}分)` };
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 3. 计算总分(当所有项都有效时)
|
|
|
|
|
const totalScore = forms.reduce((sum, item) => {
|
|
|
|
|
// 跳过特殊项(已处理)
|
|
|
|
|
if (Array.isArray(item.options)) return sum;
|
|
|
|
|
|
|
|
|
|
// 累加有效分数
|
|
|
|
|
return sum + parseFloat(item.score);
|
|
|
|
|
}, 0);
|
|
|
|
|
|
|
|
|
|
return { isValid: true, totalScore, errorMsg: '' };
|
|
|
|
|
},
|
|
|
|
|
submit() {
|
|
|
|
|
console.log("this.form", this.form)
|
|
|
|
|
const res = this.validateForm(this.form.forms)
|
|
|
|
|
if(!res.isValid){
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title:res.errorMsg,
|
|
|
|
|
icon:'none',
|
|
|
|
|
})
|
|
|
|
|
return
|
|
|
|
|
console.log("this.form", this.form)
|
|
|
|
|
const res = this.validateForm(this.form.forms)
|
|
|
|
|
if(!res.isValid){
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title:res.errorMsg,
|
|
|
|
|
icon:'none',
|
|
|
|
|
})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
const uploadSignImage = () => {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
@ -541,13 +647,13 @@
|
|
|
|
|
icon: 'success',
|
|
|
|
|
title: '保存成功',
|
|
|
|
|
})
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
if(this.type==='edit'){
|
|
|
|
|
uni.redirectTo({
|
|
|
|
|
url:'/package_sub/pages/quality/qualityHistory'
|
|
|
|
|
})
|
|
|
|
|
}else{
|
|
|
|
|
uni.navigateBack()
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
if(this.type==='edit'){
|
|
|
|
|
uni.redirectTo({
|
|
|
|
|
url:'/package_sub/pages/quality/qualityHistory'
|
|
|
|
|
})
|
|
|
|
|
}else{
|
|
|
|
|
uni.navigateBack()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.$u.vuex('vuex_admin_sign_image', '')
|
|
|
|
|
@ -570,7 +676,7 @@
|
|
|
|
|
this.detail = res;
|
|
|
|
|
for (let key in this.form) {
|
|
|
|
|
this.form[key] = res[key]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.form.customer_name = res.customer.name
|
|
|
|
|
console.log(this.form)
|
|
|
|
|
this.fileList = res.files.map(i => ({
|
|
|
|
|
|