Commit caba9d96517fe37f776708586b1fa9fb13bdb229
1 parent
eb48bd86
oa 中除了 工作办理没有测试其他测试完成
Showing
18 changed files
with
451 additions
and
300 deletions
src/components/oa/addWorkType.vue
| 1 | 1 | <template> |
| 2 | - <el-dialog | |
| 3 | - :title="$t('workType.add.title')" | |
| 4 | - :visible.sync="visible" | |
| 5 | - width="50%" | |
| 6 | - @close="handleClose" | |
| 7 | - > | |
| 8 | - <el-form ref="form" :model="formData" :rules="rules" label-width="120px"> | |
| 2 | + <el-dialog :title="$t('workType.add.title')" :visible.sync="visible" width="50%" @close="handleClose"> | |
| 3 | + <el-form ref="form" :model="formData" :rules="rules" label-width="120px" class="text-left"> | |
| 9 | 4 | <el-form-item :label="$t('workType.form.typeName')" prop="typeName"> |
| 10 | - <el-input | |
| 11 | - v-model.trim="formData.typeName" | |
| 12 | - :placeholder="$t('workType.placeholder.typeName')" | |
| 13 | - /> | |
| 5 | + <el-input v-model.trim="formData.typeName" :placeholder="$t('workType.placeholder.typeName')" /> | |
| 14 | 6 | </el-form-item> |
| 15 | - | |
| 7 | + | |
| 16 | 8 | <el-form-item :label="$t('workType.form.deduction')" prop="deduction"> |
| 17 | - <el-select | |
| 18 | - v-model="formData.deduction" | |
| 19 | - :placeholder="$t('workType.placeholder.deduction')" | |
| 20 | - style="width:100%" | |
| 21 | - > | |
| 22 | - <el-option | |
| 23 | - v-for="item in deductionOptions" | |
| 24 | - :key="item.value" | |
| 25 | - :label="item.label" | |
| 26 | - :value="item.value" | |
| 27 | - /> | |
| 9 | + <el-select v-model="formData.deduction" :placeholder="$t('workType.placeholder.deduction')" style="width:100%"> | |
| 10 | + <el-option v-for="item in deductionOptions" :key="item.value" :label="item.label" :value="item.value" /> | |
| 28 | 11 | </el-select> |
| 29 | 12 | <div class="el-form-item__tip" v-if="formData.deduction === 'Y'"> |
| 30 | 13 | {{ $t('workType.tip.deduction') }} |
| ... | ... | @@ -32,17 +15,8 @@ |
| 32 | 15 | </el-form-item> |
| 33 | 16 | |
| 34 | 17 | <el-form-item :label="$t('workType.form.smsWay')" prop="smsWay"> |
| 35 | - <el-select | |
| 36 | - v-model="formData.smsWay" | |
| 37 | - :placeholder="$t('workType.placeholder.smsWay')" | |
| 38 | - style="width:100%" | |
| 39 | - > | |
| 40 | - <el-option | |
| 41 | - v-for="item in smsWayOptions" | |
| 42 | - :key="item.value" | |
| 43 | - :label="item.label" | |
| 44 | - :value="item.value" | |
| 45 | - /> | |
| 18 | + <el-select v-model="formData.smsWay" :placeholder="$t('workType.placeholder.smsWay')" style="width:100%"> | |
| 19 | + <el-option v-for="item in smsWayOptions" :key="item.value" :label="item.label" :value="item.value" /> | |
| 46 | 20 | </el-select> |
| 47 | 21 | <div class="el-form-item__tip" v-if="formData.smsWay === 'WECHAT'"> |
| 48 | 22 | {{ $t('workType.tip.wechat') }} |
| ... | ... | @@ -53,14 +27,8 @@ |
| 53 | 27 | </el-form-item> |
| 54 | 28 | |
| 55 | 29 | <el-form-item :label="$t('workType.form.remark')"> |
| 56 | - <el-input | |
| 57 | - v-model.trim="formData.remark" | |
| 58 | - type="textarea" | |
| 59 | - :rows="3" | |
| 60 | - :placeholder="$t('workType.placeholder.remark')" | |
| 61 | - maxlength="500" | |
| 62 | - show-word-limit | |
| 63 | - /> | |
| 30 | + <el-input v-model.trim="formData.remark" type="textarea" :rows="3" | |
| 31 | + :placeholder="$t('workType.placeholder.remark')" maxlength="500" show-word-limit /> | |
| 64 | 32 | </el-form-item> |
| 65 | 33 | </el-form> |
| 66 | 34 | ... | ... |
src/components/oa/editWorkType.vue
| 1 | 1 | <template> |
| 2 | - <el-dialog | |
| 3 | - :title="$t('workType.edit.title')" | |
| 4 | - :visible.sync="visible" | |
| 5 | - width="50%" | |
| 6 | - @close="handleClose" | |
| 7 | - > | |
| 8 | - <el-form ref="form" :model="formData" :rules="rules" label-width="120px"> | |
| 2 | + <el-dialog :title="$t('workType.edit.title')" :visible.sync="visible" width="50%" @close="handleClose"> | |
| 3 | + <el-form ref="form" :model="formData" :rules="rules" label-width="120px" class="text-left"> | |
| 9 | 4 | <el-form-item :label="$t('workType.form.typeName')" prop="typeName"> |
| 10 | - <el-input | |
| 11 | - v-model.trim="formData.typeName" | |
| 12 | - :placeholder="$t('workType.placeholder.typeName')" | |
| 13 | - /> | |
| 5 | + <el-input v-model.trim="formData.typeName" :placeholder="$t('workType.placeholder.typeName')" /> | |
| 14 | 6 | </el-form-item> |
| 15 | - | |
| 7 | + | |
| 16 | 8 | <el-form-item :label="$t('workType.form.deduction')" prop="deduction"> |
| 17 | - <el-select | |
| 18 | - v-model="formData.deduction" | |
| 19 | - :placeholder="$t('workType.placeholder.deduction')" | |
| 20 | - style="width:100%" | |
| 21 | - > | |
| 22 | - <el-option | |
| 23 | - v-for="item in deductionOptions" | |
| 24 | - :key="item.value" | |
| 25 | - :label="item.label" | |
| 26 | - :value="item.value" | |
| 27 | - /> | |
| 9 | + <el-select v-model="formData.deduction" :placeholder="$t('workType.placeholder.deduction')" style="width:100%"> | |
| 10 | + <el-option v-for="item in deductionOptions" :key="item.value" :label="item.label" :value="item.value" /> | |
| 28 | 11 | </el-select> |
| 29 | 12 | <div class="el-form-item__tip" v-if="formData.deduction === 'Y'"> |
| 30 | 13 | {{ $t('workType.tip.deduction') }} |
| ... | ... | @@ -32,29 +15,14 @@ |
| 32 | 15 | </el-form-item> |
| 33 | 16 | |
| 34 | 17 | <el-form-item :label="$t('workType.form.smsWay')" prop="smsWay"> |
| 35 | - <el-select | |
| 36 | - v-model="formData.smsWay" | |
| 37 | - :placeholder="$t('workType.placeholder.smsWay')" | |
| 38 | - style="width:100%" | |
| 39 | - > | |
| 40 | - <el-option | |
| 41 | - v-for="item in smsWayOptions" | |
| 42 | - :key="item.value" | |
| 43 | - :label="item.label" | |
| 44 | - :value="item.value" | |
| 45 | - /> | |
| 18 | + <el-select v-model="formData.smsWay" :placeholder="$t('workType.placeholder.smsWay')" style="width:100%"> | |
| 19 | + <el-option v-for="item in smsWayOptions" :key="item.value" :label="item.label" :value="item.value" /> | |
| 46 | 20 | </el-select> |
| 47 | 21 | </el-form-item> |
| 48 | 22 | |
| 49 | 23 | <el-form-item :label="$t('workType.form.remark')"> |
| 50 | - <el-input | |
| 51 | - v-model.trim="formData.remark" | |
| 52 | - type="textarea" | |
| 53 | - :rows="3" | |
| 54 | - :placeholder="$t('workType.placeholder.remark')" | |
| 55 | - maxlength="500" | |
| 56 | - show-word-limit | |
| 57 | - /> | |
| 24 | + <el-input v-model.trim="formData.remark" type="textarea" :rows="3" | |
| 25 | + :placeholder="$t('workType.placeholder.remark')" maxlength="500" show-word-limit /> | |
| 58 | 26 | </el-form-item> |
| 59 | 27 | </el-form> |
| 60 | 28 | ... | ... |
src/components/oa/newOaWorkflowFinish.vue
| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | <div slot="header" class="flex justify-between"> |
| 5 | 5 | <span>{{ $t('newOaWorkflowFinish.searchTitle') }}</span> |
| 6 | 6 | </div> |
| 7 | - <el-form :inline="true" :model="conditions" class="search-form"> | |
| 7 | + <el-form :inline="true" :model="conditions" class="search-form text-left"> | |
| 8 | 8 | <el-form-item> |
| 9 | 9 | <el-input v-model="conditions.createUserName" :placeholder="$t('newOaWorkflowFinish.enterApplicant')" |
| 10 | 10 | clearable /> | ... | ... |
src/components/oa/newOaWorkflowForm.vue
| 1 | 1 | <template> |
| 2 | 2 | <div class="new-oa-workflow-form"> |
| 3 | 3 | <el-card class="form-card"> |
| 4 | - <div class="form-container" id="form-container"> | |
| 4 | + <el-form ref="form" :model="formData" label-width="120px" label-position="right" class="text-left"> | |
| 5 | + <div v-for="(item, index) in components" :key="index"> | |
| 6 | + <!-- 标题 --> | |
| 7 | + <el-divider v-if="item.type == 'text'" content-position="left"> | |
| 8 | + <span class="form-title">{{ item.text }}</span> | |
| 9 | + </el-divider> | |
| 5 | 10 | |
| 6 | - <div class="upload-wrapper"> | |
| 7 | - <upload-file ref="uploadFile" :call-back-listener="callBackListener" :call-back-function="callBackFunction" /> | |
| 11 | + <!-- 文本框 --> | |
| 12 | + <el-form-item v-if="item.type == 'textfield'" :label="item.label" :prop="item.key" | |
| 13 | + :rules="getValidationRules(item)"> | |
| 14 | + <el-input v-model="item.value" :placeholder="item.description" clearable> | |
| 15 | + </el-input> | |
| 16 | + </el-form-item> | |
| 17 | + | |
| 18 | + <!-- 数字框 --> | |
| 19 | + <el-form-item v-if="item.type == 'number'" :label="item.label" :prop="item.key" | |
| 20 | + :rules="getValidationRules(item)"> | |
| 21 | + <el-input-number v-model="item.value" :placeholder="item.description" :min="0" style="width: 100%"> | |
| 22 | + </el-input-number> | |
| 23 | + </el-form-item> | |
| 24 | + | |
| 25 | + <!-- 文本域 --> | |
| 26 | + <el-form-item v-if="item.type == 'textarea'" :label="item.label" :prop="item.key" | |
| 27 | + :rules="getValidationRules(item)"> | |
| 28 | + <el-input v-model="item.value" type="textarea" :rows="4" :placeholder="item.description"> | |
| 29 | + </el-input> | |
| 30 | + </el-form-item> | |
| 31 | + | |
| 32 | + <!-- 日期选择 --> | |
| 33 | + <el-form-item v-if="item.type == 'textdate'" :label="item.label" :prop="item.key" | |
| 34 | + :rules="getValidationRules(item)"> | |
| 35 | + <el-date-picker v-model="item.value" type="date" :placeholder="item.description" format="yyyy-MM-dd" | |
| 36 | + value-format="yyyy-MM-dd" style="width: 100%"> | |
| 37 | + </el-date-picker> | |
| 38 | + </el-form-item> | |
| 39 | + | |
| 40 | + <!-- 时间选择 --> | |
| 41 | + <el-form-item v-if="item.type == 'textdatetime'" :label="item.label" :prop="item.key" | |
| 42 | + :rules="getValidationRules(item)"> | |
| 43 | + <el-time-picker v-model="item.value" :placeholder="item.description" format="HH:mm" | |
| 44 | + value-format="HH:mm" style="width: 100%"> | |
| 45 | + </el-time-picker> | |
| 46 | + </el-form-item> | |
| 47 | + | |
| 48 | + <!-- 单选框 --> | |
| 49 | + <el-form-item v-if="item.type == 'radio'" :label="item.label" :prop="item.key" | |
| 50 | + :rules="getValidationRules(item)"> | |
| 51 | + <el-radio-group v-model="item.value"> | |
| 52 | + <el-radio v-for="(option, optionIndex) in item.values" :key="optionIndex" :label="option.value"> | |
| 53 | + {{ option.label }} | |
| 54 | + </el-radio> | |
| 55 | + </el-radio-group> | |
| 56 | + </el-form-item> | |
| 57 | + | |
| 58 | + <!-- 下拉选择 --> | |
| 59 | + <el-form-item v-if="item.type == 'select'" :label="item.label" :prop="item.key" | |
| 60 | + :rules="getValidationRules(item)"> | |
| 61 | + <el-select v-model="item.value" :placeholder="item.description" style="width: 100%" clearable> | |
| 62 | + <el-option v-for="(option, optionIndex) in item.values" :key="optionIndex" :label="option.label" | |
| 63 | + :value="option.value"> | |
| 64 | + </el-option> | |
| 65 | + </el-select> | |
| 66 | + </el-form-item> | |
| 67 | + | |
| 68 | + <!-- 复选框 --> | |
| 69 | + <el-form-item v-if="item.type == 'checkbox'" :label="item.label" :prop="item.key" | |
| 70 | + :rules="getValidationRules(item)"> | |
| 71 | + <el-checkbox-group v-model="item.value"> | |
| 72 | + <el-checkbox v-for="(option, optionIndex) in item.values" :key="optionIndex" :label="option.value"> | |
| 73 | + {{ option.label }} | |
| 74 | + </el-checkbox> | |
| 75 | + </el-checkbox-group> | |
| 76 | + </el-form-item> | |
| 77 | + | |
| 78 | + <!-- 文件上传 --> | |
| 79 | + <el-form-item v-if="item.type == 'button' && item.action == 'submit'" :label="$t('common.file')"> | |
| 80 | + <div class="upload-section"> | |
| 81 | + <upload-file ref="uploadFile" @notify="handleFileUpload" /> | |
| 82 | + </div> | |
| 83 | + </el-form-item> | |
| 84 | + | |
| 85 | + <!-- 提交按钮 --> | |
| 86 | + <el-form-item v-if="item.type == 'button' && item.action == 'submit'" class="text-right"> | |
| 87 | + <el-button type="primary" @click="_doSubmit" :loading="submitLoading"> | |
| 88 | + <i class="el-icon-check"></i> | |
| 89 | + {{ item.label }} | |
| 90 | + </el-button> | |
| 91 | + </el-form-item> | |
| 92 | + | |
| 93 | + <!-- 重置按钮 --> | |
| 94 | + <el-form-item v-if="item.type == 'button' && item.action == 'reset'" class="text-right"> | |
| 95 | + <el-button @click="_doReset"> | |
| 96 | + <i class="el-icon-refresh"></i> | |
| 97 | + {{ item.label }} | |
| 98 | + </el-button> | |
| 99 | + </el-form-item> | |
| 8 | 100 | </div> |
| 9 | - </div> | |
| 10 | 101 | |
| 102 | + </el-form> | |
| 11 | 103 | </el-card> |
| 12 | 104 | </div> |
| 13 | 105 | </template> |
| ... | ... | @@ -15,7 +107,6 @@ |
| 15 | 107 | <script> |
| 16 | 108 | import UploadFile from '@/components/upload/uploadFile' |
| 17 | 109 | import { queryOaWorkflowForm, saveOaWorkflowFormData } from '@/api/oa/newOaWorkflowApi' |
| 18 | -//import { Formio } from 'formiojs' | |
| 19 | 110 | |
| 20 | 111 | export default { |
| 21 | 112 | name: 'NewOaWorkflowForm', |
| ... | ... | @@ -24,20 +115,26 @@ export default { |
| 24 | 115 | data() { |
| 25 | 116 | return { |
| 26 | 117 | formJson: {}, |
| 118 | + components: [], | |
| 119 | + formData: {}, | |
| 27 | 120 | fileName: '', |
| 28 | 121 | realFileName: '', |
| 29 | 122 | callBackListener: 'newOaWorkflowForm', |
| 30 | 123 | callBackFunction: 'fileName', |
| 31 | - formViewer: null | |
| 124 | + submitLoading: false, | |
| 125 | + showUploadComponent: false | |
| 32 | 126 | } |
| 33 | 127 | }, |
| 128 | + | |
| 34 | 129 | mounted() { |
| 35 | 130 | }, |
| 131 | + | |
| 36 | 132 | methods: { |
| 37 | 133 | open(params) { |
| 38 | 134 | this.flowId = params.flowId |
| 39 | 135 | this.listOaWorkflowForm() |
| 40 | 136 | }, |
| 137 | + | |
| 41 | 138 | async listOaWorkflowForm() { |
| 42 | 139 | try { |
| 43 | 140 | const res = await queryOaWorkflowForm({ |
| ... | ... | @@ -50,60 +147,109 @@ export default { |
| 50 | 147 | this.initForm() |
| 51 | 148 | } catch (error) { |
| 52 | 149 | console.error('获取表单配置失败:', error) |
| 150 | + this.$message.error('获取表单配置失败') | |
| 53 | 151 | } |
| 54 | 152 | }, |
| 153 | + | |
| 55 | 154 | initForm() { |
| 56 | - const container = document.getElementById('form-container') | |
| 155 | + this.components = this.formJson.components | |
| 156 | + this.formData = {} | |
| 57 | 157 | |
| 58 | - const form = window.FormViewer.createForm({ | |
| 59 | - container, | |
| 60 | - schema: this.formJson | |
| 61 | - }); | |
| 62 | - console.log(form); | |
| 63 | - form.then((_from) => { | |
| 64 | - _from.on('submit', (event) => { | |
| 65 | - this.submitFormData(event.data, event.errors); | |
| 66 | - }) | |
| 67 | - }).then((_from) => { | |
| 68 | - console.log(_from); | |
| 69 | - let node = document.querySelector('.fjs-form .uploadFile'); | |
| 70 | - const submitBtn = document.querySelector('.fjs-form .fjs-form-field-button'); | |
| 71 | - submitBtn.parentNode.insertBefore(node, submitBtn); | |
| 72 | - }); | |
| 158 | + this.components.forEach(item => { | |
| 159 | + if (item.type !== 'button' && item.type !== 'text') { | |
| 160 | + // 初始化表单数据 | |
| 161 | + if (item.type === 'checkbox') { | |
| 162 | + this.formData[item.key] = [] | |
| 163 | + } else if (item.type === 'radio' || item.type === 'select') { | |
| 164 | + this.formData[item.key] = item.values && item.values.length > 0 ? item.values[0].value : '' | |
| 165 | + } else { | |
| 166 | + this.formData[item.key] = '' | |
| 167 | + } | |
| 168 | + } | |
| 169 | + }) | |
| 73 | 170 | }, |
| 74 | - async submitFormData(data, errors) { | |
| 75 | - if (Object.keys(errors).length !== 0) return | |
| 76 | - | |
| 77 | - const formData = { | |
| 78 | - ...data, | |
| 79 | - flowId: this.flowId, | |
| 80 | - fileName: this.fileName, | |
| 81 | - realFileName: this.realFileName | |
| 171 | + | |
| 172 | + getValidationRules(item) { | |
| 173 | + const rules = [] | |
| 174 | + if (item.validate && item.validate.required) { | |
| 175 | + rules.push({ | |
| 176 | + required: true, | |
| 177 | + message: `${item.label}不能为空`, | |
| 178 | + trigger: 'blur' | |
| 179 | + }) | |
| 82 | 180 | } |
| 181 | + return rules | |
| 182 | + }, | |
| 83 | 183 | |
| 184 | + async _doSubmit() { | |
| 84 | 185 | try { |
| 85 | - const res = await saveOaWorkflowFormData(formData) | |
| 186 | + // 表单验证 | |
| 187 | + await this.$refs.form.validate() | |
| 188 | + | |
| 189 | + this.submitLoading = true | |
| 190 | + | |
| 191 | + const _data = { | |
| 192 | + fileName: this.fileName, | |
| 193 | + realFileName: this.realFileName, | |
| 194 | + flowId: this.flowId, | |
| 195 | + ...this.formData | |
| 196 | + } | |
| 197 | + | |
| 198 | + const res = await saveOaWorkflowFormData(_data) | |
| 86 | 199 | if (res.code === 0) { |
| 87 | 200 | this.$message.success(this.$t('common.submitSuccess')) |
| 88 | 201 | this.resetForm() |
| 89 | 202 | this.$emit('switch-tab', 'newOaWorkflowPool') |
| 90 | 203 | } else { |
| 91 | - this.$message.error(res.msg) | |
| 204 | + this.$message.error(res.msg || this.$t('common.submitFailed')) | |
| 92 | 205 | } |
| 93 | 206 | } catch (error) { |
| 207 | + if (error.message) { | |
| 208 | + // 表单验证错误 | |
| 209 | + return | |
| 210 | + } | |
| 94 | 211 | console.error('提交表单失败:', error) |
| 95 | 212 | this.$message.error(this.$t('common.submitFailed')) |
| 213 | + } finally { | |
| 214 | + this.submitLoading = false | |
| 96 | 215 | } |
| 97 | 216 | }, |
| 217 | + | |
| 218 | + _doReset() { | |
| 219 | + let _that = this; | |
| 220 | + _that.components.forEach(item => { | |
| 221 | + item.value = ""; | |
| 222 | + if (item.type == 'textdate' || item.type == 'textdatetime') { | |
| 223 | + item.value = "请选择"; | |
| 224 | + } | |
| 225 | + | |
| 226 | + if (item.type == "radio" || item.type == "select") { | |
| 227 | + item.valueIndex = 0; | |
| 228 | + } | |
| 229 | + }); | |
| 230 | + this.$forceUpdate(); | |
| 231 | + }, | |
| 232 | + | |
| 233 | + _doUploadFile() { | |
| 234 | + this.showUploadComponent = true | |
| 235 | + this.$nextTick(() => { | |
| 236 | + this.$refs.uploadFile.open() | |
| 237 | + }) | |
| 238 | + }, | |
| 239 | + | |
| 98 | 240 | resetForm() { |
| 99 | - if (this.formViewer) { | |
| 100 | - this.formViewer.destroy() | |
| 241 | + this.$refs.form.resetFields() | |
| 242 | + if (this.$refs.uploadFile) { | |
| 243 | + this.$refs.uploadFile.clear() | |
| 101 | 244 | } |
| 102 | - this.$refs.uploadFile.clear() | |
| 103 | 245 | this.fileName = '' |
| 104 | 246 | this.realFileName = '' |
| 105 | 247 | this.formJson = {} |
| 248 | + this.components = [] | |
| 249 | + this.formData = {} | |
| 250 | + this.showUploadComponent = false | |
| 106 | 251 | }, |
| 252 | + | |
| 107 | 253 | handleFileUpload(fileInfo) { |
| 108 | 254 | this.fileName = fileInfo.fileName |
| 109 | 255 | this.realFileName = fileInfo.realFileName |
| ... | ... | @@ -112,103 +258,28 @@ export default { |
| 112 | 258 | } |
| 113 | 259 | </script> |
| 114 | 260 | |
| 115 | -<style lang="scss"> | |
| 261 | +<style lang="scss" scoped> | |
| 116 | 262 | .new-oa-workflow-form { |
| 117 | 263 | .form-card { |
| 118 | - padding: 20px; | |
| 119 | - border-radius: 4px; | |
| 120 | - border: 1px solid #ebeef5; | |
| 121 | - background-color: #fff; | |
| 122 | - box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); | |
| 123 | - | |
| 124 | - .form-container { | |
| 125 | - | |
| 126 | - .upload-wrapper { | |
| 127 | - margin-bottom: 20px; | |
| 128 | - padding: 20px; | |
| 129 | - background-color: #fafafa; | |
| 130 | - border: 1px solid #e4e7ed; | |
| 131 | - border-radius: 4px; | |
| 132 | - } | |
| 264 | + .form-title { | |
| 265 | + font-size: 16px; | |
| 266 | + font-weight: 600; | |
| 267 | + color: #303133; | |
| 133 | 268 | } |
| 134 | - } | |
| 135 | -} | |
| 136 | - | |
| 137 | -// 全局Formio样式覆盖(不使用scoped) | |
| 138 | - | |
| 139 | -// Formio Element UI 风格样式 | |
| 140 | -.formio-form { | |
| 141 | - font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', '微软雅黑', Arial, sans-serif !important; | |
| 142 | - | |
| 143 | - .form-group { | |
| 144 | - margin-bottom: 22px !important; | |
| 145 | - text-align: left !important; | |
| 146 | - } | |
| 147 | - | |
| 148 | - .form-control { | |
| 149 | - border: 1px solid #dcdfe6 !important; | |
| 150 | - border-radius: 4px !important; | |
| 151 | - padding: 0 15px !important; | |
| 152 | - height: 40px !important; | |
| 153 | - line-height: 40px !important; | |
| 154 | - font-size: 14px !important; | |
| 155 | - background: #fff !important; | |
| 156 | - color: #606266 !important; | |
| 157 | - box-sizing: border-box !important; | |
| 158 | - width: 100% !important; | |
| 159 | - transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1) !important; | |
| 160 | - } | |
| 161 | - | |
| 162 | - .form-control:focus { | |
| 163 | - border-color: #409eff !important; | |
| 164 | - outline: none !important; | |
| 165 | - } | |
| 166 | - | |
| 167 | - .form-control:disabled { | |
| 168 | - background: #f5f7fa !important; | |
| 169 | - color: #c0c4cc !important; | |
| 170 | - } | |
| 171 | - | |
| 172 | - .col-form-label { | |
| 173 | - font-weight: 500 !important; | |
| 174 | - color: #606266 !important; | |
| 175 | - font-size: 14px !important; | |
| 176 | - margin-bottom: 8px !important; | |
| 177 | - } | |
| 178 | - | |
| 179 | - .formio-errors { | |
| 180 | - color: #f56c6c !important; | |
| 181 | - font-size: 12px !important; | |
| 182 | - margin-top: 4px !important; | |
| 183 | - } | |
| 184 | 269 | |
| 185 | - button.btn { | |
| 186 | - background-color: #409eff !important; | |
| 187 | - border: 1px solid #409eff !important; | |
| 188 | - border-radius: 4px !important; | |
| 189 | - padding: 12px 20px !important; | |
| 190 | - font-size: 14px !important; | |
| 191 | - font-weight: 500 !important; | |
| 192 | - color: #fff !important; | |
| 193 | - cursor: pointer !important; | |
| 194 | - transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1) !important; | |
| 195 | - } | |
| 196 | - | |
| 197 | - button.btn:hover { | |
| 198 | - background-color: #66b1ff !important; | |
| 199 | - border-color: #66b1ff !important; | |
| 200 | - } | |
| 270 | + .upload-section { | |
| 271 | + .file-info { | |
| 272 | + margin-bottom: 10px; | |
| 273 | + } | |
| 274 | + } | |
| 201 | 275 | |
| 202 | - button.btn:active { | |
| 203 | - background-color: #3a8ee6 !important; | |
| 204 | - border-color: #3a8ee6 !important; | |
| 205 | - } | |
| 276 | + .el-form-item { | |
| 277 | + margin-bottom: 22px; | |
| 278 | + } | |
| 206 | 279 | |
| 207 | - button.btn:disabled { | |
| 208 | - background-color: #c0c4cc !important; | |
| 209 | - border-color: #c0c4cc !important; | |
| 210 | - color: #fff !important; | |
| 211 | - cursor: not-allowed !important; | |
| 280 | + .el-divider { | |
| 281 | + margin: 24px 0; | |
| 282 | + } | |
| 212 | 283 | } |
| 213 | 284 | } |
| 214 | 285 | </style> |
| 215 | 286 | \ No newline at end of file | ... | ... |
src/components/oa/newOaWorkflowUndo.vue
| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | <div slot="header" class="flex justify-between"> |
| 5 | 5 | <span>{{ $t('newOaWorkflowUndo.searchTitle') }}</span> |
| 6 | 6 | </div> |
| 7 | - <el-form :inline="true" :model="conditions" class="search-form"> | |
| 7 | + <el-form :inline="true" :model="conditions" class="search-form text-left"> | |
| 8 | 8 | <el-form-item> |
| 9 | 9 | <el-input v-model="conditions.createUserName" :placeholder="$t('newOaWorkflowUndo.enterApplicant')" |
| 10 | 10 | clearable /> | ... | ... |
src/i18n/commonLang.js
| ... | ... | @@ -58,6 +58,7 @@ export const messages = { |
| 58 | 58 | submitSuccess:'Submit successfully', |
| 59 | 59 | saveSuccess:'successfully', |
| 60 | 60 | noData:'No Data', |
| 61 | + file:'File' | |
| 61 | 62 | } |
| 62 | 63 | }, |
| 63 | 64 | zh: { |
| ... | ... | @@ -119,6 +120,7 @@ export const messages = { |
| 119 | 120 | submitSuccess:'提交成功', |
| 120 | 121 | saveSuccess:'成功', |
| 121 | 122 | noData:'暂无数据', |
| 123 | + file:'附件' | |
| 122 | 124 | } |
| 123 | 125 | } |
| 124 | 126 | } |
| 125 | 127 | \ No newline at end of file | ... | ... |
src/router/index.js
| ... | ... | @@ -63,8 +63,8 @@ const routes = [ |
| 63 | 63 | |
| 64 | 64 | |
| 65 | 65 | { |
| 66 | - path: '/views/staff/staffDetailList', | |
| 67 | - name: '/views/staff/staffDetailList', | |
| 66 | + path: '/views/staff/staffDetail', | |
| 67 | + name: '/views/staff/staffDetail', | |
| 68 | 68 | component: () => import('@/views/staff/staffDetailList.vue') |
| 69 | 69 | }, |
| 70 | 70 | ... | ... |
src/views/oa/addAttendanceClassesStaffList.vue
| 1 | 1 | <template> |
| 2 | 2 | <div class="add-attendance-classes-staff-container"> |
| 3 | 3 | <el-card> |
| 4 | - <div slot="header" class="clearfix"> | |
| 4 | + <div slot="header" class="flex justify-between"> | |
| 5 | 5 | <span>{{ $t('addAttendanceClassesStaff.title') }}</span> |
| 6 | 6 | <el-button type="primary" size="small" class="float-right" @click="handleGoBack"> |
| 7 | 7 | <i class="el-icon-close"></i> | ... | ... |
src/views/oa/addWorkList.vue
| 1 | 1 | <template> |
| 2 | 2 | <div class="add-work-container"> |
| 3 | 3 | <el-card class="box-card"> |
| 4 | - <div slot="header" class="clearfix"> | |
| 4 | + <div slot="header" class="flex justify-between"> | |
| 5 | 5 | <span>{{ $t('addWork.title') }}</span> |
| 6 | 6 | </div> |
| 7 | 7 | |
| 8 | - <el-form ref="form" :model="addWorkInfo" label-width="120px" label-position="right"> | |
| 8 | + <el-form ref="form" :model="addWorkInfo" label-width="120px" label-position="right" class="text-left"> | |
| 9 | 9 | <el-row :gutter="20"> |
| 10 | 10 | <el-col :span="12"> |
| 11 | 11 | <el-form-item :label="$t('addWork.workName')" prop="workName"> |
| ... | ... | @@ -235,10 +235,10 @@ export default { |
| 235 | 235 | methods: { |
| 236 | 236 | initDateTime() { |
| 237 | 237 | const now = new Date() |
| 238 | - this.addWorkInfo.startTime = dateFormat(now) | |
| 238 | + this.addWorkInfo.startTime = dateFormat(now)+' 00:00:00' | |
| 239 | 239 | const tomorrow = new Date(now) |
| 240 | 240 | tomorrow.setDate(tomorrow.getDate() + 1) |
| 241 | - this.addWorkInfo.endTime = dateFormat(tomorrow) | |
| 241 | + this.addWorkInfo.endTime = dateFormat(tomorrow)+' 23:59:59' | |
| 242 | 242 | }, |
| 243 | 243 | addWorkValidate() { |
| 244 | 244 | return this.$refs.form.validate() | ... | ... |
src/views/oa/newOaWorkflowDetailList.vue
| ... | ... | @@ -93,7 +93,7 @@ |
| 93 | 93 | <span>{{ $t('newOaWorkflowDetail.workflowHandle') }}</span> |
| 94 | 94 | </div> |
| 95 | 95 | |
| 96 | - <el-form label-width="120px"> | |
| 96 | + <el-form label-width="120px" class="text-left"> | |
| 97 | 97 | <el-form-item :label="$t('newOaWorkflowDetail.action')"> |
| 98 | 98 | <el-select v-model="newOaWorkflowDetailInfo.audit.auditCode" style="width:100%" |
| 99 | 99 | :placeholder="$t('newOaWorkflowDetail.selectAction')"> |
| ... | ... | @@ -109,7 +109,7 @@ |
| 109 | 109 | </el-select> |
| 110 | 110 | </el-form-item> |
| 111 | 111 | |
| 112 | - <el-form-item :label="$t('newOaWorkflowDetail.workflowDescription')"> | |
| 112 | + <el-form-item :label="$t('newOaWorkflowDetail.workflowDescription')" class="margin-top"> | |
| 113 | 113 | <el-input type="textarea" :rows="3" :placeholder="$t('newOaWorkflowDetail.descriptionRequired')" |
| 114 | 114 | v-model="newOaWorkflowDetailInfo.audit.auditMessage" /> |
| 115 | 115 | </el-form-item> |
| ... | ... | @@ -117,7 +117,7 @@ |
| 117 | 117 | <!-- 办理时 判断是否指定 委托人 如果指定了 则不显示 --> |
| 118 | 118 | <el-form-item |
| 119 | 119 | v-if="newOaWorkflowDetailInfo.audit.auditCode == '1100' && newOaWorkflowDetailInfo.nextAudit.assignee == '-2'" |
| 120 | - :label="$t('newOaWorkflowDetail.nextHandler')"> | |
| 120 | + :label="$t('newOaWorkflowDetail.nextHandler')" class="margin-top"> | |
| 121 | 121 | <el-input v-model="newOaWorkflowDetailInfo.audit.staffName" |
| 122 | 122 | :placeholder="$t('newOaWorkflowDetail.selectNextHandler')" disabled style="width:80%" /> |
| 123 | 123 | <el-button type="primary" @click="chooseStaff" style="margin-left:10px"> |
| ... | ... | @@ -127,7 +127,7 @@ |
| 127 | 127 | |
| 128 | 128 | <!-- 转单时 必须指定 委托人 --> |
| 129 | 129 | <el-form-item v-if="newOaWorkflowDetailInfo.audit.auditCode == '1300'" |
| 130 | - :label="$t('newOaWorkflowDetail.nextHandler')"> | |
| 130 | + :label="$t('newOaWorkflowDetail.nextHandler')" class="margin-top"> | |
| 131 | 131 | <el-input v-model="newOaWorkflowDetailInfo.audit.staffName" |
| 132 | 132 | :placeholder="$t('newOaWorkflowDetail.selectNextHandler')" disabled style="width:80%" /> |
| 133 | 133 | <el-button type="primary" @click="chooseStaff" style="margin-left:10px"> |
| ... | ... | @@ -158,13 +158,14 @@ |
| 158 | 158 | </el-col> |
| 159 | 159 | </el-row> |
| 160 | 160 | |
| 161 | - <select-staff ref="selectStaff" /> | |
| 161 | + <select-staff ref="selectStaff" @selectStaff="handleSelectStaff"/> | |
| 162 | 162 | </div> |
| 163 | 163 | </template> |
| 164 | 164 | |
| 165 | 165 | <script> |
| 166 | 166 | import { getCommunityId } from '@/api/community/communityApi' |
| 167 | -import { queryOaWorkflowForm, queryOaWorkflowFormData, queryOaWorkflowUser, getNextTask, auditOaWorkflow, listRunWorkflowImage } from '@/api/oa/newOaWorkflowDetailApi' | |
| 167 | +import { queryOaWorkflowForm, queryOaWorkflowFormData, queryOaWorkflowUser, | |
| 168 | + getNextTask, auditOaWorkflow, listRunWorkflowImage } from '@/api/oa/newOaWorkflowDetailApi' | |
| 168 | 169 | import SelectStaff from '@/components/staff/SelectStaff' |
| 169 | 170 | |
| 170 | 171 | export default { |
| ... | ... | @@ -253,7 +254,7 @@ export default { |
| 253 | 254 | row: 10 |
| 254 | 255 | } |
| 255 | 256 | const response = await queryOaWorkflowUser(params) |
| 256 | - if (response.code !== '0') return | |
| 257 | + if (response.code !== 0) return | |
| 257 | 258 | this.newOaWorkflowDetailInfo.comments = response.data |
| 258 | 259 | } catch (error) { |
| 259 | 260 | console.error('请求失败:', error) |
| ... | ... | @@ -265,6 +266,10 @@ export default { |
| 265 | 266 | chooseStaff() { |
| 266 | 267 | this.$refs.selectStaff.open(this.newOaWorkflowDetailInfo.audit) |
| 267 | 268 | }, |
| 269 | + handleSelectStaff(staff) { | |
| 270 | + this.newOaWorkflowDetailInfo.audit.staffId = staff.userId | |
| 271 | + this.newOaWorkflowDetailInfo.audit.staffName = staff.userName | |
| 272 | + }, | |
| 268 | 273 | async _auditSubmit() { |
| 269 | 274 | const audit = this.newOaWorkflowDetailInfo.audit |
| 270 | 275 | audit.flowId = this.newOaWorkflowDetailInfo.flowId |
| ... | ... | @@ -336,7 +341,7 @@ export default { |
| 336 | 341 | businessKey: this.newOaWorkflowDetailInfo.id |
| 337 | 342 | } |
| 338 | 343 | const response = await listRunWorkflowImage(params) |
| 339 | - if (response.code !== '0') return | |
| 344 | + if (response.code !== 0) return | |
| 340 | 345 | this.newOaWorkflowDetailInfo.imgData = 'data:image/png;base64,' + response.data |
| 341 | 346 | } catch (error) { |
| 342 | 347 | console.error('请求失败:', error) | ... | ... |
src/views/oa/newOaWorkflowDoingList.vue
| ... | ... | @@ -83,26 +83,26 @@ export default { |
| 83 | 83 | ownerSettledApplyCount: 0 |
| 84 | 84 | }, |
| 85 | 85 | pendingItems: [ |
| 86 | - { key: 'repairPending', url: '/#/pages/property/repairDispatchManage', count: 0 }, | |
| 87 | - { key: 'complaintPending', url: '/#/pages/complaint/uodoComplaints', count: 0 }, | |
| 88 | - { key: 'purchasePending', url: '/#/pages/admin/myAuditOrders', count: 0 }, | |
| 89 | - { key: 'collectionPending', url: '/#/pages/admin/myItemOutAuditOrders', count: 0 }, | |
| 90 | - { key: 'contractApplyPending', url: '/#/pages/admin/contractApplyAuditOrders', count: 0 }, | |
| 91 | - { key: 'contractChangePending', url: '/#/pages/admin/contractChangeAuditOrders', count: 0 }, | |
| 92 | - { key: 'allocationPending', url: '/#/pages/admin/allocationStorehouseAuditOrders', count: 0 }, | |
| 93 | - { key: 'itemReleasePending', url: '/#/pages/property/itemReleaseUndo', count: 0 }, | |
| 94 | - { key: 'visitPending', url: '/#/pages/property/visitUndo', count: 0 } | |
| 86 | + { key: 'repairPending', url: '/pages/property/repairDispatchManage', count: 0 }, | |
| 87 | + { key: 'complaintPending', url: '/pages/complaint/uodoComplaints', count: 0 }, | |
| 88 | + { key: 'purchasePending', url: '/pages/admin/myAuditOrders', count: 0 }, | |
| 89 | + { key: 'collectionPending', url: '/pages/admin/myItemOutAuditOrders', count: 0 }, | |
| 90 | + { key: 'contractApplyPending', url: '/pages/admin/contractApplyAuditOrders', count: 0 }, | |
| 91 | + { key: 'contractChangePending', url: '/pages/admin/contractChangeAuditOrders', count: 0 }, | |
| 92 | + { key: 'allocationPending', url: '/pages/admin/allocationStorehouseAuditOrders', count: 0 }, | |
| 93 | + { key: 'itemReleasePending', url: '/pages/property/itemReleaseUndo', count: 0 }, | |
| 94 | + { key: 'visitPending', url: '/pages/property/visitUndo', count: 0 } | |
| 95 | 95 | ], |
| 96 | 96 | completedItems: [ |
| 97 | - { key: 'repairCompleted', url: '/#/pages/property/myRepairDispatchManage' }, | |
| 98 | - { key: 'complaintCompleted', url: '/#/pages/complaint/doHistoryComplaints' }, | |
| 99 | - { key: 'purchaseCompleted', url: '/#/pages/admin/myAuditHistoryOrders' }, | |
| 100 | - { key: 'collectionCompleted', url: '/#/pages/admin/myItemOutAuditHistoryOrders' }, | |
| 101 | - { key: 'contractApplyCompleted', url: '/#/pages/admin/contractApplyAuditHistoryOrders' }, | |
| 102 | - { key: 'contractChangeCompleted', url: '/#/pages/admin/contractChangeAuditHistoryOrders' }, | |
| 103 | - { key: 'allocationCompleted', url: '/#/pages/admin/allocationStorehouseHistoryAuditOrders' }, | |
| 104 | - { key: 'itemReleaseCompleted', url: '/#/pages/property/itemReleaseFinish' }, | |
| 105 | - { key: 'visitCompleted', url: '/#/pages/property/visitFinish' } | |
| 97 | + { key: 'repairCompleted', url: '/pages/property/myRepairDispatchManage' }, | |
| 98 | + { key: 'complaintCompleted', url: '/pages/complaint/doHistoryComplaints' }, | |
| 99 | + { key: 'purchaseCompleted', url: '/pages/admin/myAuditHistoryOrders' }, | |
| 100 | + { key: 'collectionCompleted', url: '/pages/admin/myItemOutAuditHistoryOrders' }, | |
| 101 | + { key: 'contractApplyCompleted', url: '/pages/admin/contractApplyAuditHistoryOrders' }, | |
| 102 | + { key: 'contractChangeCompleted', url: '/pages/admin/contractChangeAuditHistoryOrders' }, | |
| 103 | + { key: 'allocationCompleted', url: '/pages/admin/allocationStorehouseHistoryAuditOrders' }, | |
| 104 | + { key: 'itemReleaseCompleted', url: '/pages/property/itemReleaseFinish' }, | |
| 105 | + { key: 'visitCompleted', url: '/pages/property/visitFinish' } | |
| 106 | 106 | ], |
| 107 | 107 | communityId: '' |
| 108 | 108 | } | ... | ... |
src/views/oa/newOaWorkflowFormEditList.vue
| ... | ... | @@ -4,50 +4,97 @@ |
| 4 | 4 | <div slot="header" class="flex justify-between"> |
| 5 | 5 | <span>{{ $t('newOaWorkflowFormEdit.title') }}</span> |
| 6 | 6 | </div> |
| 7 | - <el-form> | |
| 7 | + <el-form ref="form" :model="formData" class="text-left" label-width="120px"> | |
| 8 | 8 | <el-row :gutter="20"> |
| 9 | 9 | <el-col :span="24"> |
| 10 | 10 | <div v-for="(item, index) in newOaWorkflowFormEditInfo.components" :key="index"> |
| 11 | + <!-- 文本框 --> | |
| 11 | 12 | <el-form-item v-if="item.type === 'textfield'" :label="item.label" |
| 12 | - :prop="'components.' + index + '.value'" | |
| 13 | - :rules="[{ required: item.validate && item.validate.required, message: $t('newOaWorkflowFormEdit.requiredMessage') }]"> | |
| 14 | - <el-input v-model="item.value" :placeholder="item.description" clearable /> | |
| 13 | + :prop="item.key" | |
| 14 | + :rules="getValidationRules(item)"> | |
| 15 | + <el-input v-model="formData[item.key]" :placeholder="item.description" clearable /> | |
| 15 | 16 | </el-form-item> |
| 16 | 17 | |
| 17 | - <el-form-item v-if="item.type === 'number'" :label="item.label" :prop="'components.' + index + '.value'"> | |
| 18 | - <el-input-number v-model="item.value" :placeholder="item.description" controls-position="right" /> | |
| 18 | + <!-- 数字框 --> | |
| 19 | + <el-form-item v-if="item.type === 'number'" :label="item.label" | |
| 20 | + :prop="item.key" | |
| 21 | + :rules="getValidationRules(item)"> | |
| 22 | + <el-input-number v-model="formData[item.key]" :placeholder="item.description" | |
| 23 | + controls-position="right" style="width: 100%" /> | |
| 19 | 24 | </el-form-item> |
| 20 | 25 | |
| 26 | + <!-- 文本域 --> | |
| 21 | 27 | <el-form-item v-if="item.type === 'textarea'" :label="item.label" |
| 22 | - :prop="'components.' + index + '.value'"> | |
| 23 | - <el-input v-model="item.value" type="textarea" :placeholder="item.description" :rows="4" /> | |
| 28 | + :prop="item.key" | |
| 29 | + :rules="getValidationRules(item)"> | |
| 30 | + <el-input v-model="formData[item.key]" type="textarea" :placeholder="item.description" | |
| 31 | + :rows="4" /> | |
| 24 | 32 | </el-form-item> |
| 25 | 33 | |
| 34 | + <!-- 日期选择 --> | |
| 26 | 35 | <el-form-item v-if="item.type === 'textdate'" :label="item.label" |
| 27 | - :prop="'components.' + index + '.value'"> | |
| 28 | - <el-date-picker v-model="item.value" type="date" :placeholder="item.description" | |
| 29 | - value-format="yyyy-MM-dd" /> | |
| 36 | + :prop="item.key" | |
| 37 | + :rules="getValidationRules(item)"> | |
| 38 | + <el-date-picker v-model="formData[item.key]" type="date" :placeholder="item.description" | |
| 39 | + value-format="yyyy-MM-dd" style="width: 100%" /> | |
| 30 | 40 | </el-form-item> |
| 31 | 41 | |
| 42 | + <!-- 日期时间选择 --> | |
| 32 | 43 | <el-form-item v-if="item.type === 'textdatetime'" :label="item.label" |
| 33 | - :prop="'components.' + index + '.value'"> | |
| 34 | - <el-date-picker v-model="item.value" type="datetime" :placeholder="item.description" | |
| 35 | - value-format="yyyy-MM-dd HH:mm:ss" /> | |
| 44 | + :prop="item.key" | |
| 45 | + :rules="getValidationRules(item)"> | |
| 46 | + <el-date-picker v-model="formData[item.key]" type="datetime" :placeholder="item.description" | |
| 47 | + value-format="yyyy-MM-dd HH:mm:ss" style="width: 100%" /> | |
| 36 | 48 | </el-form-item> |
| 37 | 49 | |
| 50 | + <!-- 单选框 --> | |
| 51 | + <el-form-item v-if="item.type === 'radio'" :label="item.label" | |
| 52 | + :prop="item.key" | |
| 53 | + :rules="getValidationRules(item)"> | |
| 54 | + <el-radio-group v-model="formData[item.key]"> | |
| 55 | + <el-radio v-for="(option, optionIndex) in item.values" :key="optionIndex" | |
| 56 | + :label="option.value"> | |
| 57 | + {{ option.label }} | |
| 58 | + </el-radio> | |
| 59 | + </el-radio-group> | |
| 60 | + </el-form-item> | |
| 61 | + | |
| 62 | + <!-- 下拉选择 --> | |
| 63 | + <el-form-item v-if="item.type === 'select'" :label="item.label" | |
| 64 | + :prop="item.key" | |
| 65 | + :rules="getValidationRules(item)"> | |
| 66 | + <el-select v-model="formData[item.key]" :placeholder="item.description" | |
| 67 | + style="width: 100%" clearable> | |
| 68 | + <el-option v-for="(option, optionIndex) in item.values" :key="optionIndex" | |
| 69 | + :label="option.label" :value="option.value"> | |
| 70 | + </el-option> | |
| 71 | + </el-select> | |
| 72 | + </el-form-item> | |
| 73 | + | |
| 74 | + <!-- 复选框 - 修复数组类型问题 --> | |
| 38 | 75 | <el-form-item v-if="item.type === 'checkbox'" :label="item.label" |
| 39 | - :prop="'components.' + index + '.value'"> | |
| 40 | - <el-checkbox-group v-model="item.value"> | |
| 41 | - <el-checkbox :label="item.value">{{ item.label }}</el-checkbox> | |
| 76 | + :prop="item.key" | |
| 77 | + :rules="getValidationRules(item)"> | |
| 78 | + <el-checkbox-group v-model="formData[item.key]"> | |
| 79 | + <el-checkbox v-for="(option, optionIndex) in item.values" :key="optionIndex" | |
| 80 | + :label="option.value"> | |
| 81 | + {{ option.label }} | |
| 82 | + </el-checkbox> | |
| 42 | 83 | </el-checkbox-group> |
| 43 | 84 | </el-form-item> |
| 44 | 85 | </div> |
| 45 | 86 | |
| 46 | - <upload-file ref="uploadFile" :call-back-listener="'newOaWorkflowFormEdit'" | |
| 47 | - :call-back-function="'fileName'" /> | |
| 87 | + <!-- 文件上传 --> | |
| 88 | + <el-form-item :label="$t('common.file')"> | |
| 89 | + <div class="file-info" v-if="newOaWorkflowFormEditInfo.fileName"> | |
| 90 | + <el-tag type="info">{{ newOaWorkflowFormEditInfo.fileName }}</el-tag> | |
| 91 | + </div> | |
| 92 | + <upload-file ref="uploadFile" @notify="handleFileUpload" /> | |
| 93 | + </el-form-item> | |
| 48 | 94 | |
| 95 | + <!-- 按钮区域 --> | |
| 49 | 96 | <div class="form-footer"> |
| 50 | - <el-button type="primary" @click="_submitFormData"> | |
| 97 | + <el-button type="primary" @click="_submitFormData" :loading="submitLoading"> | |
| 51 | 98 | <i class="el-icon-check"></i> |
| 52 | 99 | {{ $t('newOaWorkflowFormEdit.submit') }} |
| 53 | 100 | </el-button> |
| ... | ... | @@ -64,7 +111,7 @@ |
| 64 | 111 | |
| 65 | 112 | <script> |
| 66 | 113 | import { queryOaWorkflowForm, queryOaWorkflowFormData, updateOaWorkflowFormData } from '@/api/oa/newOaWorkflowFormEditApi' |
| 67 | -import UploadFile from '@/components/oa/uploadFile' | |
| 114 | +import UploadFile from '@/components/upload/uploadFile' | |
| 68 | 115 | |
| 69 | 116 | export default { |
| 70 | 117 | name: 'NewOaWorkflowFormEditList', |
| ... | ... | @@ -81,7 +128,9 @@ export default { |
| 81 | 128 | id: '', |
| 82 | 129 | fileName: '', |
| 83 | 130 | realFileName: '' |
| 84 | - } | |
| 131 | + }, | |
| 132 | + formData: {}, // 新增:用于表单数据绑定 | |
| 133 | + submitLoading: false | |
| 85 | 134 | } |
| 86 | 135 | }, |
| 87 | 136 | created() { |
| ... | ... | @@ -102,11 +151,34 @@ export default { |
| 102 | 151 | const formData = JSON.parse(data[0].formJson) |
| 103 | 152 | this.newOaWorkflowFormEditInfo.formJson = formData |
| 104 | 153 | this.newOaWorkflowFormEditInfo.components = formData.components |
| 154 | + | |
| 155 | + // 初始化表单数据 | |
| 156 | + this.initFormData() | |
| 157 | + | |
| 105 | 158 | this._listOaWorkflowDetails() |
| 106 | 159 | } catch (error) { |
| 107 | 160 | console.error('获取表单数据失败:', error) |
| 161 | + this.$message.error('获取表单数据失败') | |
| 108 | 162 | } |
| 109 | 163 | }, |
| 164 | + | |
| 165 | + initFormData() { | |
| 166 | + // 初始化表单数据对象 | |
| 167 | + this.formData = {} | |
| 168 | + this.newOaWorkflowFormEditInfo.components.forEach(item => { | |
| 169 | + if (item.type !== 'button' && item.type !== 'text') { | |
| 170 | + if (item.type === 'checkbox') { | |
| 171 | + // 确保复选框的值是数组类型 | |
| 172 | + this.$set(this.formData, item.key, []) | |
| 173 | + } else if (item.type === 'radio' || item.type === 'select') { | |
| 174 | + this.$set(this.formData, item.key, item.values && item.values.length > 0 ? item.values[0].value : '') | |
| 175 | + } else { | |
| 176 | + this.$set(this.formData, item.key, '') | |
| 177 | + } | |
| 178 | + } | |
| 179 | + }) | |
| 180 | + }, | |
| 181 | + | |
| 110 | 182 | async _listOaWorkflowDetails() { |
| 111 | 183 | try { |
| 112 | 184 | const params = { |
| ... | ... | @@ -119,39 +191,80 @@ export default { |
| 119 | 191 | const { data } = await queryOaWorkflowFormData(params) |
| 120 | 192 | const detailData = data[0] |
| 121 | 193 | |
| 194 | + // 更新表单数据 | |
| 122 | 195 | this.newOaWorkflowFormEditInfo.components.forEach(item => { |
| 123 | - item.value = detailData[item.key] | |
| 196 | + if (item.type !== 'button' && item.type !== 'text') { | |
| 197 | + const value = detailData[item.key] | |
| 198 | + if (value !== undefined && value !== null) { | |
| 199 | + if (item.type === 'checkbox') { | |
| 200 | + // 确保复选框数据是数组类型 | |
| 201 | + if (Array.isArray(value)) { | |
| 202 | + this.$set(this.formData, item.key, value) | |
| 203 | + } else if (typeof value === 'string' && value) { | |
| 204 | + // 如果是字符串,转换为数组 | |
| 205 | + this.$set(this.formData, item.key, [value]) | |
| 206 | + } else { | |
| 207 | + this.$set(this.formData, item.key, []) | |
| 208 | + } | |
| 209 | + } else { | |
| 210 | + this.$set(this.formData, item.key, value) | |
| 211 | + } | |
| 212 | + } | |
| 213 | + } | |
| 124 | 214 | }) |
| 125 | 215 | |
| 126 | - if (detailData.files) { | |
| 216 | + // 处理文件数据 | |
| 217 | + if (detailData.files && detailData.files.length > 0) { | |
| 127 | 218 | this.newOaWorkflowFormEditInfo.fileName = detailData.files[0].fileName |
| 128 | 219 | this.newOaWorkflowFormEditInfo.realFileName = detailData.files[0].realFileName |
| 129 | - this.$refs.uploadFile.notifyVedio(detailData.files[0].fileName) | |
| 220 | + this.$nextTick(() => { | |
| 221 | + if (this.$refs.uploadFile) { | |
| 222 | + this.$refs.uploadFile.notifyVedio(detailData.files[0].fileName) | |
| 223 | + } | |
| 224 | + }) | |
| 130 | 225 | } |
| 131 | 226 | } catch (error) { |
| 132 | 227 | console.error('获取表单详情失败:', error) |
| 228 | + this.$message.error('获取表单详情失败') | |
| 133 | 229 | } |
| 134 | 230 | }, |
| 231 | + | |
| 232 | + getValidationRules(item) { | |
| 233 | + const rules = [] | |
| 234 | + if (item.validate && item.validate.required) { | |
| 235 | + rules.push({ | |
| 236 | + required: true, | |
| 237 | + message: `${item.label}不能为空`, | |
| 238 | + trigger: 'blur' | |
| 239 | + }) | |
| 240 | + } | |
| 241 | + return rules | |
| 242 | + }, | |
| 243 | + | |
| 135 | 244 | async _submitFormData() { |
| 136 | 245 | try { |
| 137 | - const components = this.newOaWorkflowFormEditInfo.components | |
| 246 | + // 表单验证 | |
| 247 | + await this.$refs.form.validate() | |
| 248 | + | |
| 249 | + this.submitLoading = true | |
| 250 | + | |
| 138 | 251 | const formData = { |
| 139 | 252 | id: this.newOaWorkflowFormEditInfo.id, |
| 140 | 253 | flowId: this.newOaWorkflowFormEditInfo.flowId, |
| 141 | 254 | fileName: this.newOaWorkflowFormEditInfo.fileName, |
| 142 | - realFileName: this.newOaWorkflowFormEditInfo.realFileName | |
| 255 | + realFileName: this.newOaWorkflowFormEditInfo.realFileName, | |
| 256 | + | |
| 143 | 257 | } |
| 144 | 258 | |
| 145 | - components.forEach(item => { | |
| 146 | - if (item.validate && item.validate.required && !item.value) { | |
| 147 | - this.$message.error(item.label + this.$t('newOaWorkflowFormEdit.requiredMessage')) | |
| 148 | - throw new Error(item.label + this.$t('newOaWorkflowFormEdit.requiredMessage')) | |
| 149 | - } | |
| 150 | - | |
| 259 | + // 收集表单数据 | |
| 260 | + this.newOaWorkflowFormEditInfo.components.forEach(item => { | |
| 151 | 261 | if (item.type !== 'button' && item.type !== 'text') { |
| 152 | - formData[item.key] = item.value | |
| 262 | + formData[item.key] = this.formData[item.key] | |
| 153 | 263 | if (item.type === 'checkbox') { |
| 154 | - formData[item.key] = item.value.length > 0 ? item.value[0] : '' | |
| 264 | + // 复选框提交时取第一个值或空字符串 | |
| 265 | + formData[item.key] = this.formData[item.key] && this.formData[item.key].length > 0 | |
| 266 | + ? this.formData[item.key][0] | |
| 267 | + : '' | |
| 155 | 268 | } |
| 156 | 269 | } |
| 157 | 270 | }) |
| ... | ... | @@ -161,15 +274,27 @@ export default { |
| 161 | 274 | this.$message.success(this.$t('newOaWorkflowFormEdit.submitSuccess')) |
| 162 | 275 | this.closeEditInfo() |
| 163 | 276 | } else { |
| 164 | - this.$message.error(res.msg) | |
| 277 | + this.$message.error(res.msg || this.$t('newOaWorkflowFormEdit.submitError')) | |
| 165 | 278 | } |
| 166 | 279 | } catch (error) { |
| 280 | + if (error.message) { | |
| 281 | + // 表单验证错误 | |
| 282 | + return | |
| 283 | + } | |
| 167 | 284 | console.error('提交表单失败:', error) |
| 168 | 285 | this.$message.error(this.$t('newOaWorkflowFormEdit.submitError')) |
| 286 | + } finally { | |
| 287 | + this.submitLoading = false | |
| 169 | 288 | } |
| 170 | 289 | }, |
| 290 | + | |
| 171 | 291 | closeEditInfo() { |
| 172 | 292 | this.$router.go(-1) |
| 293 | + }, | |
| 294 | + | |
| 295 | + handleFileUpload(data) { | |
| 296 | + this.newOaWorkflowFormEditInfo.fileName = data.fileName | |
| 297 | + this.newOaWorkflowFormEditInfo.realFileName = data.realFileName | |
| 173 | 298 | } |
| 174 | 299 | } |
| 175 | 300 | } |
| ... | ... | @@ -191,5 +316,9 @@ export default { |
| 191 | 316 | .el-form-item { |
| 192 | 317 | margin-bottom: 22px; |
| 193 | 318 | } |
| 319 | + | |
| 320 | + .file-info { | |
| 321 | + margin-bottom: 10px; | |
| 322 | + } | |
| 194 | 323 | } |
| 195 | 324 | </style> |
| 196 | 325 | \ No newline at end of file | ... | ... |
src/views/oa/newOaWorkflowList.vue
| ... | ... | @@ -23,7 +23,7 @@ |
| 23 | 23 | <el-col :span="20"> |
| 24 | 24 | <div class="content-wrapper"> |
| 25 | 25 | <new-oa-workflow-pool v-show="activeTab === 'newOaWorkflowPool'" ref="newOaWorkflowPool" /> |
| 26 | - <new-oa-workflow-form v-if="activeTab === 'newOaWorkflowForm'" ref="newOaWorkflowForm" /> | |
| 26 | + <new-oa-workflow-form v-if="activeTab === 'newOaWorkflowForm'" ref="newOaWorkflowForm" @switch-tab="switchTab"/> | |
| 27 | 27 | <new-oa-workflow-undo v-show="activeTab === 'newOaWorkflowUndo'" ref="newOaWorkflowUndo" /> |
| 28 | 28 | <new-oa-workflow-finish v-show="activeTab === 'newOaWorkflowFinish'" ref="newOaWorkflowFinish" /> |
| 29 | 29 | </div> | ... | ... |
src/views/oa/startWorkList.vue
| 1 | 1 | <template> |
| 2 | 2 | <div class="start-work-container"> |
| 3 | 3 | <el-row :gutter="20"> |
| 4 | - <el-col :span="2"> | |
| 4 | + <el-col :span="3"> | |
| 5 | 5 | <div class="state-sidebar"> |
| 6 | 6 | <ul class="state-list"> |
| 7 | 7 | <li v-for="(item, index) in states" :key="index" class="state-item" |
| ... | ... | @@ -11,12 +11,12 @@ |
| 11 | 11 | </ul> |
| 12 | 12 | </div> |
| 13 | 13 | </el-col> |
| 14 | - <el-col :span="22"> | |
| 14 | + <el-col :span="21"> | |
| 15 | 15 | <el-card class="search-card"> |
| 16 | 16 | <div slot="header" class="flex justify-between"> |
| 17 | 17 | <span>{{ $t('startWork.search.title') }}</span> |
| 18 | 18 | </div> |
| 19 | - <el-form :inline="true" :model="conditions" class="search-form"> | |
| 19 | + <el-form :inline="true" :model="conditions" class="search-form text-left"> | |
| 20 | 20 | <el-form-item> |
| 21 | 21 | <el-input v-model="conditions.workName" :placeholder="$t('startWork.search.workName')" clearable /> |
| 22 | 22 | </el-form-item> | ... | ... |
src/views/oa/workTypeList.vue
| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | <el-col :span="6"> |
| 10 | 10 | <el-input v-model.trim="searchForm.typeName" :placeholder="$t('workType.search.typeName')" clearable /> |
| 11 | 11 | </el-col> |
| 12 | - <el-col :span="18" style="margin-top:5px;"> | |
| 12 | + <el-col :span="6" > | |
| 13 | 13 | <el-button type="primary" @click="handleSearch"> |
| 14 | 14 | <i class="el-icon-search"></i> |
| 15 | 15 | {{ $t('common.search') }} | ... | ... |
src/views/org/orgList.vue
| ... | ... | @@ -122,7 +122,7 @@ export default { |
| 122 | 122 | this.$refs.deleteOrgRelStaff.open(staff); |
| 123 | 123 | }, |
| 124 | 124 | toStaffDetail(staff) { |
| 125 | - this.$router.push(`/views/staff/staffDetailList?staffId=${staff.userId}`) | |
| 125 | + this.$router.push(`/views/staff/staffDetail?staffId=${staff.userId}`) | |
| 126 | 126 | |
| 127 | 127 | }, |
| 128 | 128 | handlePageChange(page) { | ... | ... |
src/views/resource/addItemOutList.vue
| ... | ... | @@ -69,35 +69,43 @@ |
| 69 | 69 | <table class="custom-table"> |
| 70 | 70 | <thead> |
| 71 | 71 | <tr> |
| 72 | - <th style="text-align: center; padding: 12px 8px; border: 1px solid #ebeef5; background-color: #fafafa;"> | |
| 72 | + <th | |
| 73 | + style="text-align: center; padding: 12px 8px; border: 1px solid #ebeef5; background-color: #fafafa;"> | |
| 73 | 74 | {{ $t('addItemOut.itemType') }} |
| 74 | 75 | </th> |
| 75 | - <th style="text-align: center; padding: 12px 8px; border: 1px solid #ebeef5; background-color: #fafafa;"> | |
| 76 | + <th | |
| 77 | + style="text-align: center; padding: 12px 8px; border: 1px solid #ebeef5; background-color: #fafafa;"> | |
| 76 | 78 | {{ $t('addItemOut.itemName') }} |
| 77 | 79 | </th> |
| 78 | - <th style="text-align: center; padding: 12px 8px; border: 1px solid #ebeef5; background-color: #fafafa;"> | |
| 80 | + <th | |
| 81 | + style="text-align: center; padding: 12px 8px; border: 1px solid #ebeef5; background-color: #fafafa;"> | |
| 79 | 82 | {{ $t('addItemOut.itemSpec') }} |
| 80 | 83 | </th> |
| 81 | - <th style="text-align: center; padding: 12px 8px; border: 1px solid #ebeef5; background-color: #fafafa;"> | |
| 84 | + <th | |
| 85 | + style="text-align: center; padding: 12px 8px; border: 1px solid #ebeef5; background-color: #fafafa;"> | |
| 82 | 86 | {{ $t('addItemOut.price') }} |
| 83 | 87 | </th> |
| 84 | - <th style="text-align: center; padding: 12px 8px; border: 1px solid #ebeef5; background-color: #fafafa;"> | |
| 88 | + <th | |
| 89 | + style="text-align: center; padding: 12px 8px; border: 1px solid #ebeef5; background-color: #fafafa;"> | |
| 85 | 90 | {{ $t('addItemOut.stock') }} |
| 86 | 91 | </th> |
| 87 | - <th style="text-align: center; padding: 12px 8px; border: 1px solid #ebeef5; background-color: #fafafa;"> | |
| 92 | + <th | |
| 93 | + style="text-align: center; padding: 12px 8px; border: 1px solid #ebeef5; background-color: #fafafa;"> | |
| 88 | 94 | {{ $t('addItemOut.applyQuantity') }} |
| 89 | 95 | </th> |
| 90 | - <th style="text-align: center; padding: 12px 8px; border: 1px solid #ebeef5; background-color: #fafafa;"> | |
| 96 | + <th | |
| 97 | + style="text-align: center; padding: 12px 8px; border: 1px solid #ebeef5; background-color: #fafafa;"> | |
| 91 | 98 | {{ $t('addItemOut.remark') }} |
| 92 | 99 | </th> |
| 93 | - <th style="text-align: center; padding: 12px 8px; border: 1px solid #ebeef5; background-color: #fafafa;"> | |
| 100 | + <th | |
| 101 | + style="text-align: center; padding: 12px 8px; border: 1px solid #ebeef5; background-color: #fafafa;"> | |
| 94 | 102 | {{ $t('addItemOut.operation') }} |
| 95 | 103 | </th> |
| 96 | 104 | </tr> |
| 97 | 105 | </thead> |
| 98 | 106 | <tbody> |
| 99 | - <tr v-for="(item, index) in addItemOutInfo.resourceStores" :key="index" | |
| 100 | - style="border-bottom: 1px solid #ebeef5;"> | |
| 107 | + <tr v-for="(item, index) in addItemOutInfo.resourceStores" :key="index" | |
| 108 | + style="border-bottom: 1px solid #ebeef5;"> | |
| 101 | 109 | <td style="text-align: center; padding: 12px 8px; border: 1px solid #ebeef5;"> |
| 102 | 110 | {{ item.parentRstName || '-' }} > {{ item.rstName || '-' }} |
| 103 | 111 | </td> |
| ... | ... | @@ -159,8 +167,8 @@ |
| 159 | 167 | <el-form-item :label="$t('addItemOut.approver')"> |
| 160 | 168 | <el-row :gutter="20"> |
| 161 | 169 | <el-col :span="18"> |
| 162 | - <el-input :placeholder="$t('addItemOut.approverPlaceholder')" v-model="addItemOutInfo.audit.staffName" | |
| 163 | - disabled></el-input> | |
| 170 | + <el-input :placeholder="$t('addItemOut.approverPlaceholder')" | |
| 171 | + v-model="addItemOutInfo.audit.staffName" disabled></el-input> | |
| 164 | 172 | </el-col> |
| 165 | 173 | <el-col :span="6"> |
| 166 | 174 | <el-button type="primary" @click="chooseStaff"> | ... | ... |
src/views/staff/staffList.vue
| ... | ... | @@ -230,7 +230,7 @@ export default { |
| 230 | 230 | this.resetPwdVisible = true |
| 231 | 231 | }, |
| 232 | 232 | openStaffDetail(staff) { |
| 233 | - this.$router.push(`/views/staff/staffDetailList?staffId=${staff.userId}`) | |
| 233 | + this.$router.push(`/views/staff/staffDetail?staffId=${staff.userId}`) | |
| 234 | 234 | }, |
| 235 | 235 | handleSuccess() { |
| 236 | 236 | this.loadData(this.page.current, this.page.size) | ... | ... |