ENV = 'development'
VUE_APP_BASE_API = 'http://itfly.vip:8888'
ENV = 'production'
VUE_APP_BASE_API = 'http://itfly.vip:8888'
vue.config.js
module.exports = {
css: {
loaderOptions: {
css: {},
postcss: {
plugins: [
require('postcss-px2rem')({
remUnit: 37.5
})
]
}
}
},
devServer: {
// proxy: {
// '/api': {
// target: 'https://yys.res.netease.com', // 目标地址
// ws: true, /// / 是否启用websockets
// changeOrigin: true, // 开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
// pathRewrite: { '^/api': '/' } // 这里重写路径
// }
// }
before(app) {
app.get('/api', (req, res) => {
res.send(require('./mock/data.json'))
})
}
}
}
package.json
{
"name": "vue-mall-phone-2105",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"build:prod": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.23.0",
"core-js": "^3.6.5",
"lib-flexible": "^0.3.2",
"moment": "^2.29.1",
"nprogress": "^0.2.0",
"postcss-px2rem": "^0.3.0",
"vant": "^2.0.5",
"vue": "^2.6.11",
"vue-router": "^3.5.2",
"vuex": "^3.4.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-vuex": "^4.5.14",
"@vue/cli-service": "~4.5.0",
"@vue/eslint-config-standard": "^5.1.2",
"babel-eslint": "^10.1.0",
"babel-plugin-import": "^1.8.0",
"eslint": "^6.7.2",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^6.2.2",
"node-sass": "^4.14.1",
"sass-loader": "^9.0.3",
"vue-cli-plugin-route": "0.0.7",
"vue-cli-plugin-vant": "~1.0.1",
"vue-template-compiler": "^2.6.11"
}
}
babel.config.js
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
eslink
module.exports = {
root: true,
env: {
node: true
},
extends: [
'plugin:vue/essential',
'@vue/standard'
],
parserOptions: {
parser: 'babel-eslint'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'space-before-function-paren': 0,
'eol-last': 0,
'no-multiple-empty-lines': 0
}
}
api
goods
import request from '../utils/request'
export const getGoods = ({ page, limit }) => {
return request({
method: 'get',
// eslint-disable-next-line quotes
url: `/api/getgoods?pageindex=${page}&limit=${limit}`
})
}
export const getGoodsInfo = id => {
return request({
method: 'get',
url: '/api/goods/getinfo/' + id
})
}
home
import request from '../utils/request'
export const getLunbo = () => {
return request({
method: 'get',
url: '/api/getlunbo'
})
}
export const getGrids = () => {
return request({
method: 'get',
url: '/api/grids'
})
}
news
import request from '../utils/request'
export const getNewsList = () => {
return request({
method: 'get',
url: '/api/getnewslist'
})
}
export const getNewsInfo = id => {
return request({
method: 'get',
url: '/api/getnew/' + id
})
}
export const getComments = ({ id, pageNo, pageSize }) => {
return request({
method: 'get',
// eslint-disable-next-line quotes
url: `/api/getcomments/${id}?pageindex=${pageNo}&limit=${pageSize}`
})
}
export const postComments = ({ id, content }) => {
return request({
method: 'post',
url: '/api/postcomment/' + id,
data: {
content
}
})
}
photos
import request from '../utils/request'
export const getImageCategory = () => {
return request({
method: 'get',
url: '/api/getimgcategory'
})
}
export const getImages = id => {
return request({
method: 'get',
url: '/api/getimages/' + id
})
}
export const getImageInfo = id => {
return request({
method: 'get',
url: '/api/getimageInfo/' + id
})
}
export const getThumImages = id => {
return request({
method: 'get',
url: '/api/getthumimages/' + id
})
}
components comment
<template>
<div class="comment">
<van-field
class="content"
v-model="message"
rows="1"
autosize
label="发表评论"
type="textarea"
placeholder="请输入bb的内容"
autofocus
ref="fieldRef"
/>
<van-button
type="primary"
block
@click="postComments"
>提交评论</van-button>
<div class="comment-list">
<van-card
v-for="(item,index) in comments"
:key="index"
:desc="item.content"
>
<template #thumb>
<van-icon name="https://b.yzcdn.cn/vant/icon-demo-1126.png" />
<div>{{item.user_name}}</div>
</template>
<template #title>
<van-rate
v-model="value"
readonly
/>
</template>
<template #price>
{{item.add_time}}
</template>
</van-card>
</div>
<van-loading
type="circular"
v-if="isLoading"
class="more"
>
加载中...
</van-loading>
<div
v-else
@click="getMore"
class="more"
>
{{hasMore?'被掏空了': '加载更多'}}
</div>
</div>
</template>
<script>
import { getComments, postComments } from '@/api/news'
export default {
props: ['id'],
data() {
return {
message: '',
value: 5,
comments: [],
pageNo: 0,
pageSize: 3,
hasMore: false,
disabled: false,
isLoading: false
}
},
created() {
this.getComments()
},
methods: {
async getComments() {
if (this.hasMore !== false) {
this.disabled = true
return
}
++this.pageNo
const res = await getComments({ id: this.id, pageNo: this.pageNo, pageSize: this.pageSize })
this.comments = this.comments.concat(res.data.message)
// 计算临界点
this.hasMore = this.pageNo * this.pageSize > res.data.count
},
getMore() {
this.isLoading = true
setTimeout(() => {
this.isLoading = false
this.getComments()
}, 1000)
},
async postComments() {
if (this.message) {
await postComments({ id: this.id, content: this.message })
this.comments.unshift({
user_name: '匿名用户',
add_time: new Date().getTime(),
content: this.message,
rate: 5
})
this.message = ' '
// this.$refs.fieldRef.focus()
}
}
}
}
</script>
<style lang="scss" scoped>
.comment {
.content {
margin: 10px 0;
border: 1px solid #ddd;
padding: 10px 16px;
height: 60px;
}
.comment-list {
margin-top: 10px;
.van-icon {
font-size: 50px;
}
.van-card__desc {
margin-top: 15px;
}
}
.more {
color: #969799;
font-size: 14px;
line-height: 50px;
text-align: center;
}
}
</style>
swiper
<template>
<div>
<van-swipe
:autoplay="autoplay"
indicator-color="white"
class="my-swipe"
>
<van-swipe-item
v-for="item in lunbolist"
:key="item.id"
>
<img v-lazy="item.src||item.img">
</van-swipe-item>
</van-swipe>
</div>
</template>
<script>
export default {
props: {
lunbolist: {},
autoplay: {
type: Number,
default: 0
}
}
}
</script>
<style lang="scss" scoped>
.my-swipe {
height: 150px;
text-align: center;
img {
width: 50%;
height: 100%;
}
}
</style>
diretives
import Vue from 'vue'
Vue.directive('price', {
inserted(el, binding) {
console.log(el)
el.textContent = binding.value + el.textContent
}
})
// export default function (Vue) {
// Vue.directive('price', {
// inserted(el, binding) {
// el.textContent = binding.value + el.textContent + '元'
// }
// })
// }
filters
import Vue from 'vue'
import moment from 'moment'
Vue.filter('datefmt', arg => {
return moment(arg).format('YYYY-MM-DD HH:mm:ss')
})
mixins
// export default {
// created() {
// console.log('mixins created')
// },
// methods: {
// goDetail(url, id) {
// this.$router.push(url + '/' + id)
// }
// }
// }
import Vue from 'vue'
// 全局混入 容易变量 重复
Vue.mixin({
methods: {
goDetail(url, id) {
this.$router.push(url + '/' + id)
}
}
})