SpringBoot+Vue


一、任務要求

  1. 對多張表增刪改查 (數據表字段類型包括字符、數值、時間)
  2. Controller、Dao、 Service 分層
  3. 代碼及命名規范
  4. 頁面展示使用多種形式(radio 、checkbox 、下拉框、日期選擇等)
  5. 多種條件查詢( 文本框、radio 、checkbox 、下拉框、日期選擇等 ),多種匹配模式(精確匹配、模糊匹配、范圍匹配等)
  6. 查詢分頁
  7. 前台JS 控制
  8. 前、后台校驗
  9. 查詢頁面,包括顯示列的字典翻譯、URL、查詢條件的字典、字典級聯。
  10. 表單頁面,包括字段的字典、字典級聯、字典過濾、自動帶值、操作校驗等。

二、頁面搭建

Ant Design Vue【任務要求使用

三、曲折過程

1、ant-design-vue的button失效

問題所在:float:left

解決:加個 z-index: 99;

<style>
.editable-add-btn {
    margin-bottom: 8px;
    float: left;
    z-index: 99;
}
</style>

2、跨域問題

解決方案:

1、前端vue設置全局參數withCredentials : true

2、后端相關Controller添加跨域注解@CrossOrigin

3、后端新建CorsConfig類,繼承WebMvcConfigurerAdapter,並重寫addCorsMappings方法

@Configuration
@EnableWebMvc
public class CorsConfig implements WebMvcConfigurer {
 
    public void addCorsMappings(CorsRegistry registry) {
        //設置允許跨域的路徑
        registry.addMapping("/**")
                //設置允許跨域請求的域名
                .allowedOrigins("*")
                //這里:是否允許證書 不再默認開啟
                .allowCredentials(true)
                //設置允許的方法
                .allowedMethods("*")
                //跨域允許時間
                .maxAge(3600);
    }
    
}

3、字典翻譯

<!-- 字典翻譯:性別 -->
<span slot="switchStuSex" slot-scope="stuSex">
    <span v-if="stuSex === 1">男</span>
    <span v-else>女</span>
</span>

<!-- 關聯上面的 slot -->
{
    title: '性別',
    dataIndex: 'stuSex',
    key: 'stuSex',
    align:'center',
    fixed:'left',
    width: 60,
    scopedSlots: { customRender: 'switchStuSex' }, // 關聯那個 <a slot='switchStuSex'>
},

4、獲取表格當前行的數據

<!-- text:文本數據,record:行對象數據 -->
<a slot="name" slot-scope="text,record" @click="fetch(record.id)">{{text}}</a>

5、彈窗信息信息

通過控制 visible 的值進行控制彈窗

<a-modal v-model="visible" title="Basic Modal" @ok="handleOk">
    <p>Some contents...</p>
    <p>Some contents...</p>
    <p>Some contents...</p>
</a-modal>

6、表格標簽自閉和導致插槽失效

結果就是所有的 slot 的字典翻譯都失效了,我看了所有的邏輯代碼,沒有一點毛病。。。我還以為遇上什么詭異的bug了,后來才發現,我不小心把第一個 a-table 標簽自閉和了!因為最后我把去官網重新拷了一份表格代碼,重新改了一次。。。。靠!好氣啊!

但是 axios 查詢出來的數據還能遍歷顯示。。。因為這個情況,導致我一直沒想到和標簽閉合有關。

7、限制輸入文本長度在 1-6 個字符

使用ui表單自帶的校驗api

<a-form-item label="姓名">
    <a-input
             v-decorator="['note', { rules: [{ required: true, message: '姓名為1-6個漢字!', 									  			 min: 1, max: 6 }] }]"
     />
</a-form-item>

8、限制選擇今天之后的日期

前提:ui(antd vue )

<template>
    <a-form-item label="入學日期" has-feedback >
        <a-date-picker format="YYYY-MM-DD"
                       :disabled-date="disabledDate"
                       style="width: 100%" />
    </a-form-item>
</template>
<script>
    import moment from 'moment';
    export default {
        name: 'StuAdd',
        data() {},
        methods: {
            moment,
            disabledDate(current) {
                // 不能選擇今天之后作為入學時間
                return current > moment().endOf('day');
            },
        },
    }
</script>

9、表單項的 name

對前端不是很熟悉,當時提交表單時,發現請求體中各表單項都沒有 name 屬性!!!最后一頓百度,發現沒有結果,可能是因為這個問題太簡單了。。。然后沒辦法,對着ui庫的文檔死磕,最后發現了v-decorator里面的值,就是name屬性,我...@!#$%&*(!@#$%^&*()!!!

例如:stuName

<a-input v-decorator="['stuName']" />

10、自定義表單項校驗,姓名在 1-6個漢字

例如:stuName

<a-form-item label="姓名">
    <a-input
             v-decorator="['stuName', {
                          rules: [
                          { required: true},
                          { validator: this.checkStuName }
                          ]
                          }]"
             />
</a-form-item>

methods:

<script>	
	methods: {
			// 檢查名字
            checkStuName(rule, value, callback){
                const pwdRegex = new RegExp('^[\\u4E00-\\u9FA5]{1,6}$');
                if (!pwdRegex.test(value)) {
                    callback(new Error('名字應為1-6個漢字!'))
                }
                callback()
            },
	}
</script>	

11、給表單項賦默認值為一個變量

錯誤做法:

<a-form-item label="必修技能">
    <a-input disabled v-bind:value="stuSkill" />
</a-form-item>

會報錯:

warning.js?d96e:34 Warning: `getFieldDecorator` will override `value`, so please don't set `value and v-model` directly and use `setFieldsValue` to set it.

原因:v-bind 和 v-decorator 不能同時使用!

正確做法:

<a-form-item label="必修技能">
    <a-input disabled v-decorator="['stuSkill']" />
</a-form-item>

在級聯下拉框的 onChange 方法里:

			// 級聯選擇
            onChange(value, selectedOptions) {
                // alert('院系——'+value[0]);
                // alert('專業——'+value[1]); 
                if(value[0] == 1){
                    this.form.setFieldsValue({stuSkill:'C語言'});
                }else if(value[0] == 2){
                    this.form.setFieldsValue({stuSkill:'基礎急救'});
                }else {
                    this.form.setFieldsValue({stuSkill:''});
                }
            },

12、可輸入值的級聯選擇框的name(7-17: 好看不會用...已換~)

這個不能通過 v-decorator 定義 name,好像很冷門,百度了好久,試了好多,才發現是 v-decorator="['depMajName']"

<a-form-item label="院系及專業">
    <a-cascader
            :options="options"
            :show-search="{ filter }"
            placeholder="請選擇"
            @change="onChange"
            v-decorator="['depMajName']"
    />
</a-form-item>

13、成功往數據庫添加的數據中,日期比傳遞的日期時間提前一天

時區問題,解決:在連接庫url地址后面加上 ?serverTimezone=GMT%2B8

14、對話框和表格同時使用的bug

把對話框的代碼放到表格外面即可!

15、表單數據回顯:setFieldsValue

1.radio 數據回顯

ant design vue 推薦使用 this.form.setFieldsValue 進行不賦值,而不是 v-bindv-model

而且必須 a-radio 中的value,必須要是 :value='1',注意要有冒號:,就無法設置值了。。。

<a-form-item label="性別">
    <a-radio-group v-decorator="['stuSex']" @change="onRadioChange">
        <a-radio :value='1'>
            男
        </a-radio>
        <a-radio :value='0'>
            女
        </a-radio>
    </a-radio-group>
</a-form-item>
2、select 數據回顯(靜態option)

例如:因為年級選項 “大一”的 value 是數字 1,但是顯示的是字符串“大一”。故 setFieldsValue 的時候,需要把 value的值 用 toString() 轉為 String。

例如:


    this.form.setFieldsValue({
    	stuGrade:   this.stu.stuGrade.toString(),
    });

3、checkbox 數據回顯

直接 setFieldsValue 即可。(日期控件 同樣)

例如:this.stu.stuLoves = "2,3,4"

setTimeout(() => {
    this.form.setFieldsValue({
    	stuLoves:   this.stu.stuLoves,
    });
}, 300); 
4、select 數據回顯(動態option)

這是第二種情況,動態option:

:value ,產生動態 value。

<a-form-item label="院系">
                <a-select
                        show-search
                        placeholder="請選擇"
                        :filter-option="filterOption"
                        @change="handleChange"
                        v-decorator="['depName']"
                >
                    <a-select-option v-for="dep in departments" :key="dep.depId" :value="dep.depName">
                        {{dep.depName == 1 ? '計算機系' : ''}}
                        {{dep.depName == 2 ? '醫學系' : ''}}
                    </a-select-option>
                </a-select>
            </a-form-item>

            <a-form-item label="專業">
                <a-select
                        show-search
                        placeholder="請選擇"
                        :filter-option="filterOption2"
                        @change="handleChange2"
                        v-decorator="['majName']"
                >
                    <a-select-option v-for="major in majors" :key="major.majId" :value="major.majName">
                        {{major.majName == 1 ? '軟工' : ''}}
                        {{major.majName == 2 ? '計科' : ''}}
                        {{major.majName == 3 ? '網工' : ''}}
                        {{major.majName == 4 ? '信管' : ''}}
                        {{major.majName == 5 ? '醫學檢驗' : ''}}
                        {{major.majName == 6 ? '臨床醫學' : ''}}
                        {{major.majName == 7 ? '法醫' : ''}}
                    </a-select-option>
                </a-select>
            </a-form-item>

然后賦值:

					setTimeout(() => {
                        this.form.setFieldsValue({
                            // stuGrade:   stuGradeStr,
                            stuGrade:   this.stu.stuGrade.toString(),
                            depName:    this.stu.depName.toString(),
                            majName:    this.stu.majName.toString(),
                        });
                    }, 0);

卻發現不可以,於是把 toString 給去掉,就可以了!應該是因為下拉框的value是整數,而非字符串,顯示的字符是我們的字典翻譯!!!

		setTimeout(() => {
                        this.form.setFieldsValue({
                            // stuGrade:   stuGradeStr,
                            stuGrade:   this.stu.stuGrade.toString(),
                            depName:    this.stu.depName,
                            majName:    this.stu.majName,
                        });
                    }, 0);

16、條件查詢整合分頁查詢

    // 翻頁
    onChange(pagination) {
        console.log('Page: ', pagination.current);

        /* 帶過濾條件的分頁查詢 */
        // 在這個方法里,可以直接獲取表單的屬性
        this.form.validateFields((err, values) => {
            const _this = this;
            this.axios.post("/list/"+ pagination.current +'/'+ pagination.pageSize,
                {
                    stuName:  values.stuName,
                    stuLoves: values.stuLoves.toString(),
                    stuGrade: values.stuGrade,
                    startDate:values.startDate,
                    endDate:  values.endDate,
                }).then(resp => {
                _this.data = resp.data.records;
                _this.pagination.total = resp.data.total;
                _this.pagination.ipages = resp.data.pages;

            });
        });
    },

17、checkbox 提交數據的格式問題

解決:轉字符串

問題:提交不上去,如圖 ,這樣的數據,后端對接不上!

報錯信息如下:

2020-07-17 19:34:12.080  WARN 18856 --- [io-8081-exec-10] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `java.lang.String` out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_ARRAY token
 at [Source: (PushbackInputStream); line: 1, column: 26] (through reference chain: com.feng.pojo.QueryCondition["stuLoves"])]

加上了 toString(),轉為字符串后成功解決:

18、刪除后的條件分頁查詢(根據情況,修改當前頁)

此處如果不對查詢參數 當前頁 進行處理,則會出現一個不友好的情況:當最后一頁只有一條數據時,刪除后,該頁面就為空白了!

	<script>
			// 刪除學生信息
            delStu(record){
                const _this = this;
                this.$confirm({
                    title: '刪除提示',
                    content: '您確定要刪除 “'+record.stuName+'” 嗎?',
                    // content: 'Some descriptions',
                    okText: '確定',
                    okType: 'danger',
                    cancelText: '取消',
                    onOk() {
                        _this.axios.delete('/delete/'+record.stuId).then(resp => {
                            if(resp.data.flag){
                                // 再查詢一次

                                /* 帶過濾條件的分頁查詢 */
                                // 在這個方法里,可以直接獲取表單的屬性
                                _this.form.validateFields((err, values) => {
                                    let stuLovesStr = values.stuLoves+'';

                                    // 如果刪除時,本頁只有一條數據,name當前頁減一
                                    let refreshPage = _this.pagination.current;
                                    if(_this.pagination.total % _this.pagination.pageSize == 1){
                                        refreshPage -= 1;
                                    }
                                    // 刪除后的條件分頁查詢
                                    _this.axios.post("/list/"+ refreshPage +'/'+ _this.pagination.pageSize,
                                        {
                                            stuName:  values.stuName,
                                            stuLoves: stuLovesStr,
                                            stuGrade: values.stuGrade,
                                            startDate:values.startDate,
                                            endDate:  values.endDate,
                                        }).then(resp => {
                                        _this.data = resp.data.records;
                                        _this.pagination.total = resp.data.total;
                                        _this.pagination.ipages = resp.data.pages;
                                        _this.pagination.current = resp.data.current;

                                    });
                                });
                            }
                        });
                        console.log('OK');
                    },
                    onCancel() {
                        console.log('Cancel');
                    }
                });
            },
	</script>		


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM