|
@@ -0,0 +1,173 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <el-form :model="formData" :rules="rules" ref="formRef" label-width="140px" class="output-form">
|
|
|
|
|
+ <el-form-item label="项目" prop="projectId">
|
|
|
|
|
+ <el-select v-model="formData.projectId" placeholder="请选择项目" :disabled="disabled" filterable style="width: 100%">
|
|
|
|
|
+ <el-option v-for="item in projectOptions" :key="item.projectId" :label="item.projectName" :value="item.projectId">
|
|
|
|
|
+ <span>{{ item.projectName }}</span>
|
|
|
|
|
+ <span style="float: right; color: #909399; font-size: 12px">{{ item.deptName }}</span>
|
|
|
|
|
+ </el-option>
|
|
|
|
|
+ </el-select>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <el-form-item label="填报月份" prop="month">
|
|
|
|
|
+ <el-date-picker v-model="formData.month" type="month" value-format="YYYY-MM" placeholder="请选择填报月份" :disabled="disabled" style="width: 100%" />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <el-form-item label="当月实际进度" prop="currentProgress">
|
|
|
|
|
+ <div class="output-form__progress">
|
|
|
|
|
+ <el-slider v-model="formData.currentProgress" :min="0" :max="100" :step="0.5" :marks="progressMarks" show-input :format-tooltip="formatProgress" />
|
|
|
|
|
+ <span class="output-form__progress-unit">%</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <el-form-item label="当月实际产值" prop="currentOutput">
|
|
|
|
|
+ <el-input-number v-model="formData.currentOutput" :precision="4" :min="0" :max="maxOutput" placeholder="请输入当月实际产值" style="width: 100%">
|
|
|
|
|
+ <template #suffix>万元</template>
|
|
|
|
|
+ </el-input-number>
|
|
|
|
|
+ <div v-if="maxOutput" class="output-form__hint">该项目总产值上限 {{ maxOutput }} 万元</div>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <el-form-item label="协作产值" prop="coopOutput" v-if="showCooperation">
|
|
|
|
|
+ <el-input-number v-model="formData.coopOutput" :precision="4" :min="0" placeholder="请输入协作产值(如有)" style="width: 100%">
|
|
|
|
|
+ <template #suffix>万元</template>
|
|
|
|
|
+ </el-input-number>
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <el-form-item label="进度说明" prop="description">
|
|
|
|
|
+ <el-input v-model="formData.description" type="textarea" :rows="3" placeholder="请输入进度说明(可选)" maxlength="500" show-word-limit />
|
|
|
|
|
+ </el-form-item>
|
|
|
|
|
+
|
|
|
|
|
+ <el-alert
|
|
|
|
|
+ v-if="validationMessage"
|
|
|
|
|
+ :title="validationMessage"
|
|
|
|
|
+ :type="validationType"
|
|
|
|
|
+ :closable="false"
|
|
|
|
|
+ show-icon
|
|
|
|
|
+ style="margin-bottom: 18px"
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-form>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script setup>
|
|
|
|
|
+const props = defineProps({
|
|
|
|
|
+ modelValue: {
|
|
|
|
|
+ type: Object,
|
|
|
|
|
+ default: () => ({})
|
|
|
|
|
+ },
|
|
|
|
|
+ projectOptions: {
|
|
|
|
|
+ type: Array,
|
|
|
|
|
+ default: () => []
|
|
|
|
|
+ },
|
|
|
|
|
+ disabled: {
|
|
|
|
|
+ type: Boolean,
|
|
|
|
|
+ default: false
|
|
|
|
|
+ },
|
|
|
|
|
+ showCooperation: {
|
|
|
|
|
+ type: Boolean,
|
|
|
|
|
+ default: false
|
|
|
|
|
+ },
|
|
|
|
|
+ projectTotalOutput: {
|
|
|
|
|
+ type: Number,
|
|
|
|
|
+ default: undefined
|
|
|
|
|
+ }
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const emit = defineEmits(['update:modelValue', 'validate'])
|
|
|
|
|
+
|
|
|
|
|
+const formRef = ref(null)
|
|
|
|
|
+
|
|
|
|
|
+const progressMarks = {
|
|
|
|
|
+ 0: '0%',
|
|
|
|
|
+ 25: '25%',
|
|
|
|
|
+ 50: '50%',
|
|
|
|
|
+ 75: '75%',
|
|
|
|
|
+ 100: '100%'
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const maxOutput = computed(() => props.projectTotalOutput)
|
|
|
|
|
+
|
|
|
|
|
+const formData = computed({
|
|
|
|
|
+ get: () => props.modelValue,
|
|
|
|
|
+ set: (val) => emit('update:modelValue', val)
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const rules = {
|
|
|
|
|
+ projectId: [{ required: true, message: '请选择项目', trigger: 'change' }],
|
|
|
|
|
+ month: [{ required: true, message: '请选择填报月份', trigger: 'change' }],
|
|
|
|
|
+ currentProgress: [
|
|
|
|
|
+ { required: true, message: '请输入当月实际进度', trigger: 'blur' },
|
|
|
|
|
+ { type: 'number', min: 0, max: 100, message: '进度范围 0-100%', trigger: 'blur' }
|
|
|
|
|
+ ],
|
|
|
|
|
+ currentOutput: [
|
|
|
|
|
+ { required: true, message: '请输入当月实际产值', trigger: 'blur' },
|
|
|
|
|
+ { type: 'number', min: 0, message: '产值不能为负数', trigger: 'blur' }
|
|
|
|
|
+ ]
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const validationMessage = computed(() => {
|
|
|
|
|
+ const output = formData.value.currentOutput
|
|
|
|
|
+ const progress = formData.value.currentProgress
|
|
|
|
|
+ const max = maxOutput.value
|
|
|
|
|
+ if (output != null && output < 0) {
|
|
|
|
|
+ return '当月产值不能为负数'
|
|
|
|
|
+ }
|
|
|
|
|
+ if (max != null && output > max) {
|
|
|
|
|
+ return `当月产值 ${output} 超过项目总产值的 ${(output - max).toFixed(4)} 万元`
|
|
|
|
|
+ }
|
|
|
|
|
+ if (progress != null && (progress < 0 || progress > 100)) {
|
|
|
|
|
+ return '进度百分比必须在 0-100% 之间'
|
|
|
|
|
+ }
|
|
|
|
|
+ return ''
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const validationType = computed(() => {
|
|
|
|
|
+ const msg = validationMessage.value
|
|
|
|
|
+ if (!msg) return 'success'
|
|
|
|
|
+ return 'error'
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+function formatProgress(val) {
|
|
|
|
|
+ return val + '%'
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function validate() {
|
|
|
|
|
+ return new Promise((resolve) => {
|
|
|
|
|
+ formRef.value?.validate((valid) => {
|
|
|
|
|
+ resolve(valid)
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function resetFields() {
|
|
|
|
|
+ formRef.value?.resetFields()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+defineExpose({ validate, resetFields })
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
|
+.output-form {
|
|
|
|
|
+ &__progress {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 12px;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+
|
|
|
|
|
+ .el-slider {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &__progress-unit {
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ color: #606266;
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ &__hint {
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ color: #909399;
|
|
|
|
|
+ margin-top: 4px;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|