Commit e77ce462 authored by Junling Bu's avatar Junling Bu
Browse files

chore[litemall-vue]: 增加用户反馈页面

parent 59ecc562
......@@ -43,10 +43,38 @@ export function authLogout() {
method: 'post'
})
}
const AuthInfo='wx/auth/info'; //用户信息
export function authInfo() {
return request({
url: AuthInfo,
method: 'get'
})
}
const AuthProfile='wx/auth/profile'; //验证码
export function authProfile(data) {
return request({
url: AuthProfile,
method: 'post',
data
})
}
const AuthRegister='wx/auth/register'; //账号注册
const AuthReset='wx/auth/reset'; //账号密码重置
export function authReset(data) {
return request({
url: AuthReset,
method: 'post',
data
})
}
const AuthRegisterCaptcha='wx/auth/regCaptcha'; //验证码
export function authRegisterCaptcha(data) {
return request({
url: AuthRegisterCaptcha,
method: 'post',
data
})
}
const AuthBindPhone='wx/auth/bindPhone'; //绑定微信手机号
const GoodsCount='wx/goods/count'; //统计商品总数
......@@ -282,6 +310,14 @@ const OrderGoods='wx/order/goods'; // 代评价商品信息
const OrderComment='wx/order/comment'; // 评价订单商品信息
const FeedbackAdd='wx/feedback/submit'; //添加反馈
export function feedbackAdd(data) {
return request({
url: FeedbackAdd,
method: 'post',
data
})
}
const FootprintList='wx/footprint/list'; //足迹列表
const FootprintDelete='wx/footprint/delete'; //删除足迹
......@@ -350,4 +386,6 @@ export function getList(api, query) {
method: 'get',
params: query
})
}
\ No newline at end of file
}
export const REFUND_LIST = '';
\ No newline at end of file
import request from '@/utils/request'
// export const GOODS_CATEGORY = '/category';
export const GOODS_CATEGORY = '/wx/catalog/index';
export const GOODS_CHANNGE_CATEGORY = '/wx/catalog/current?id=';
export const GOODS_SEARCH = '/moreGoods';
export const GOODS_DETAIL = '/details';
export function goodsCategory(query) {
return request({
url: '/wx/catalog/index',
method: 'get',
params: query
})
}
export function goodsChannelCategory(query) {
return request({
url: '/wx/catalog/index',
method: 'get',
params: query
})
}
export function goodsSearch(query) {
return request({
url: '/wx/catalog/current?id=',
method: 'get',
params: query
})
}
export function goodsDetail(query) {
return request({
url: '/wx/catalog/index',
method: 'get',
params: query
})
}
\ No newline at end of file
import request from '@/utils/request'
export const ORDER_LIST = '/order-list';
export const ELE_COUPON_LIST = '/electronic-list';
export const REFUND_LIST = '/refund-list';
import request from '@/utils/request'
import request from '@/utils/request'
export const HOME_module = '/home';
export const ALL_GOODS = '/moreGoods';
export const SHOPINFO = '/shop-info';
// 运费模板
export const POST_FEE = '';
export function getHome(query) {
return request({
url: '/wx/home/index',
method: 'get',
params: query
})
}
import request from '@/utils/request'
// 登录
export const USER_LOGIN = '/wx/auth/login';
export const USER_LOGOUT = '';
// 用户信息
export const USER_PROFILE = '/user-profile';
export const USER_MODIFY_PASSWORD = '';
export const USER_CHANGE_MOBILE = '';
// 验证码
export const USER_SENDCODE = '';
// 地址
export const ADDRESS = '/address';
export const ADDRESS_DEFAULT = '/address-default';
// 收藏
export const GOODS_COLLECT_LIST = '/moreGoods';
export function loginByUsername(data) {
return request({
url: '/wx/auth/login',
method: 'post',
data
})
}
export function logout() {
return request({
url: '/auth/logout',
method: 'post'
})
}
export function getUserInfo(token) {
return request({
url: '/auth/info',
method: 'get',
params: { token }
})
}
\ No newline at end of file
......@@ -4,6 +4,7 @@ const UserAddress = () => import('@/views/user/module-address');
const UserAddressEdit = () => import('@/views/user/module-address-edit');
const UserServer = () => import('@/views/user/module-server');
const UserHelp = () => import('@/views/user/module-help');
const UserFeedback = () => import('@/views/user/module-feedback');
const UserInformation = () => import('@/views/user/user-information-set');
const UserInfo_SetBg = () => import('@/views/user/user-information-set/set-bg');
......@@ -61,6 +62,11 @@ export default [
name: 'user-help',
component: UserHelp
},
{
path: '/user/feedback',
name: 'user-feedback',
component: UserFeedback
},
{
path: '/user/information',
name: 'user-information',
......
import { loginByUsername, logout, getUserInfo } from '@/api/user'
import { authLoginByAccount, authLogout, authInfo } from '@/api/api'
import { getToken, setToken, removeToken } from '@/utils/auth'
const user = {
......@@ -52,7 +52,7 @@ const user = {
LoginByUsername({ commit }, userInfo) {
const username = userInfo.username.trim()
return new Promise((resolve, reject) => {
loginByUsername(username, userInfo.password).then(response => {
authLoginByAccount(username, userInfo.password).then(response => {
const token = response.data.data
commit('SET_TOKEN', token)
setToken(token)
......@@ -69,12 +69,6 @@ const user = {
getUserInfo(state.token).then(response => {
const data = response.data.data
if (data.perms && data.perms.length > 0) { // 验证返回的perms是否是一个非空数组
commit('SET_PERMS', data.perms)
} else {
reject('getInfo: perms must be a non-null array !')
}
commit('SET_ROLES', data.roles)
commit('SET_NAME', data.name)
commit('SET_AVATAR', data.avatar)
......@@ -86,60 +80,22 @@ const user = {
})
},
// 第三方验证登录
// LoginByThirdparty({ commit, state }, code) {
// return new Promise((resolve, reject) => {
// commit('SET_CODE', code)
// loginByThirdparty(state.status, state.email, state.code).then(response => {
// commit('SET_TOKEN', response.data.token)
// setToken(response.data.token)
// resolve()
// }).catch(error => {
// reject(error)
// })
// })
// },
// 登出
LogOut({ commit, state }) {
return new Promise((resolve, reject) => {
logout(state.token).then(() => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
commit('SET_PERMS', [])
authLogout(state.token).then(() => {
commit('Authorization', '')
commit('avatar', '')
commit('background_image', [])
commit('nickName', [])
removeToken()
resolve()
}).catch(error => {
reject(error)
})
})
},
// 前端 登出
FedLogOut({ commit }) {
return new Promise(resolve => {
commit('SET_TOKEN', '')
removeToken()
resolve()
})
},
// 动态修改权限
ChangeRoles({ commit, dispatch }, role) {
return new Promise(resolve => {
commit('SET_TOKEN', role)
setToken(role)
getUserInfo(role).then(response => {
const data = response.data
commit('SET_ROLES', data.roles)
commit('SET_PERMS', data.perms)
commit('SET_NAME', data.name)
commit('SET_AVATAR', data.avatar)
commit('SET_INTRODUCTION', data.introduction)
dispatch('GenerateRoutes', data) // 动态修改权限后 重绘侧边菜单
resolve()
})
})
}
}
}
......
......@@ -18,7 +18,7 @@
</template>
<script>
import { goodsCategory, goodsChannelCategory } from '@/api/goods';
import { catalogList } from '@/api/api';
import getLocationParam from '@/utils/location-param';
import { Search } from 'vant';
......@@ -52,7 +52,7 @@ export default {
methods: {
initData() {
goodsCategory().then(res => {
catalogList().then(res => {
this.list = res.data.data.categoryList;
this.$refs.classTree.changeList(res.data.data);
this.subCategory = res.data.data.currentSubCategory;
......@@ -63,7 +63,7 @@ export default {
return data.filter(item => item.children && item.children.length);
},
changeCatalog(id) {
goodsChannelCategory({ id: id}).then(res => {
catalogList({ id: id}).then(res => {
let index = getIndex(this.list, res.data.data.currentCategory.id);
this.$refs.classTree.changeList(res.data.data);
this.subCategory = res.data.data.currentSubCategory;
......
......@@ -37,7 +37,16 @@ export default {
},
loadAddress() {
addressList().then(res => {
this.addressList = res.data.data;
var list = res.data.data;
for(var i = 0; i < list.length; i++ ){
var item = list[i]
this.addressList.push({
id: item.id,
name: item.name,
tel: item.tel,
address: item.province + item.city + item.county + " " + item.addressDetail
})
}
})
}
},
......
<template>
<div>
<van-cell-group title="反馈类型">
<van-cell class="order-coupon" :title="type" is-link arrow-direction="down" @click="showList = true" />
</van-cell-group>
<van-cell-group title="反馈内容">
<van-field v-model="content"
clearable autosize center
placeholder="对我们网站、商品、服务,你还有什么建议吗?你还希望在商城上买到什么?请告诉我们..."
type="textarea"
rows="10"
size="large"
/>
</van-cell-group>
<van-cell-group title="联系方式">
<van-field size="large" v-model="mobile" placeholder="请输入联系电话,方便我们与您联系" />
</van-cell-group>
<van-button size="large" type="primary" @click="submit">提交</van-button>
<van-popup v-model="showList" position="bottom">
<van-picker :columns="types" @change="onType" />
</van-popup>
</div>
</template>
<script>
import { Field , Picker, Popup, Button } from 'vant';
import { feedbackAdd } from '@/api/api';
export default {
data() {
return {
mobile: '',
content: '',
showList: false,
types:['商品相关', '功能异常', '优化建议', '其他'],
type: ''
};
},
created() {
},
methods: {
onType(picker, value, index) {
this.type = value
this.showList = false
},
submit() {
if(this.mobile === ''){
this.$toast("请输入联系电话");
return;
}
if(this.type === ''){
this.$toast("请选择反馈类型");
return;
}
if(this.content === ''){
this.$toast("请输入反馈内容");
return;
}
feedbackAdd({ mobile: this.mobile, feedType: this.type, content: this.content}).then(res => {
this.$toast("感谢您的宝贵意见!");
this.$router.go(-1);
})
}
},
components: {
[Field.name]: Field,
[Popup.name]: Popup,
[Button.name]: Button,
[Picker.name]: Picker
}
};
</script>
<style lang="scss" scoped>
.addressGroup {
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
}
.bottom_btn {
position: fixed;
bottom: 0;
}
</style>
<template>
<div>
<van-collapse accordion="true" v-model="activeNames">
<van-collapse :accordion="true" v-model="activeNames">
<van-collapse-item :title="issue.question" :name="index" v-for="(issue, index) in issueList" :key="index">
{{issue.answer}}
</van-collapse-item>
......@@ -35,7 +35,4 @@ export default {
[CollapseItem.name]: CollapseItem
}
};
</script>
<style scoped lang="scss">
</style>
\ No newline at end of file
</script>
\ No newline at end of file
......@@ -2,7 +2,7 @@
<div>
<van-cell-group>
<van-cell title="联系客服" @click="showKefu = true" isLink></van-cell>
<van-cell title="意见反馈" isLink></van-cell>
<van-cell title="意见反馈" to="/user/feedback" isLink></van-cell>
<van-cell title="常见问题" to="/user/help" isLink/>
</van-cell-group>
<van-popup v-model="showKefu">
......
......@@ -43,7 +43,7 @@
</template>
<script>
import { REFUND_LIST } from '@/api/order';
import { REFUND_LIST } from '@/api/api';
import { Tab, Tabs, Panel, Card, List } from 'vant';
import InfinityScroll from '@/components/infinity-scroll';
......
......@@ -40,7 +40,6 @@
<script>
import { Uploader, Picker, Popup, Button } from 'vant';
import { USER_PROFILE } from '@/api/user';
import { removeLocalStorage } from '@/utils/local-storage';
import { getLocalStorage } from '@/utils/local-storage';
import { authLogout } from '@/api/api';
......@@ -78,12 +77,7 @@ export default {
console.log(file);
},
onSexConfirm(value, index) {
this.$reqPut(USER_PROFILE, {
gender: index[0]
}).then(res => {
this.gender = res.data.data.gender;
this.showSex = false;
});
},
getUserInfo() {
const infoData = getLocalStorage(
......
<template>
<div>
<van-cell-group>
<van-field
label="登录密码"
v-model="password"
type="password"
placeholder="请输入登录密码"
:error="!!$vuelidation.error('password')" />
<van-field
label="新手机号"
v-model="new_mobile"
placeholder="请输入新手机号"
:error="!!$vuelidation.error('new_mobile')" />
<van-field
label="验证码"
v-model="code"
@click-icon="getCode"
placeholder="请输入验证码">
<span slot="icon"
class="verifi_code red"
:class="{verifi_code_counting: counting}"
@click="getCode">
<countdown v-if="counting" :time="60000" @countdownend="countdownend">
<template slot-scope="props">{{ +props.seconds || 60 }}秒后获取</template>
</countdown>
<span v-else>获取验证码</span>
</span>
</van-field>
</van-cell-group>
<div class="bottom_btn">
<van-button size="large" type="danger" @click="saveMobile">保存</van-button>
</div>
</div>
</template>
<script>
import { USER_SENDCODE } from '@/api/user';
import { Field } from 'vant';
export default {
data: () => ({
password: '',
new_mobile: '',
code: '',
counting: false
}),
vuelidation: {
data: {
password: {
required: true
},
new_mobile: {
required: true,
mobile: true
}
}
},
methods: {
getCode() {
if (!this.counting && this.vuelidat()) {
this.$reqPost(USER_SENDCODE, {
mobile: this.new_mobile,
operation: 'changeMobile'
}).then(() => {
this.$toast.success('发送成功');
this.counting = true;
});
}
},
countdownend() {
this.counting = false;
},
vuelidat() {
this.$vuelidation.valid();
if (this.$vuelidation.error('new_mobile')) {
const msg = this.$vuelidation.error('new_mobile');
this.$toast(msg == 'Required' ? '请输入手机号' : msg);
return false;
}
return true;
},
saveMobile() {
console.log('保存手机号');
}
},
components: {
[Field.name]: Field
}
};
</script>
<style lang="scss" scoped>
@import '../../../../assets/scss/var';
@import '../../../../assets/scss/mixin';
.bottom_btn {
padding: 30px 15px 0 15px;
}
.verifi_code {
@include one-border;
padding-left: 10px;
&::after {
border-bottom: 0;
border-left: 1px solid $border-color;
}
&_counting {
color: $font-color-gray;
}
}
</style>
<template>
<div>
<van-cell-group>
<van-field
label="登录密码"
v-model="password"
type="password"
placeholder="请输入登录密码"
:error="!!$vuelidation.error('password')" />
<van-field
label="新手机号"
v-model="new_mobile"
placeholder="请输入新手机号"
:error="!!$vuelidation.error('new_mobile')" />
<van-field
label="验证码"
v-model="code"
@click-icon="getCode"
placeholder="请输入验证码">
<span slot="icon"
class="verifi_code red"
:class="{verifi_code_counting: counting}"
@click="getCode">
<countdown v-if="counting" :time="60000" @countdownend="countdownend">
<template slot-scope="props">{{ +props.seconds || 60 }}秒后获取</template>
</countdown>
<span v-else>获取验证码</span>
</span>
</van-field>
</van-cell-group>
<div class="bottom_btn">
<van-button size="large" type="danger" @click="saveMobile">保存</van-button>
</div>
</div>
</template>
<script>
import { authRegisterCaptcha } from '@/api/api';
import { Field } from 'vant';
export default {
data: () => ({
password: '',
new_mobile: '',
code: '',
counting: false
}),
vuelidation: {
data: {
password: {
required: true
},
new_mobile: {
required: true,
mobile: true
}
}
},
methods: {
getCode() {
if (!this.counting && this.vuelidat()) {
authRegisterCaptcha({
mobile: this.new_mobile,
operation: 'changeMobile'
}).then(() => {
this.$toast.success('发送成功');
this.counting = true;
});
}
},
countdownend() {
this.counting = false;
},
vuelidat() {
this.$vuelidation.valid();
if (this.$vuelidation.error('new_mobile')) {
const msg = this.$vuelidation.error('new_mobile');
this.$toast(msg == 'Required' ? '请输入手机号' : msg);
return false;
}
return true;
},
saveMobile() {
console.log('保存手机号');
}
},
components: {
[Field.name]: Field
}
};
</script>
<style lang="scss" scoped>
@import '../../../../assets/scss/var';
@import '../../../../assets/scss/mixin';
.bottom_btn {
padding: 30px 15px 0 15px;
}
.verifi_code {
@include one-border;
padding-left: 10px;
&::after {
border-bottom: 0;
border-left: 1px solid $border-color;
}
&_counting {
color: $font-color-gray;
}
}
</style>
<template>
<div class="set_nickname">
<van-cell-group>
<van-field v-model="nickName" label="昵称" :error="!!$vuelidation.error('nickName')"/>
</van-cell-group>
<div class="bottom_btn">
<van-button size="large" type="danger" @click="saveNick">保存</van-button>
</div>
</div>
</template>
<script>
import { USER_PROFILE } from '@/api/user';
import { Field } from 'vant';
export default {
data() {
return {
nickName: ''
};
},
created() {
this.getNick();
},
methods: {
getNick() {
this.nickName = localStorage.getItem('nickName') || '';
},
saveNick() {
if (true) {
this.$reqPut(USER_PROFILE, { nickName: this.nickName })
.then(res => {
localStorage.setItem('nickName', res.data.data.nickName);
return this.$dialog.alert({ message: '保存成功' });
})
.then(() => {
this.$router.go(-1);
});
}
}
},
components: {
[Field.name]: Field
}
};
</script>
<style scoped>
.bottom_btn {
padding: 30px 15px 0 15px;
}
</style>
<template>
<div class="set_nickname">
<van-cell-group>
<van-field v-model="nickName" label="昵称" :error="!!$vuelidation.error('nickName')"/>
</van-cell-group>
<div class="bottom_btn">
<van-button size="large" type="danger" @click="saveNick">保存</van-button>
</div>
</div>
</template>
<script>
import { authProfile } from '@/api/api';
import { Field } from 'vant';
export default {
data() {
return {
nickName: ''
};
},
created() {
this.getNick();
},
methods: {
getNick() {
this.nickName = localStorage.getItem('nickName') || '';
},
saveNick() {
if (true) {
authProfile({ nickName: this.nickName })
.then(res => {
localStorage.setItem('nickName', res.data.data.nickName);
return this.$dialog.alert({ message: '保存成功' });
})
.then(() => {
this.$router.go(-1);
});
}
}
},
components: {
[Field.name]: Field
}
};
</script>
<style scoped>
.bottom_btn {
padding: 30px 15px 0 15px;
}
</style>
......@@ -34,7 +34,7 @@
<script>
import { USER_MODIFY_PASSWORD, USER_LOGOUT } from '@/api/user';
import { authReset, authLogout } from '@/api/api';
import { removeLocalStorage } from '@/utils/local-storage';
import { Field } from 'vant';
......@@ -49,21 +49,14 @@ export default {
methods: {
modifypassword() {
if (this.passwordValid()) {
this.$reqPut(USER_MODIFY_PASSWORD, {
authReset({
old_password: this.password,
new_password: this.new_password
})
.then(() => this.$dialog.alert({ message: '保存成功, 请重新登录.' }))
.then(() => this.$reqGet(USER_LOGOUT))
.then(() => {
removeLocalStorage(
'Authorization',
'avatar',
'background_image',
'nickName'
);
this.$router.replace({ name: 'login' });
});
.then(() => {
this.$dialog.alert({ message: '保存成功, 请重新登录.' })
authLogout();
});
}
},
passwordValid() {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment