ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

VUE 前端,TP5(thinkPHP5)后端,axios 请求第一个(聚合数据)接口,解决跨城问题

2021-11-02 19:31:05  阅读:249  来源: 互联网

标签:www axios name thinkPHP5 TP5 static imgs alt com


问题描述:

1: 用 VUE 当前端
2: 用 TP5(thinkPHP5) 当后端
3: 前端请求后端接口

前端界面如下:ElementUI 使用(仿了一个 admin-vue 后端)
在这里插入图片描述

分成头部、左侧、右侧

router.js

import Vue from 'vue'
import Router from 'vue-router'
import Main from '@/components/Main'
import Right from '@/components/Right'
import Joke from '@/components/apis/Api_1'

Vue.use(Router)

export default new Router({
    mode: 'history',
    routes: [
        { path: '/',
          component: Main,
          children: [
            { path: '', component: Right },
            { path: 'joke', component: Joke }
          ]
        }
    ]
})

右侧代码:

<template>
    <div class="content-box content-right">
        <el-card class="box-card api-card" @mouseenter="goon = !goon" @mouseleave="goon = !goon">
            <div slot="header" class="clearfix">
                <span>API 列表</span>
                <el-button class="refreshBtn" type="text">刷新</el-button>
            </div>

            <div class="card-list">
                <el-card v-for="api in apiItems" :key="api.nmb" class="box-card sub-box-card">
                    <div class="sub-box-body">
                        <img class="image" :src="api.src" :alt="api.alt" />
                        <h2 class="title"></h2>
                        <p>{{ api.name }}</p>
                    </div>
                    <a class="click-btn" :href="api.link">点击使用</a>
                </el-card>

            </div>
        </el-card>
    </div>
</template>

<script>
import eventBus from '../../static/js/eventBus' // 根据 header 里面的传值

export default {
    name: 'right',
    mounted () {
        this.getApis()
        eventBus.$on('collapseOrNot', (data) => { // 对位置的绝对值进行重写
            console.log(data)
            let contentRightWidth = document.getElementsByClassName('content-right')[0]
            if (data) {
                contentRightWidth.style.left = '65px'
            } else {
                contentRightWidth.style.left = '158px'
            }
        })
    },
    data () {
        return {
            apiItems: ''
        }
    },
    methods: {
        getApis () {
            this.$axios.get('/static/json/apis.json').then(res => { // 获取 apis.json 里面的数据
                if (res.data.code === 200) { this.apiItems = res.data.data }
            }).catch(error => {
                console.log(error)
            })
        }
    }

}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

.content-box {
    padding: 1rem;
    position: absolute;
    left: 158px;
    top: 6rem;
    bottom: 0;
    padding-bottom: 30px;
    -webkit-transition: left .3s ease-in-out;
    transition: left .1s ease-in-out;
    background: #ffffff;
}
.clearfix:before, .clearfix:after {
    display: table;
    content: "";
}
.clearfix:after {
    clear: both
}

.api-card {
    padding-bottom: 2rem;
}

.refreshBtn {
    float: right; padding: 3px 0;
}

.sub-box-card {
    text-align: center;
    width: 9rem;
    float: left;
    margin: 0 2rem;
    position: relative;
    margin-bottom: 2rem;
}

.sub-box-card:hover, .sub-box-body {
    transform: translateY(-10px);
    transition: .5s;
}

.sub-box-card:hover {
    box-shadow: 0px 10px 10px -5px #eee;
}

.sub-box-card:hover .click-btn {
    opacity: 1;
    animation-fill-mode: forwards;
    animation: floatbtn .5s;
    animation-duration: 0.5s;
    animation-timing-function: ease;
    animation-delay: 0s;
    animation-iteration-count: 1;
    animation-direction: normal;
    animation-fill-mode: none;
    animation-play-state: running;
    animation-name: floatbtn;
}

.click-btn {
    opacity: 0;
    position: absolute;
    bottom: 0;
    margin-left: -50%;
    width: 100%;
    height: 2rem;
    text-align: center;
    line-height: 2rem;
    color: white;
    font-size: 1rem;
    font-weight: bold;
    background-color: #00bdff;
    border-radius: 0.2rem;
    text-decoration: none;
    padding: 0;
    transition: .5s;
    cursor: pointer;
}

.sub-box-card .image {
    width: 4rem;
    height: 4rem;
    margin-bottom: 1rem;
}

.sub-box-card .title{
    font-size: 18px;
    color: white;
}
</style>

apis.json:

{
    "msg": "success",
    "code": 200,
    "data": [
        { "nmb": 1, "src": "/static/imgs/constellation.jpeg", "alt": "星座", "name": "星座", "link": "https://www.baidu.com" },
        { "nmb": 2, "src": "/static/imgs/weather.png", "alt": "天气", "name": "天气", "link": "https://www.baidu.com" },
        { "nmb": 3, "src": "/static/imgs/phone_attribution.jpeg", "alt": "星座", "name": "星座", "link": "https://www.baidu.com" },
        { "nmb": 4, "src": "/static/imgs/news.jpeg", "alt": "新闻", "name": "新闻", "link": "https://www.baidu.com" },
        { "nmb": 5, "src": "/static/imgs/video.jpeg", "alt": "热门视频榜单", "name": "热门视频榜单", "link": "https://www.baidu.com" },
        { "nmb": 6, "src": "/static/imgs/joke.jpeg", "alt": "笑话大全", "name": "笑话大全", "link": "/joke" },
        { "nmb": 7, "src": "/static/imgs/rate.jpeg", "alt": "汇率", "name": "汇率", "link": "https://www.baidu.com" },
        { "nmb": 8, "src": "/static/imgs/history.jpg", "alt": "历史上的今天", "name": "历史上的今天", "link": "https://www.baidu.com" },
        { "nmb": 9, "src": "/static/imgs/idiom.jpeg", "alt": "成语接龙", "name": "成语接龙", "link": "https://www.baidu.com" },
        { "nmb": 10, "src": "/static/imgs/drive_liscence.jpeg", "alt": "驾照题库", "name": "驾照题库", "link": "https://www.baidu.com" },
        { "nmb": 11, "src": "/static/imgs/calendar.jpeg", "alt": "万年历", "name": "万年历", "link": "https://www.baidu.com" },
        { "nmb": 12, "src": "/static/imgs/qq.jpeg", "alt": "QQ号测吉凶", "name": "QQ号测吉凶", "link": "https://www.baidu.com" },
        { "nmb": 13, "src": "/static/imgs/idiom_2.jpeg", "alt": "成语大全", "name": "成语大全", "link": "https://www.baidu.com" },
        { "nmb": 14, "src": "/static/imgs/dictionary.jpg", "alt": "新华字典", "name": "新华字典", "link": "https://www.baidu.com" },
        { "nmb": 15, "src": "/static/imgs/code.jpeg", "alt": "邮编查询", "name": "邮编查询", "link": "https://www.baidu.com" },
        { "nmb": 16, "src": "/static/imgs/zhougong.jpeg", "alt": "周公解梦", "name": "周公解梦", "link": "https://www.baidu.com" },
        { "nmb": 17, "src": "/static/imgs/ebook.jpeg", "alt": "图书电商数据", "name": "图书电商数据", "link": "https://www.baidu.com" },
        { "nmb": 18, "src": "/static/imgs/balance.jpeg", "alt": "健康指数器", "name": "健康指数器", "link": "https://www.baidu.com" },
        { "nmb": 19, "src": "/static/imgs/solar_terms.jpeg", "alt": "二十四节气", "name": "二十四节气", "link": "https://www.baidu.com" },
        { "nmb": 20, "src": "/static/imgs/flower.jpeg", "alt": "生日花语", "name": "生日花语", "link": "https://www.baidu.com" },
        { "nmb": 21, "src": "/static/imgs/id.jpg", "alt": "身份证查询", "name": "身份证查询", "link": "https://www.baidu.com" }
    ]
}

Api_1.vue

<template>
    <div class="api_interface content-box content-right">
        <el-card class="box-card">
            <div slot="header" class="clearfix">
                <span>笑话大全</span>
                <el-button type="text" @click="refresh">刷新</el-button>
            </div>
            <div class="joke">
                <el-select v-model="value" placeholder="按更新时间查询笑话" @change="selectType($event)">
                    <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"></el-option>
                </el-select>
            </div>

            <!-- 按更新时间查询笑话 -->
            <div class="type-one">
                <div class="page_number">
                    <el-select v-model="page" placeholder="显示第1页">
                        <el-option v-for="i in 20" :key="i" :label="'显示第' + i + '页'" :value="'显示第' + i + '页'"></el-option>
                    </el-select>
                </div>
                <div class="pagesize">
                    <el-select v-model="pagesize" placeholder="显示1条">
                        <el-option v-for="i in 20" :key="i" :label="'显示' + i + '条'" :value="'显示' + i + '条'"></el-option>
                    </el-select>
                </div>
                <div class="timestamp"></div>
            </div>

            <!-- 最新笑话 -->
            <div class="type-two">
                <div class="page_number">
                    <el-select v-model="page" placeholder="显示第1页">
                        <el-option v-for="i in 20" :key="i" :label="'显示第' + i + '页'" :value="'显示第' + i + '页'"></el-option>
                    </el-select>
                </div>
                <div class="pagesize">
                    <el-select v-model="pagesize" placeholder="显示1条">
                        <el-option v-for="i in 20" :key="i" :label="'显示' + i + '条'" :value="'显示' + i + '条'"></el-option>
                    </el-select>
                </div>
            </div>

            <!-- 随机获取笑话 -->
            <div class="type-three"></div>

            <el-button class="query-btn" round @click="queryFn">确定查询</el-button>

            <el-card class="box-card query-result">
                <div slot="header" class="clearfix">
                    <span>结果如下</span>
                </div>
                <div class="joke-result-show"></div>
            </el-card>

        </el-card>
    </div>
</template>

<script>

export default {
    name: 'right',
    data () {
        return {
            options: [
                { value: '1', label: '按更新时间查询笑话' },
                { value: '2', label: '最新笑话' },
                { value: '3', label: '随机笑话' }
            ],
            value: '',
            page: '',
            pagesize: ''
        }
    },
    methods: {
        selectType (e) {
            let typeOne = document.getElementsByClassName('type-one')[0]
            let typeTwo = document.getElementsByClassName('type-two')[0]
            let typeThree = document.getElementsByClassName('type-three')[0]
            switch (e) {
                case '2':
                    typeOne.style.display = 'none'
                    typeThree.style.display = 'none'
                    typeTwo.style.display = 'block'
                    break
                case '3':
                    typeOne.style.display = 'none'
                    typeTwo.style.display = 'none'
                    typeThree.style.display = 'block'
                    break
                default:
                    typeTwo.style.display = 'none'
                    typeThree.style.display = 'none'
                    typeOne.style.display = 'block'
            }
        },
        refresh () {
            this.$router.go(0)
        },
        queryFn () {
            let baseUrl = '/api_1'
            this.$axios({
                methods: 'get',
                url: baseUrl
            }).then(res => {
                console.log(res.data)
            }).catch(error => {
                console.log(error)
            })
        }
    }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.content-box {
    text-align: center;
    margin-left: 4rem;
}

.type-one {
    display: block;
}

.type-two {
    display: none;
}

.type-three {
    display: none;
}

.page_number, .pagesize {
    margin-top: 1rem;
}

.query-btn {
    margin: 2rem 0;
}

</style>

Api_1.vue 里面 axios 请求 /api_1, 配置对应的 /config/index.js

'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.

const path = require('path')

module.exports = {
  dev: {

    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
      '/api_1': {
        target:'http://www.chaxun.com/index/Apis/index', // 你请求的第三方接口
        changeOrigin:true,  // 在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
        pathRewrite:{       // 路径重写,
          '^/api_1': '/api_1'       // 替换target中的请求地址,也就是说以后你在请求 target 的地址的时候直接写成 /api_1 即可。
        }
      }
    },
    ... ... // 剩下的内容我没有改动过

剩下的内容就在 TP5 里面写了,TP5 布局如下:
加粗样式

Apis.php 里面的内容

<?php
namespace   app\index\controller;
use think\Route;
use think\View;
use think\Db;
use think\Request;

class Apis {
    public function index() 
    {
        return '<h1>This is my first controller.</h1>';
    }

    /**
 * 发起网络请求函数
 * @param String $url 请求的URL
 * @param bool $params  请求的参数内容
 * @param int $isPost   是否POST请求
 * @return bool|string  返回内容
 */
    public function httpRequest($url, $params = false, $isPost = 0){
        $httpInfo = [];
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt($ch, CURLOPT_USERAGENT,  'ozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36');    // 浏览器代理信息,我这里设置的自己的浏览器
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);    // 连接的等待时间, 3秒
        curl_setopt($ch, CURLOPT_TIMEOUT, 12);          // 函数最长的执行时间 
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 将 curl_exec() 获取的信息以字符串返回,而不是直接输出
        if ($isPost) {
            curl_setopt($ch, CURLOPT_POST, true);       // true 表示 post 请求
            curl_setopt($ch, CURLOPT_POSTFIELDS, $params);  // post 的请求数据的处理
            curl_setopt($ch, CURLOPT_URL, $url);        // 设置访问的 URL
        } else {
            if ($params) {
                curl_setopt($ch, CURLOPT_URL, $url . '?' . $params);
            } else {
                curl_setopt($ch, CURLOPT_URL, $url);
            }
        }
        $reponse = curl_exec($ch);
        if ($reponse === FALSE) {
            return false;   // echo "cURL Error: ".curl_error($ch);
        }
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $httpInfo = array_merge($httpInfo, curl_getinfo($ch));
        curl_close($ch);
        return $reponse;
    }

    const CONST_KEY = "";   // 使用的时候 self::CONST_KEY, 自己聚合里面申请的KEY填写上

    public function joke() // joke api_01 笑话大全
    {
        $url = "http://v.juhe.cn/joke/content/list.php";  // 笑话大全方式一
        /*
参数名	    类型	是否必填	说明
sort	  string	是	    类型,desc:指定时间之前发布的,asc:指定时间之后发布的	
page	   int	    否	    当前页数,默认1,最大20	
pagesize   int	    否	    每次返回条数,默认1,最大20	
time	  string	是	    时间戳(10位),如: 1635328323
        */
        // $sort = 'desc';
        // $page = 1;
        // $pagesize = 20;
        // $time = time();

        // $parameters = "sort=desc&page=1&pagesize=20&time=1635328323&key=".self::CONST_KEY;
        $params = [ // 请求参数
            'sort' => 'desc',
            'page' => 1,
            'pagesize' => 20,
            'time' => time()
        ];

        $paramsString = http_build_query($params);  // 参数数组转换成字符串
        $response = self::httpRequest($url, $paramsString."&key=".self::CONST_KEY, 0);  // 第二个参数里面添加聚合里面给的 key
        echo $response;
        $result = json_decode($response, true); // true 返回 json 而不是 objection

        if ($result) {
            // return print_r($result);
            $errorCode = $result['error_code'];
            if ($errorCode == 0) {
                $data = $result['result'];
                return "<h1>I am good man.</h1>";
                // return $jsonData;
            } else {
                return "第一种错: {$errorCode}_{$result['reason']}".PHP_EOL;
            }
        } else {
            return "第二种错: ".PHP_EOL;    // 可能网络异常等问题,无法正常获得相应内容,业务逻辑可自行修改
        }

        return '<h1>Api coming</h1>';
    }
}

在前端运行的结果如下:
在这里插入图片描述

至于界面,准备写中。

标签:www,axios,name,thinkPHP5,TP5,static,imgs,alt,com
来源: https://blog.csdn.net/qq_38192709/article/details/121106885

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有