可持续发展项目(六):前端配置以及开发


前言

为自己搭建一个可以自我思考的平台,其核心为“心想事成”。


一、思考过程?

前端框架搭建完成,该开始编写页面了!在页面编写过程中也遇到了许多问题,在这里记录一下。首先就是axios请求参数不正确导致调用不到接口!其次是请求跨域问题修复!

二、完善

1、首先在package.json中增加element-plus

{
    "name": "sustainable_front",
    "version": "0.1.0",
    "private": true,
    "scripts": {
        "serve": "vue-cli-service serve",
        "build": "vue-cli-service build"
    },
    "dependencies": {
        "core-js": "^3.8.3",
        "vue": "^3.2.13",
        "vue-class-component": "^8.0.0-0",
        "vue-router": "^4.0.3",
        "vuex": "^4.0.0"
    },
    "devDependencies": {
        "@vue/cli-plugin-babel": "~5.0.0",
        "@vue/cli-plugin-router": "~5.0.0",
        "@vue/cli-plugin-typescript": "~5.0.0",
        "@vue/cli-plugin-vuex": "~5.0.0",
        "@vue/cli-service": "~5.0.0",
        "element-plus": "^2.3.14",
        "sass": "^1.32.7",
        "sass-loader": "^12.0.0",
        "typescript": "~4.5.5"
    },
    "browserslist": [
        "> 1%",
        "last 2 versions",
        "not dead",
        "not ie 11"
    ]
}


2、在vue.config.js中加入基本配置

const { defineConfig } = require('@vue/cli-service')
const port = process.env.port || process.env.npm_config_port || 8080; // 端口
module.exports = defineConfig({
	// 在npm run build 或 yarn build 时 ,生成文件的目录名称(要和baseUrl的生产环境路径一致)(默认dist)
	outputDir: 'sustainable',
	publicPath: '/sustainable/',
	lintOnSave: false,
	productionSourceMap: false,
	transpileDependencies: true,
	// webpack-dev-server 相关配置
	devServer: {
		host: "0.0.0.0",
		port: port,
		// Paths
		proxy: { // 配置跨域
			'/api': {
				target: `http://localhost:8080`, //请求后台接口
				changeOrigin: true, // 允许跨域
				pathRewrite: {
					'^/api': '' // 重写请求
				}
			}
		},
	},
})

3、在main.ts中加入vue配置

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

const app = createApp(App).use(store).use(router).use(ElementPlus)
app.mount('#app')

4、请求接口类

import axios from "axios";
import router from '../router'
import {ElMessage} from "element-plus";

axios.defaults.baseURL = 'http://localhost:8080/' //本地

//post请求头
axios.defaults.headers.post["Content-Type"] =
	"application/x-www-form-urlencoded;charset=UTF-8";
//设置超时
axios.defaults.timeout = 10000;


// request拦截器
axios.interceptors.request.use(config => {
	// get请求映射params参数
	if (config.method === 'get' && config.data) {
		let url = config.url + '?';
		for (const propName of Object.keys(config.data)) {
			const value = config.data[propName];
			var part = encodeURIComponent(propName) + "=";
			if (value !== null && typeof(value) !== "undefined") {
				if (typeof value === 'object') {
					for (const key of Object.keys(value)) {
						// let params = propName + '[' + key + ']';
						var subPart = encodeURIComponent(key) + "=";
						url += subPart + encodeURIComponent(value[key]) + "&";
					}
				} else {
					url += part + encodeURIComponent(value) + "&";
				}
			}
		}
		url = url.slice(0, -1);
		// config.params = {};
		config.url = url;
	}
	return config
}, error => {
	Promise.reject(error)
})

let a = true
axios.interceptors.response.use(
	response => {
		if (!response) {
			return Promise.reject("网络异常")
		}
		if (response.data.code !== 200) {
			if (a) {
				ElMessage({
					message: response.data.msg,
					type: "error",
				});
			}
		}
		return response.data
	},
	error => {
		ElMessage({
			type: "error",
			message: "网络请求失败,反馈给客服"
		});
	}
);

export default function axiosApi(url, params, method) {
	return new Promise((resolve, reject) => {
		axios({
			method: method,
			url: url,
			data: params
		})
			.then(res => {
				if (res.code === 200) {
					resolve(res)
				} else {
					// 接口错误提示
					ElMessage({
						type: "error",
						message: res.msg
					});
				}
			})
			.catch(err => {
				reject(err)
			});
	})
};

5、接口调用类

import axios from '../utils/http'

// 查询用户信息
export function page(params) {
    return axios('/user/page', { params }, "get");
}

// 查询关键字列表
export function page(params) {
    return axios('/keywordRecord/page', { params }, "get");
}

// 查询关键字-句关联列表
export function page(params) {
    return axios('/keywordRelation/page', { params }, "get");
}

6、页面编写

<template>
    <div>
        <div style="height: 50px">
            <el-autocomplete
                v-model="name"
                :fetch-suggestions="querySearch"
                :clearable="false"
                value-key="value"
                class="inline-input w-50"
                placeholder="请输入用户名"
                @select="handleSelect"
                @keyup.enter.native="getDataList(true)"
            />
        </div>
        <el-table v-loading="loading" :data="tableData" border>
            <template slot="empty">
                <el-empty :image-size="100" description="暂无数据"></el-empty>
            </template>
            <el-table-column label="姓名" align="center" prop="name"/>
        </el-table>
    </div>
</template>

<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import { page } from '../api/user'
import { page as keywordPage } from '../api/keyword'
import { page as keywordRelationPage } from '../api/keywordRelation'

interface RestaurantItem {
    value: string
    count: string
}

const name = ref('')

const restaurants = ref<RestaurantItem[]>([])
const querySearch = (queryString: string, cb: any) => {
    if (queryString && queryString != '') {
        let params = {
            current: 1,
            size: 10,
            keyword: queryString,
        }
        let keywordList = []
        params.keyword = queryString
        keywordRelationPage(params).then(res => {
            if (res.data.total > 0) {
                res.data.records.forEach(item => {
                    let keyword = {
                        key: item.keyword,
                        value: item.keywordRelationSentence,
                        count: item.useCount,
                        createTime: item.createTime,
                    }
                    keywordList.push(keyword)
                })
            }
            const results = queryString
                ? keywordList.filter(createFilter(queryString))
                : keywordList
            // call callback function to return suggestions
            cb(results)
        })
    } else {
        const results = queryString
            ? restaurants.value.filter(createInitFilter(queryString))
            : restaurants.value
        // call callback function to return suggestions
        cb(results)
    }
}
const createFilter = (queryString: string) => {
    return (item) => {
        return (
            item.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
        )
    }
}
const createInitFilter = (queryString: string) => {
    return (restaurant: RestaurantItem) => {
        return (
            restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
        )
    }
}
const loadAll = () => {
    let params = {
        current: 1,
        size: 10,
    }
    let keywordList = []
    keywordPage(params).then(res => {
        if (res.data.total > 0) {
            res.data.records.forEach(item => {
                let keyword = {
                    value: item.keyword,
                    count: item.useCount,
                    createTime: item.createTime,
                }
                keywordList.push(keyword)
            })
        }
    })
    return keywordList;
}

const handleSelect = (item: RestaurantItem) => {
    console.log(item, 'restaurantItem')
}

onMounted(() => {
    restaurants.value = loadAll()
})

const tableData = ref('')
const loading = ref('')
const queryParams = ref({
    current: 1,
    size: 10,
    name: '',
})
const getDataList = (reset) => {
    if (reset) {
        queryParams.value.current = 1
    }
    if (name.value) {
        queryParams.value.name = name.value
    }
    page(queryParams.value).then(resp => {
        tableData.value = resp.data.records
    })
}

onMounted(() => {
    getDataList( true)
})
</script>


效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值