在Flex中用Validator检测数字、字符串、Email、电话号码等 .

Flex中使用Validator
在Flex中用Validator检测数字、字符串、Email、电话号码等
在上例“ 用Validator检测必填项”中,我记录了Validator最简单的用法。但mx.validators包中的类并非只有Validator一个,他们可以实现信用卡号码格式检测(mx.validators.CreditCardValidator)、货币格式检测(mx.validators.CurrencyValidator)、E-mail格式检测(mx.validators.EmailValidator)等等功能,所有的检测器列表可以看 这里。这些类都是Validator的子类。

先看效果。下面的范例演示了StringValidator、NumberValidator和EmailValidator的用法。由于这三个类都继承自Validator,因此都拥有requiredFieldError属性,用于自定义没有值的时候的错误信息。但是这三个类拥有更多的错误信息。要检测的值越复杂,需要定义的错误信息就越多,例如EmailValidator,本例中共定义了9个错误信息。

如果不定义错误信息,Flex会显示默认的英文错误信息,这显然也不是我们所需要的。如果想偷懒的话,可以定义几个最可能出现的错误,例如本例的NumberValidator,就没有定义所有的错误信息。

顺便还要说一句的是,NumberValidator可以指定要检测的数字是整数还是实数,这需要用domain属性来指定。同时,它还可以指定千分位分隔符。

<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" fontSize="12" width="300" height="200">

 <mx:Style>
 <![CDATA[
 .errorTip
 {
 fontSize: 12;
 }
 ]]>
 </mx:Style>

 <mx:StringValidator id="nameV" source="{nameTI}" property="text"
 minLength="2"
 maxLength="5"
 requiredFieldError="必须输入姓名!"
 tooShortError="姓名过短!"
 tooLongError="姓名过长!"
 trigger="{btn}" triggerEvent="click"/>

 <mx:NumberValidator id="ageV" source="{ageTI}" property="text"
 domain="int"
 minValue="6"
 maxValue="100"
 lowerThanMinError="年龄过小!"
 exceedsMaxError="年龄过大!"
 integerError="年龄必须是整数!"
 invalidCharError='输入了非数字字符!'
 requiredFieldError="必须输入年龄!"
 trigger="{btn}" triggerEvent="click"/>

 <mx:Validator id="sexV" source="{sexRBG}" property="selectedValue"
 requiredFieldError="必须选择性别!"
 trigger="{btn}" triggerEvent="click"
 listener="{maleRB}"/>

 <mx:EmailValidator id="emailV" source="{emailTI}" property="text"
 requiredFieldError="必须输入E-mail"
 invalidCharError="E-mail地址中有错误字符。"
 invalidDomainError="E-mail地址中的域名不符合规范。"
 invalidIPDomainError="E-mail地址中的IP格式域名不符合规范。"
 invalidPeriodsInDomainError="域名中的“.”错误。"
 missingAtSignError="E-mail地址缺少“@”符号。"
 missingPeriodInDomainError="域名中缺少“.”"
 missingUsernameError="E-mail地址缺少用户名。"
 tooManyAtSignsError="E-mail地址中的“@”符号太多。"
 trigger="{btn}" triggerEvent="click"/>
 
 <mx:FormItem label="姓名:" width="200">
 <mx:TextInput id="nameTI"/>
 </mx:FormItem>

 <mx:FormItem label="年龄:" width="200">
 <mx:TextInput id="ageTI"/>
 </mx:FormItem>

 <mx:FormItem label="性别:" direction="horizontal" width="200">
 <mx:RadioButtonGroup id="sexRBG"/>
 <mx:RadioButton id="maleRB" groupName="sexRBG" label="男" value="1"/>
 <mx:RadioButton id="femaleRB" groupName="sexRBG" label="女" value="0"/>
 </mx:FormItem>

 <mx:FormItem label="E-mail:" width="200">
 <mx:TextInput id="emailTI"/>
 </mx:FormItem>

 <mx:Button id="btn" label="提交" />
<template> <el-form ref="ruleFormRef" style="margin-top: 20px;max-width: 600px" :model="ruleForm" :rules="rules" label-width="auto"> <el-form-item label="产品名称:" prop="name"> <el-input v-model="ruleForm.name" /> </el-form-item> <el-form-item label="产品描述:" prop="description"> <el-input v-model="ruleForm.description" type="textarea"/> </el-form-item> <el-form-item label="产品分类:" prop="category" style="width: 50%;"> <el-select v-model="ruleForm.category" placeholder="请选择分类"> <el-option v-for="item in categorys" :label="item.name" :value="item.id" :key="item.id" /> </el-select> </el-form-item> <el-form-item label="产品单价:" prop="price"> <el-input v-model.number="ruleForm.price" type="number" style="width: 240px" /> </el-form-item> <el-form-item label="产品库存:" prop="stock"> <el-input v-model.number="ruleForm.stock" type="number" style="width: 240px" /> </el-form-item> <el-form-item label="生产厂家:" prop="manufacturer"> <el-input v-model="ruleForm.manufacturer" /> </el-form-item> <el-form-item label="产地:" required> <el-col :span="12"> <el-form-item prop="originProvince"> <el-select v-model="ruleForm.originProvince" placeholder="省" style="flex: 1; margin-right: 10px"> <el-option v-for="item in originProvinces" :key="item.id" :label="item.name" :value="item.id" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item prop="originCity"> <el-select v-model="ruleForm.originCity" placeholder="市" style="flex: 1 " :disabled="!ruleForm.originProvince"> <el-option v-for="item in originCitys" :key="item.id" :label="item.name" :value="item.id" /> </el-select> </el-form-item> </el-col> </el-form-item> <el-form-item label="发货地:" required> <el-col :span="12"> <el-form-item prop="shippingProvince"> <el-select v-model="ruleForm.shippingProvince" placeholder="省" style="flex: 1; margin-right: 10px"> <el-option v-for="item in originProvinces" :key="item.id" :label="item.name" :value="item.id" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item prop="shippingCity"> <el-select v-model="ruleForm.shippingCity" placeholder="市" style="flex: 1" :disabled="!ruleForm.shippingProvince"> <el-option v-for="item in shippingCities" :key="item.id" :label="item.name" :value="item.id" /> </el-select> </el-form-item> </el-col> </el-form-item> <el-form-item label="生产日期" required> <el-col :span="11"> <el-form-item prop="createAt"> <el-date-picker v-model="ruleForm.createAt" type="date" aria-label="Pick a date" placeholder="Pick a date" style="width: 100%" /> </el-form-item> </el-col> </el-form-item> <el-form-item> <!-- 登录按钮:仅在默认模式下显示 --> <el-button v-if="pageMode === 'default'" style="margin-left: 18px;" type="primary" @click="submitForm(ruleFormRef, ruleForm)"> 登录 </el-button> <!-- 更新按钮:仅在编辑模式下显示 --> <el-button v-if="pageMode === 'edit'" style="margin-left: 30px;" type="primary" @click="updateForm(ruleFormRef)"> 更新 </el-button> <!-- 重置按钮:在编辑或默认模式下都显示 --> <el-button v-if="pageMode === 'edit' || pageMode === 'default'" style="margin-left: 30px;" type="primary" @click="resetForm(ruleFormRef)"> 重置 </el-button> </el-form-item> </el-form> </template> <script setup> import { ref, reactive, onMounted } from 'vue'; import productApi from '@/api/products' import placeApi from '@/api/place' import { useRouter } from 'vue-router' import { ElLoading, ElMessage } from 'element-plus' const pageMode = ref('') // 可选值: 'view', 'edit', 'default' const router = useRouter(); const ruleFormRef = ref() const categorys = ref([])// 产品分类 const originProvinces = ref([]) // 省份数据 const originCitys = ref([]) // 城市数据 const shippingCities = ref([]) // 发货地城市数据 const ruleForm = reactive({ name: '', description: '', category: '', price: '', stock: '', manufacturer: '', originProvince: '', originCity: '', shippingProvince: '', shippingCity: '', createAt: '', user: 'aaa', delivery: false, type: [], }) const rules = reactive({ name: [ { required: true, message: '请输入商品名称', trigger: 'blur' }, { max: 10, message: '长度超过10位', trigger: 'blur' }, ], description: [ { required: true, message: '请输入商品描述', trigger: 'blur' }, { max: 200, message: '长度超过200位', trigger: 'blur' }, ], category: [ { required: true, message: '请选择分类', trigger: 'change', }, ], price: [ { required: true, message: '请输入商品单价', trigger: ['blur', 'change'] }, { type: 'number', message: '请输入有效的数字', trigger: ['blur', 'change'] }, { validator: (rule, value, callback) => { if (value === null || value === '') { callback(new Error('请输入商品单价')) } else if (value <= 0) { callback(new Error('单价必须大于 0')) } else if (value > 10000) { callback(new Error('单价不能大于 10000')) } else { callback() } }, trigger: ['blur', 'change'] } ], stock: [ { required: true, message: '请输入商品单价', trigger: ['blur', 'change'] }, { type: 'number', message: '请输入有效的数字', trigger: ['blur', 'change'] }, { validator: (rule, value, callback) => { if (value === null || value === '') { callback(new Error('请输入商品单价')) } else if (value <= 0) { callback(new Error('单价必须大于 0')) } else if (value > 10000) { callback(new Error('单价不能大于 10000')) } else { callback() } }, trigger: ['blur', 'change'] } ], manufacturer: [ { required: true, message: '请输入生产厂家', trigger: 'blur' }, ], shippingProvince: { validator: (rule, value, callback) => { if (!value) { callback(new Error('请选择发货省份')) } else { callback() } }, trigger: 'change' }, shippingCity:{ validator: (rule, value, callback) => { if (!value) { callback(new Error('请选择发货城市')) } else { callback() } }, trigger: 'change' }, originProvince: { validator: (rule, value, callback) => { if (!value) { callback(new Error('请选择发货省份')) } else { callback() } }, trigger: 'change' }, originCity:{ validator: (rule, value, callback) => { if (!value) { callback(new Error('请选择发货城市')) } else { callback() } }, trigger: 'change' }, createAt: [ { type: 'date', required: true, message: 'Please pick a date', trigger: 'change', }, ], type: [ { type: 'array', required: true, message: 'Please select at least one activity type', trigger: 'change', }, ], }) // 表单操作 const resetForm = (formEl) => { if (!formEl) return formEl.resetFields() } //产品分类 function getCategory() { productApi.getCategory().then(res => { categorys.value = res.data; }) } // 获取省份 function getProvinces() { placeApi.getProvince().then(res => { originProvinces.value = res.data }).catch(error => { console.error('获取省份失败:', error) }) } // 获取商品详情 function getProductDetail(productId) { productApi.getById(productId).then(res => { const data = res.data // 先赋值整个对象 Object.assign(ruleForm, data) }).catch(error => { console.error('获取商品详情失败:', error); }); } // 监听产地省份变化,加载城市 watch( () => ruleForm.originProvince, (newVal) => { if (newVal) { placeApi.getCity(newVal).then(res => { originCitys.value = res.data }).catch(() => { originCitys.value = [] }) } else { originCitys.value = [] ruleForm.originCity = '' } } ) // 监听发货地省份变化,加载城市 watch( () => ruleForm.shippingProvince, (newVal) => { if (newVal) { placeApi.getCity(newVal).then(res => { shippingCities.value = res.data }).catch(() => { shippingCities.value = [] }) } else { shippingCities.value = [] ruleForm.shippingCity = '' } } ) // 更新操作 const updateForm = async (formEl) => { if (!formEl) return const loading = ElLoading.service({ fullscreen: true }) await formEl.validate((valid, fields) => { if (valid) { console.log('开始提交...') // 调用 API 更新商品信息 productApi.update(ruleForm).then(res => { ElMessage.success('更新成功') router.push('/home/test1') // 可选跳转回列表页 }).catch(error => { ElMessage.error('更新失败,请重试') }).finally(() => { loading.close() }) } else { console.log('表单验证失败:', fields) ElMessage.error('请检查输入内容') loading.close() return false } }) } // 登录操作 const submitForm = async (formEl, ruleForm) => { if (!formEl) return await formEl.validate((valid, fields) => { if (valid) { console.log('开始提交商品...') const loading = ElLoading.service({ fullscreen: true }) productApi.addProduct(ruleForm).then(res => { ElMessage.success('保存成功') router.push('/home/test1') }).catch(error => { ElMessage.error('保存失败,请重试') }).finally(() => { loading.close() }) } else { console.log('表单验证失败:', fields) ElMessage.error('请检查输入内容') loading.close() return false } }) } onMounted(() => { getCategory() getProvinces() const route = router.currentRoute.value const type = route.query.type const productId = route.params.id || route.query.id if (type === 'view') { pageMode.value = 'view' // 查看模式:不显示按钮 } else if (type === 'edit') { pageMode.value = 'edit' // 编辑模式:显示“更新”、“重置” } else { pageMode.value = 'default' // 默认模式:显示“登录”、“重置” } if (productId) { getProductDetail(productId) } }) </script> <style> .location-selectors { display: flex; justify-content: space-between; width: 100%; } </style>
07-15
<script lang="tsx" setup>   import { stringToBase64 } from './utils/index';   import { ref, watchEffect } from 'vue';   import { renderToString } from '@vue/server-renderer';   interface IProps {     defaultDurTime?: number; //进度条完结时间     progress?: number; //当前进度0-100     color?: object | string; //进度条颜色,传入对象格式可以定义渐变色     width?: number; //矩形宽度     height?: number; //矩形高度     radian?: number; //矩形圆角弧度     layerColor?: string; //轨道颜色     fill?: string; //填充颜色     strokeWidth?: number; //线条宽度     strokeLinecap?: string; //进度条端点(butt,round,square)   }   const props = withDefaults(defineProps<IProps>(), {     defaultDurTime: 1000, //进度条完结时间     progress: 50,     color: () => {       return { '0': '#80EDFF', '100': '#4A7DFF' };     },     width: 140,     height: 120,     radian: 20,     layerColor: '#e0e0e0',     fill: 'none',     strokeWidth: 10,     strokeLinecap: 'round',   });   const progressOffset = ref(0);   const allLen = ref(0);   const strokeBgColor = ref<string | object>('#666666');   let dataURL = ref('');   async function handleSave() {     const html = await renderToString(renderTitle());     dataURL.value = stringToBase64(html);     console.log(dataURL);   }   const renderTitle = () =>     return (       <svg         width={props.width + props.strokeWidth}         height={props.height + props.strokeWidth}         xmlns="http://www.w3.org/2000/svg"       >         {Object.prototype.toString.call(props.color) === '[object Object]' && (           <defs>             <linearGradient id="progressGradient" x1="0%" y1="0%" x2="100%" y2="0%">               {Object.keys(props.color).map((key) => (                 <stop offset={`${key}%`} stop-color={props.color[key]} key={key}></stop>               ))}             </linearGradient>           </defs>         )}         <rect           x={0.5 * props.strokeWidth}           y={0.5 * props.strokeWidth}           rx={props.radian}           ry={props.radian}           width={props.width}           height={props.height}           style={{ strokeWidth: props.strokeWidth, fill: props.fill, stroke: props.layerColor }}         />         {props.progress !== 0 && (           <rect             x={0.5 * props.strokeWidth}             y={0.5 * props.strokeWidth}             rx={props.radian}             ry={props.radian}             width={props.width}             height={props.height}             style={{               strokeDashoffset: progressOffset.value,               strokeDasharray: allLen.value,               strokeWidth: props.strokeWidth,               fill: props.fill,               stroke: strokeBgColor.value,               strokeLinecap: props.strokeLinecap,             }}           >             <animate               attributeName="stroke-dashoffset"               dur={`${props.defaultDurTime}ms`}               fill="freeze"               from={allLen.value}               to={progressOffset.value}             ></animate>           </rect>         )}       </svg>     );   };   watchEffect(() => {     allLen.value = (props.width + props.height) * 2 - props.radian * 8 + 2 * props.radian * Math.PI;     if (props.strokeLinecap !== 'butt' && props.progress !== 100 && props.progress > 95) {       progressOffset.value         allLen.value - (props.progress / 100) * allLen.value + props.strokeWidth;     } else {       progressOffset.value = allLen.value - (props.progress / 100) * allLen.value;     }     if (Object.prototype.toString.call(props.color) === '[object Object]') {       strokeBgColor.value = `url(#progressGradient)`;     } else {       strokeBgColor.value = props.color;     }     handleSave();   }); </script> 把这段代码使用vue3实现
05-14
基于数据驱动的 Koopman 算子的递归神经网络模型线性化,用于纳米定位系统的预测控制研究(Matlab代码实现)内容概要:本文围绕“基于数据驱动的Koopman算子的递归神经网络模型线性化”展开,旨在研究纳米定位系统的预测控制问题,并提供完整的Matlab代码实现。文章结合数据驱动方法与Koopman算子理论,利用递归神经网络(RNN)对非线性系统进行建模与线性化处理,从而提升纳米级定位系统的精度与动态响应性能。该方法通过提取系统隐含动态特征,构建近似线性模型,便于后续模型预测控制(MPC)的设计与优化,适用于高精度自动化控制场景。文中还展示了相关实验验证与仿真结果,证明了该方法的有效性和先进性。; 适合人群:具备一定控制理论基础和Matlab编程能力,从事精密控制、智能制造、自动化或相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于纳米级精密定位系统(如原子力显微镜、半导体制造设备)中的高性能控制设计;②为非线性系统建模与线性化提供一种结合深度学习与现代控制理论的新思路;③帮助读者掌握Koopman算子、RNN建模与模型预测控制的综合应用。; 阅读建议:建议读者结合提供的Matlab代码逐段理解算法实现流程,重点关注数据预处理、RNN结构设计、Koopman观测矩阵构建及MPC控制器集成等关键环节,并可通过更换实际系统数据进行迁移验证,深化对方法泛化能力的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值