|
|
@@ -1,25 +1,24 @@
|
|
|
<template>
|
|
|
- <view v-if="rulesInit" class="mt-40 flex flex-col gap-30">
|
|
|
- <view v-for="(r,i) in renderRules.filter(i => i.details?.length)" :key="i" class="flex flex-col gap-30">
|
|
|
- <view class="text-32 font-bold">{{ r.category }}</view>
|
|
|
- <uv-form ref="form" :model="model" :rules="rules" label-position="top">
|
|
|
- <uv-form-item v-for="d in r.details" :key="d.fieldName" :prop="d.fieldName">
|
|
|
- <view class="flex-1 flex items-center justify-between gap-40">
|
|
|
- <text class="text-30 text-fore-title" :style="{width: getLabelWidth(r)}">{{ d.label }}</text>
|
|
|
- <uv-input v-model="model[d.fieldName]" :disabled="d.readonly"
|
|
|
- :placeholder="d.placeholder || '请输入'"
|
|
|
- :suffix-icon="d.readonly ? 'lock': undefined"/>
|
|
|
- <text class="text-28 text-fore-placeholder">(总分 {{ d.options.toString() }})</text>
|
|
|
- </view>
|
|
|
- </uv-form-item>
|
|
|
- </uv-form>
|
|
|
- </view>
|
|
|
+ <view v-if="rulesInit && renderRules" class="mt-40 flex flex-col gap-30">
|
|
|
+ <view v-for="(r, i) in renderRules.filter(i => i.details?.length)" :key="i" class="flex flex-col gap-30">
|
|
|
+ <view class="text-32 font-bold">{{ r.category }}</view>
|
|
|
+ <uv-form ref="form" :model="model" :rules="rules" label-position="top">
|
|
|
+ <uv-form-item v-for="d in r.details" :key="d.fieldName" :prop="d.fieldName">
|
|
|
+ <view class="flex-1 flex items-center justify-between gap-40">
|
|
|
+ <text class="text-30 text-fore-title" :style="{ width: getLabelWidth(r) }">{{ d.label }}</text>
|
|
|
+ <uv-input v-model="model[d.fieldName]" :disabled="d.readonly" :placeholder="d.placeholder || '请输入'"
|
|
|
+ :suffix-icon="d.readonly ? 'lock' : undefined" />
|
|
|
+ <text v-if="d.options" class="text-28 text-fore-placeholder">(总分 {{ d.options.toString() }})</text>
|
|
|
+ </view>
|
|
|
+ </uv-form-item>
|
|
|
+ </uv-form>
|
|
|
</view>
|
|
|
+ </view>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import {VOLUNTARY_RULES, VOLUNTARY_MODEL} from "@/types/injectionSymbols";
|
|
|
-import {EnrollRule, EnrollRuleItem, VoluntaryModel} from "@/types/voluntary";
|
|
|
+import { VOLUNTARY_RULES, VOLUNTARY_MODEL } from "@/types/injectionSymbols";
|
|
|
+import { EnrollRule, EnrollRuleItem, VoluntaryModel } from "@/types/voluntary";
|
|
|
import _ from "lodash";
|
|
|
|
|
|
const renderRules = inject(VOLUNTARY_RULES) || ref<EnrollRule[]>()
|
|
|
@@ -29,112 +28,110 @@ const rules = ref({})
|
|
|
const rulesInit = ref(false)
|
|
|
|
|
|
const getLabelWidth = function (rule: EnrollRule) {
|
|
|
- const maxLen = _.maxBy(rule.details, d => d.label.length)
|
|
|
- return (maxLen?.label.length || 2) * 30 + 'rpx'
|
|
|
+ const maxLen = _.maxBy(rule.details, d => d.label.length)
|
|
|
+ return (maxLen?.label.length || 2) * 30 + 'rpx'
|
|
|
}
|
|
|
|
|
|
const validate = () => {
|
|
|
- if (!form.value) return
|
|
|
- const validates = form.value.map(f => f.validate())
|
|
|
- return Promise.all(validates)
|
|
|
+ if (!form.value) return
|
|
|
+ const validates = form.value.map(f => f.validate())
|
|
|
+ return Promise.all(validates)
|
|
|
}
|
|
|
|
|
|
watch([renderRules, model], ([renderRules, model]) => {
|
|
|
- if (!renderRules || !model) return
|
|
|
- const autoRules: Record<string, any> = {}
|
|
|
- renderRules.forEach((item: EnrollRule) => {
|
|
|
- item.details?.forEach((r: EnrollRuleItem) => {
|
|
|
- // TODO: 此规则逻辑从旧的uni-vueuse mx-base分支迁移过来,可能不完全适用于新版本。
|
|
|
- const fieldRules = []
|
|
|
- // 录取规则,自动添加非空校验
|
|
|
- if (r.enumRuleCategory == 'Enroll') {
|
|
|
- fieldRules.push({required: true, message: `请填写${r.label}分数`})
|
|
|
+ if (!renderRules || !model) return
|
|
|
+ const autoRules: Record<string, any> = {}
|
|
|
+ renderRules.forEach((item: EnrollRule) => {
|
|
|
+ item.details?.forEach((r: EnrollRuleItem) => {
|
|
|
+ // TODO: 此规则逻辑从旧的uni-vueuse mx-base分支迁移过来,可能不完全适用于新版本。
|
|
|
+ const fieldRules = []
|
|
|
+ // 录取规则,自动添加非空校验
|
|
|
+ if (r.enumRuleCategory == 'Enroll') {
|
|
|
+ fieldRules.push({ required: true, message: `请填写${r.label}分数` })
|
|
|
+ }
|
|
|
+ // 分制类型的输入,要同时校验分制与得分
|
|
|
+ if (r.enumInputType == 'Score') {
|
|
|
+ fieldRules.push({
|
|
|
+ validator: (_r: any, _v: any, cb: (arg0: string | undefined) => void) => {
|
|
|
+ const fieldTotal = r.fieldName + 'Total'
|
|
|
+ let score = Number(model[r.fieldName]) || 0
|
|
|
+ let total = Number(model[fieldTotal]) || 0
|
|
|
+ if (!total) {
|
|
|
+ cb(`请选择总分`)
|
|
|
+ return
|
|
|
}
|
|
|
- // 分制类型的输入,要同时校验分制与得分
|
|
|
- if (r.enumInputType == 'Score') {
|
|
|
- fieldRules.push({
|
|
|
- validator: (_r: any, _v: any, cb: (arg0: string | undefined) => void) => {
|
|
|
- const fieldTotal = r.fieldName + 'Total'
|
|
|
- let score = Number(model[r.fieldName]) || 0
|
|
|
- let total = Number(model[fieldTotal]) || 0
|
|
|
- if (!total) {
|
|
|
- cb(`请选择总分`)
|
|
|
- return
|
|
|
- }
|
|
|
- if (!score) {
|
|
|
- cb(`请填写${r.label}分数`)
|
|
|
- return
|
|
|
- }
|
|
|
- if (score < 0 || score > total) {
|
|
|
- cb(`分数不能超过总分${total}`)
|
|
|
- return
|
|
|
- }
|
|
|
- cb(undefined)
|
|
|
- }
|
|
|
- })
|
|
|
+ if (!score) {
|
|
|
+ cb(`请填写${r.label}分数`)
|
|
|
+ return
|
|
|
}
|
|
|
- const hasVal = (val: any) => val !== null && val !== undefined
|
|
|
- if (hasVal(r.min) || hasVal(r.max)) {
|
|
|
- const createRangeMsg = () => {
|
|
|
- if (r.enumInputType == 'Text') {
|
|
|
- if (hasVal(r.min) && hasVal(r.max)) return `长度必须在${r.min}-${r.max}个字符之间`
|
|
|
- if (hasVal(r.min)) return `长度至少${r.min}个字符`
|
|
|
- if (hasVal(r.max)) return `长度不超过${r.max}个字符`
|
|
|
- } else if (r.enumInputType == 'Number') {
|
|
|
- if (hasVal(r.min) && hasVal(r.max)) return `数值必须在${r.min}-${r.max}之间`
|
|
|
- if (hasVal(r.min)) return `数值不能小于${r.min}`
|
|
|
- if (hasVal(r.max)) return `数值不能大于${r.max}`
|
|
|
- } else if (r.enumInputType == 'Checkbox') {
|
|
|
- if (hasVal(r.min) && hasVal(r.max)) return `必须选择${r.min}-${r.max}项`
|
|
|
- if (hasVal(r.min)) return `至少选择${r.min}项`
|
|
|
- if (hasVal(r.max)) return `至多选择${r.max}项`
|
|
|
- }
|
|
|
- }
|
|
|
- const createRangeType = () => {
|
|
|
- switch (r.enumInputType) {
|
|
|
- case 'Number':
|
|
|
- case 'Score':
|
|
|
- return 'number'
|
|
|
- case 'Checkbox':
|
|
|
- return 'array'
|
|
|
- default:
|
|
|
- return 'string'
|
|
|
- }
|
|
|
- }
|
|
|
- const rangeRule : {
|
|
|
- type: string,
|
|
|
- min?: number,
|
|
|
- max?: number,
|
|
|
- message: string | undefined
|
|
|
- transform?: (val: any) => any
|
|
|
- } = {
|
|
|
- type: createRangeType(),
|
|
|
- min: r.min,
|
|
|
- max: r.max,
|
|
|
- message: createRangeMsg()
|
|
|
- }
|
|
|
- if (!hasVal(r.min)) delete rangeRule.min
|
|
|
- if (!hasVal(r.max)) delete rangeRule.max
|
|
|
- if (r.enumInputType == 'Number')
|
|
|
- rangeRule.transform = val => hasVal(val) ? val * 1 : val
|
|
|
- fieldRules.push(rangeRule)
|
|
|
+ if (score < 0 || score > total) {
|
|
|
+ cb(`分数不能超过总分${total}`)
|
|
|
+ return
|
|
|
}
|
|
|
- if (r.regex) {
|
|
|
- fieldRules.push({
|
|
|
- pattern: r.regex,
|
|
|
- message: `${r.label}格式不符合要求`
|
|
|
- })
|
|
|
- }
|
|
|
- if (fieldRules.length) autoRules[r.fieldName] = fieldRules
|
|
|
+ cb(undefined)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ const hasVal = (val: any) => val !== null && val !== undefined
|
|
|
+ if (hasVal(r.min) || hasVal(r.max)) {
|
|
|
+ const createRangeMsg = () => {
|
|
|
+ if (r.enumInputType == 'Text') {
|
|
|
+ if (hasVal(r.min) && hasVal(r.max)) return `长度必须在${r.min}-${r.max}个字符之间`
|
|
|
+ if (hasVal(r.min)) return `长度至少${r.min}个字符`
|
|
|
+ if (hasVal(r.max)) return `长度不超过${r.max}个字符`
|
|
|
+ } else if (r.enumInputType == 'Number') {
|
|
|
+ if (hasVal(r.min) && hasVal(r.max)) return `数值必须在${r.min}-${r.max}之间`
|
|
|
+ if (hasVal(r.min)) return `数值不能小于${r.min}`
|
|
|
+ if (hasVal(r.max)) return `数值不能大于${r.max}`
|
|
|
+ } else if (r.enumInputType == 'Checkbox') {
|
|
|
+ if (hasVal(r.min) && hasVal(r.max)) return `必须选择${r.min}-${r.max}项`
|
|
|
+ if (hasVal(r.min)) return `至少选择${r.min}项`
|
|
|
+ if (hasVal(r.max)) return `至多选择${r.max}项`
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const createRangeType = () => {
|
|
|
+ switch (r.enumInputType) {
|
|
|
+ case 'Number':
|
|
|
+ case 'Score':
|
|
|
+ return 'number'
|
|
|
+ case 'Checkbox':
|
|
|
+ return 'array'
|
|
|
+ default:
|
|
|
+ return 'string'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const rangeRule: {
|
|
|
+ type: string,
|
|
|
+ min?: number,
|
|
|
+ max?: number,
|
|
|
+ message: string | undefined
|
|
|
+ transform?: (val: any) => any
|
|
|
+ } = {
|
|
|
+ type: createRangeType(),
|
|
|
+ min: r.min,
|
|
|
+ max: r.max,
|
|
|
+ message: createRangeMsg()
|
|
|
+ }
|
|
|
+ if (!hasVal(r.min)) delete rangeRule.min
|
|
|
+ if (!hasVal(r.max)) delete rangeRule.max
|
|
|
+ if (r.enumInputType == 'Number')
|
|
|
+ rangeRule.transform = val => hasVal(val) ? val * 1 : val
|
|
|
+ fieldRules.push(rangeRule)
|
|
|
+ }
|
|
|
+ if (r.regex) {
|
|
|
+ fieldRules.push({
|
|
|
+ pattern: r.regex,
|
|
|
+ message: `${r.label}格式不符合要求`
|
|
|
})
|
|
|
+ }
|
|
|
+ if (fieldRules.length) autoRules[r.fieldName] = fieldRules
|
|
|
})
|
|
|
- rules.value = autoRules
|
|
|
- rulesInit.value = true
|
|
|
-}, {immediate: true})
|
|
|
+ })
|
|
|
+ rules.value = autoRules
|
|
|
+ rulesInit.value = true
|
|
|
+}, { immediate: true })
|
|
|
|
|
|
-defineExpose({validate})
|
|
|
+defineExpose({ validate })
|
|
|
</script>
|
|
|
|
|
|
-<style scoped>
|
|
|
-
|
|
|
-</style>
|
|
|
+<style scoped></style>
|