提交 cc29b4f4 authored 作者: 王鹏飞's avatar 王鹏飞

update

上级 a7f52c51
VUE_APP_LOGIN_API=
VUE_APP_BASE_API=
VUE_APP_LOGIN_API=https://databus-api2.ezijing.com
VUE_APP_BASE_API=https://lms-api.ezijing.com
module.exports = {
presets: ["@vue/cli-plugin-babel/preset"]
};
presets: ['@vue/cli-plugin-babel/preset'],
plugins: [
[
'import',
{
libraryName: 'vant',
libraryDirectory: 'es',
style: true
}
]
]
}
......@@ -8,8 +8,13 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.19.2",
"core-js": "^3.6.4",
"md5": "^2.2.1",
"qs": "^6.9.1",
"vant": "^2.5.5",
"vue": "^2.6.11",
"vue-meta": "^2.3.3",
"vue-router": "^3.1.5"
},
"devDependencies": {
......@@ -19,6 +24,7 @@
"@vue/cli-service": "~4.2.0",
"@vue/eslint-config-prettier": "^6.0.0",
"babel-eslint": "^10.0.3",
"babel-plugin-import": "^1.13.0",
"eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.1.1",
"eslint-plugin-vue": "^6.1.2",
......
module.exports = {
semi: false,
singleQuote: true
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover"
/>
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title>紫荆校友圈</title>
<script>
;(function(win, doc) {
function resizeRoot() {
var wWidth =
screen.width > 0
? win.innerWidth >= screen.width || win.innerWidth == 0
? screen.width
: win.innerWidth
: win.innerWidth,
wFsize
wFsize = ((wWidth > 750 ? 750 : wWidth) / 375) * 100
doc.documentElement.style.fontSize = wFsize + 'px'
}
resizeRoot()
win.addEventListener('resize', resizeRoot, false)
})(window, document)
</script>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
<strong
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
properly without JavaScript enabled. Please enable it to
continue.</strong
>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
......
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<router-view />
<router-view :key="$route.fullPath" />
</div>
</template>
<style lang="scss">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
* {
margin: 0;
padding: 0;
}
#nav {
padding: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
#app {
max-width: 750px;
min-height: 100vh;
margin: 0 auto;
background-color: #fff;
}
</style>
import httpRequest from '@/utils/axios'
// 登录
export function login(data) {
return httpRequest({
url: process.env.VUE_APP_LOGIN_API + '/api/user_center/login',
method: 'post',
data
})
}
// 重置密码
export function resetPassword(data) {
return httpRequest({
url: process.env.VUE_APP_LOGIN_API + '/api/user_center/reset_password',
method: 'post',
data
})
}
// 发送重置验证码
export function sendResetPasswordCode(data) {
return httpRequest({
url:
process.env.VUE_APP_LOGIN_API +
'/api/user_center/send_reset_password_code',
method: 'post',
data
})
}
html * {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
outline: none;
-webkit-text-size-adjust: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
body,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
p,
blockquote,
dl,
dt,
dd,
ul,
ol,
li,
pre,
form,
fieldset,
legend,
button,
input,
textarea,
th,
td {
margin: 0;
padding: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: 100%;
}
ul,
ol,
li {
list-style: none;
}
em,
i {
font-style: normal;
}
strong,
b {
font-weight: normal;
}
img {
border: none;
}
input,
img {
vertical-align: middle;
}
a {
color: inherit;
text-decoration: none;
}
input,
button,
select,
textarea {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-appearance: none;
border: 0;
border-radius: 0;
}
textarea:focus {
outline: 0;
}
html {
font-size: 100px;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
body {
font-size: 14px;
line-height: 1.4;
color: #333;
font-family: -apple-system-font, 'Helvetica Neue', 'PingFang SC',
'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
background-color: #f4f4f4;
}
.fixed-box {
height: 70px;
padding: 15px 0;
}
.fixed-inner {
position: fixed;
left: 0;
right: 0;
bottom: 0;
padding: 15px 30px;
max-width: 750px;
margin: 0 auto;
background: rgba(255, 255, 255, 1);
box-shadow: 0px -4px 8px 0px rgba(0, 0, 0, 0.05);
}
.fixed-button {
height: 40px;
line-height: 40px;
text-align: center;
color: #fff;
background: linear-gradient(
180deg,
rgba(255, 155, 150, 1) 0%,
rgba(206, 62, 58, 1) 100%
);
border-radius: 5px;
cursor: pointer;
}
.empty {
margin-top: 100px;
padding-top: 140px;
font-size: 15px;
color: #333;
background: url('~@/assets/img/icon_warning.png') no-repeat center top;
background-size: 93px 93px;
text-align: center;
}
.form-tips {
padding: 0 30px 10px;
font-size: 12px;
color: #999;
}
.form {
padding: 0 14px 30px;
}
.form .van-cell {
flex-direction: column;
}
.form input.van-field__control,
.form textarea.van-field__control {
height: 40px;
padding: 0 20px;
border: 1px solid #999;
}
.form .van-field__label {
margin-bottom: 10px;
}
.form .van-field--error .van-field__control,
.form .van-field--error .van-field__control::placeholder {
color: #999;
-webkit-text-fill-color: currentColor;
}
<template>
<div class="card" @click="onClick">
<div class="card-main">
<div class="card-title">{{ data.title }}</div>
<div class="card-publish">
<div class="card-user">
<div class="card-user__avatar"></div>
<div class="card-user__nickname">赵瑾龙</div>
</div>
<div class="card-publish__time">44分钟前</div>
</div>
</div>
<div class="card-pic"></div>
</div>
</template>
<script>
export default {
name: 'Card',
props: { data: Object },
methods: {
onClick() {
this.$router.push({ name: 'item', query: this.$route.query })
}
}
}
</script>
<style lang="scss" scoped>
.card {
display: flex;
margin: 0 20px;
padding: 20px 0;
border-bottom: 1px solid #f5f5f5;
}
.card-title {
font-size: 14px;
color: #666;
}
.card-main {
flex: 1;
overflow: hidden;
}
.card-publish {
display: flex;
align-items: center;
margin-top: 15px;
}
.card-user {
display: flex;
align-items: center;
flex: 1;
overflow: hidden;
}
.card-user__avatar {
width: 25px;
height: 25px;
background-color: #ccc;
border-radius: 50%;
overflow: hidden;
}
.card-user__nickname {
padding-left: 10px;
font-size: 12px;
color: #ccc;
}
.card-publish__time {
padding-left: 10px;
font-size: 12px;
color: #ccc;
}
.card-pic {
width: 138px;
height: 78px;
margin-left: 10px;
}
</style>
<template>
<van-button
native-type="button"
:disabled="currentDisabled"
:loading="loading"
>
{{ curretnValue }}
</van-button>
</template>
<script>
export default {
name: 'CountdownButton',
props: {
step: { type: Number, default: 1000 },
disabled: { type: Boolean, default: false },
seconds: { type: Number, default: 60 },
defaultValue: { type: String, default: '发送验证码' }
},
data() {
return {
currentDisabled: false,
currentSeconds: 0,
loading: false,
timer: null
}
},
computed: {
curretnValue() {
let longTime = this.seconds - this.currentSeconds
return longTime < this.seconds ? `${longTime}秒后重发` : this.defaultValue
}
},
methods: {
genTimer() {
this.timer && clearInterval(this.timer)
this.timer = setInterval(() => {
this.currentSeconds++
if (this.currentSeconds === this.seconds) {
this.stop()
}
}, this.step)
},
start() {
this.loading = false
this.currentDisabled = true
this.genTimer()
},
stop() {
this.timer && clearInterval(this.timer)
this.currentSeconds = 0
this.currentDisabled = false
}
}
}
</script>
<template>
<van-form
ref="form"
class="form"
validate-trigger="onChange"
v-bind="$attrs"
v-on="$listeners"
>
<template v-for="(item, index) in fields">
<div class="form-item" :key="index">
<!-- 时间 -->
<template v-if="item.fieldType === 'datetime'">
<van-field
readonly
clickable
:border="false"
v-bind="item"
v-model="ruleForm[item.name]"
@click="showPicker('datetime', item.name)"
/>
</template>
<!-- 选择 -->
<template v-else-if="item.fieldType === 'select'">
<van-field
readonly
clickable
:border="false"
v-bind="item"
v-model="ruleForm[item.name]"
@click="showPicker('select', item.name)"
/>
</template>
<!-- 上传图片 -->
<van-field
:border="false"
:label="item.label"
v-else-if="item.fieldType === 'uploader'"
>
<template #input>
<van-uploader v-model="ruleForm[item.name]" />
</template>
</van-field>
<!-- 文本框 -->
<van-field
:border="false"
v-bind="item"
v-model="ruleForm[item.name]"
v-else
/>
<!-- 时间选择器 -->
<van-popup v-model="pickerVisible" position="bottom">
<van-datetime-picker
type="datetime"
:value="pickerValue"
:min-date="minDate"
@confirm="onTimePickerConfirm"
@cancel="pickerVisible = false"
v-if="pickerValue === 'datetime'"
/>
<van-picker
show-toolbar
:columns="columns"
@confirm="onPickerConfirm"
@cancel="pickerVisible = false"
v-if="pickerValue === 'select'"
/>
</van-popup>
</div>
</template>
</van-form>
</template>
<script>
export default {
name: 'VForm',
props: {
params: {
type: Object,
default() {
return {}
}
},
fields: {
type: Array,
required: true,
default() {
return []
}
}
},
data() {
return {
ruleForm: this.params,
pickerVisible: false,
pickerType: '',
pickerName: '',
pickerValue: '',
minDate: new Date()
}
},
methods: {
showPicker(fieldType, name) {
this.pickerVisible = true
this.pickerValue = this.ruleForm[name]
},
showDatetimePicker(name) {
this.pickerVisible = true
this.pickerName = name
this.pickerValue = this.ruleForm[name]
},
onTimePickerConfirm(time) {
this.ruleForm[this.pickerName] = time
this.pickerVisible = false
},
onPickerConfirm(value) {
this.ruleForm[this.pickerName] = value
this.pickerVisible = false
},
submit() {
return this.$refs.form.submit()
}
}
}
</script>
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br />
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener"
>vue-cli documentation</a
>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel"
target="_blank"
rel="noopener"
>babel</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router"
target="_blank"
rel="noopener"
>router</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint"
target="_blank"
rel="noopener"
>eslint</a
>
</li>
</ul>
<h3>Essential Links</h3>
<ul>
<li>
<a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
</li>
<li>
<a href="https://forum.vuejs.org" target="_blank" rel="noopener"
>Forum</a
>
</li>
<li>
<a href="https://chat.vuejs.org" target="_blank" rel="noopener"
>Community Chat</a
>
</li>
<li>
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener"
>Twitter</a
>
</li>
<li>
<a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
</li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li>
<a href="https://router.vuejs.org" target="_blank" rel="noopener"
>vue-router</a
>
</li>
<li>
<a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
</li>
<li>
<a
href="https://github.com/vuejs/vue-devtools#vue-devtools"
target="_blank"
rel="noopener"
>vue-devtools</a
>
</li>
<li>
<a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener"
>vue-loader</a
>
</li>
<li>
<a
href="https://github.com/vuejs/awesome-vue"
target="_blank"
rel="noopener"
>awesome-vue</a
>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String
}
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
<template>
<div class="main-layout">
<header class="main-header">
<menu class="menu" :class="{ 'is-show': menuVisible }">
<div class="inner">
<div class="menu-icon" @click="toggleMenu">
<span></span><span></span><span></span>
</div>
<ul class="menu-list">
<li @click="toPage({ name: 'list', query: { tab: '0' } })">
热门推荐
</li>
<li @click="toPage({ name: 'list', query: { tab: '1' } })">
我参与的
</li>
<li @click="toPage({ name: 'list', query: { tab: '2' } })">
我发起的
</li>
<li @click="$router.back()">返回上一页</li>
</ul>
</div>
</menu>
</header>
<div class="main-body">
<router-view />
</div>
</div>
</template>
<script>
export default {
name: 'PageContainer',
data() {
return {
menuVisible: false
}
},
methods: {
toggleMenu() {
this.menuVisible = !this.menuVisible
},
toPage(route) {
this.menuVisible = false
this.$router.push({
name: route.name,
query: Object.assign({}, this.$route.query, route.query)
})
}
}
}
</script>
<style lang="scss">
.menu {
height: 60px;
}
.menu .inner {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 60px;
padding: 20px 30px;
z-index: 100;
background-color: #fff;
max-width: 750px;
margin: 0 auto;
}
.menu.is-show {
.menu-list {
display: block;
}
.menu-icon {
width: 18px;
height: 20px;
flex-direction: inherit;
}
.menu-icon span {
width: 2px;
height: 18px;
}
}
.menu-icon {
position: absolute;
right: 30px;
width: 20px;
height: 18px;
cursor: pointer;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.menu-icon span {
width: 20px;
height: 2px;
background: #333;
}
.menu-list {
position: absolute;
top: 20px;
right: 25px;
display: none;
margin-top: 30px;
width: 180px;
background: #fff;
box-shadow: 0px 2px 20px 0px rgba(0, 0, 0, 0.2);
li {
height: 60px;
line-height: 60px;
color: #333;
text-align: center;
border-top: 1px solid #f5f5f5;
cursor: pointer;
&:first-child {
border: 0;
}
}
&::before {
position: absolute;
top: -6px;
right: 8px;
content: ' ';
display: block;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
border-width: 6px;
border-top-width: 0;
border-bottom-color: #fff;
}
}
</style>
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import Vue from 'vue'
import App from './App.vue'
import router from './router'
// import store from '@/store'
Vue.config.productionTip = false;
// vue-meta
import VueMeta from 'vue-meta'
Vue.use(VueMeta)
// vant
import { Notify } from 'vant'
Vue.use(Notify)
import { Dialog } from 'vant'
Vue.use(Dialog)
import { Popup } from 'vant'
Vue.use(Popup)
import { Overlay } from 'vant'
Vue.use(Overlay)
import { Tab, Tabs } from 'vant'
Vue.use(Tab)
Vue.use(Tabs)
import { Form } from 'vant'
Vue.use(Form)
import { Field } from 'vant'
Vue.use(Field)
import { Button } from 'vant'
Vue.use(Button)
import { Checkbox, CheckboxGroup } from 'vant'
Vue.use(Checkbox)
Vue.use(CheckboxGroup)
import { RadioGroup, Radio } from 'vant'
Vue.use(Radio)
Vue.use(RadioGroup)
import { DatetimePicker } from 'vant'
Vue.use(DatetimePicker)
import { Uploader } from 'vant'
Vue.use(Uploader)
import { List } from 'vant'
Vue.use(List)
// 公共css
import '@/assets/css/base.css'
Vue.config.productionTip = false
new Vue({
// store,
router,
render: h => h(App)
}).$mount("#app");
}).$mount('#app')
import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";
import Vue from 'vue'
import VueRouter from 'vue-router'
import Layout from '@/components/Layout.vue'
Vue.use(VueRouter);
Vue.use(VueRouter)
const routes = [
{ path: '*', redirect: '/list' },
{ path: '/', redirect: '/list' },
{
path: "/",
name: "Home",
component: Home
name: 'login',
path: '/login',
component: () => import('@/views/Login.vue')
},
{
path: "/about",
name: "About",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "../views/About.vue")
name: 'list',
path: '/list',
component: () => import('@/views/List.vue')
},
{
path: '/item',
component: Layout,
children: [
{
name: 'item',
path: '',
component: () => import('@/views/Item.vue')
}
]
},
{
path: '/create',
component: Layout,
children: [
{
name: 'create',
path: '',
component: () => import('@/views/Create.vue')
}
]
}
];
]
const router = new VueRouter({
mode: "history",
mode: 'history',
base: process.env.BASE_URL,
routes
});
})
export default router;
export default router
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
menuCollapse: false
},
mutations: {
toggleMenuCollapse(state, collapse) {
state.menuCollapse = collapse
}
},
actions: {}
})
import axios from 'axios'
import qs from 'qs'
import { Toast } from 'vant'
import router from '@/router'
const httpRequest = axios.create({
// baseURL: process.env.VUE_APP_BASE_API,
timeout: 60000,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
})
// 请求拦截
httpRequest.interceptors.request.use(
function(config) {
if (
config.headers['Content-Type'] === 'application/x-www-form-urlencoded'
) {
config.data = qs.stringify(config.data)
}
return config
},
function(error) {
return Promise.reject(error)
}
)
// 响应拦截
httpRequest.interceptors.response.use(
function(response) {
return response.data
},
function(error) {
if (error.response) {
const { status } = error.response.data
if (status === 403) {
router.replace({
path: '/login',
query: { redirect_uri: encodeURIComponent(window.location.href) }
})
}
} else {
Toast({ type: 'error', message: error })
}
return Promise.reject(error)
}
)
export default httpRequest
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>
<template>
<div class="main">
<v-form ref="form" :fields="page.form.fields" @submit="onSubmit"></v-form>
<div class="fixed-box">
<div class="fixed-inner">
<div class="fixed-button" @click="onSubmit">发布</div>
</div>
</div>
</div>
</template>
<script>
import VForm from '@/components/Form'
const pages = {
0: {
title: '发布活动',
form: {
fields: [
{
name: 'title',
label: '主题',
required: true,
placeholder: '请输入活动主题',
rules: [{ required: true, message: '请输入活动主题' }]
},
{
fieldType: 'uploader',
name: 'uploader',
label: '封面',
placeholder: '请上传活动封面'
},
{
type: 'textarea',
name: 'content',
label: '内容',
required: true,
placeholder: '请输入活动内容',
rules: [{ required: true, message: '请输入活动内容' }]
},
{
fieldType: 'datetime',
name: 'time',
label: '时间',
required: true,
placeholder: '请选择活动时间',
rules: [{ required: true, message: '请选择活动时间' }]
},
{
name: 'city',
label: '城市',
required: true,
placeholder: '请输入活动城市',
rules: [{ required: true, message: '请输入活动城市' }]
},
{
name: 'address',
label: '具体地址',
required: true,
placeholder: '请输入活动具体地址',
rules: [{ required: true, message: '请输入活动具体地址' }]
},
{
type: 'digit',
name: 'count',
label: '希望人数',
required: true,
placeholder: '请输入希望人数',
rules: [{ required: true, message: '请输入希望人数' }]
}
]
}
},
1: {
title: '发布需求',
form: {
fields: [
{
fieldType: 'select',
name: 'type',
label: '类型',
required: true,
placeholder: '请选择需求类型',
rules: [{ required: true, message: '请选择需求类型' }]
},
{
name: 'title',
label: '主题',
required: true,
placeholder: '请输入需求主题',
rules: [{ required: true, message: '请输入需求主题' }]
},
{
type: 'textarea',
name: 'content',
label: '内容',
required: true,
placeholder: '请输入需求内容',
rules: [{ required: true, message: '请输入需求内容' }]
}
]
}
}
}
export default {
name: 'Create',
components: { VForm },
metaInfo() {
return {
title: this.page.title
}
},
data() {
return {}
},
computed: {
page() {
const publishType = this.$route.query.publish_type || '0'
return pages[publishType] || {}
}
},
methods: {
onSubmit() {
this.$refs.form.submit()
}
}
}
</script>
<style lang="scss"></style>
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png" />
<HelloWorld msg="Welcome to Your Vue.js App" />
</div>
</template>
<script>
// @ is an alias to /src
import HelloWorld from "@/components/HelloWorld.vue";
export default {
name: "Home",
components: {
HelloWorld
}
};
</script>
<template>
<div class="detail"></div>
</template>
<script>
export default {
metaInfo: {
title: '文章内容'
},
data() {
return {}
}
}
</script>
<style lang="scss"></style>
<template>
<div class="list">
<van-tabs v-model="tabActive">
<van-tab title="热门推荐" name="0">热门推荐</van-tab>
<van-tab title="我参与的" name="1">我参与的</van-tab>
<van-tab title="我发起的" name="2">我发起的</van-tab>
</van-tabs>
<van-list
v-model="loading"
:finished="finished"
finished-text="没有更多了"
@load="onLoad"
v-if="list.length"
>
<card v-for="item in list" :data="item" :key="item.id"></card>
</van-list>
<div class="empty" v-else>{{ page.emptyText }}</div>
<div class="publish-button" @click="publishVisible = true"></div>
<van-popup v-model="publishVisible" position="bottom">
<div class="publish">
<ul>
<li @click="toCreatePage(0)">
<img src="~@/assets/img/icon_publish1.png" />发布活动
</li>
<li @click="toCreatePage(1)">
<img src="~@/assets/img/icon_publish2.png" />发布需求
</li>
</ul>
</div>
</van-popup>
</div>
</template>
<script>
import Card from '@/components/Card.vue'
export default {
components: { Card },
metaInfo: {
title: '紫荆校友圈'
},
data() {
return {
tabActive: '0',
publishVisible: false,
list: [
{
id: '0',
title: '紫荆-索菲亚上海校友会 || 齐聚南京,体验数字化魅力',
time: '2020.02.10',
user: '王鹏飞',
time2: '2020.02.10'
}
],
loading: false,
finished: true
}
},
watch: {
$route: {
immediate: true,
depp: true,
handler(route) {
this.tabActive = route.query.tab || '0'
}
}
},
methods: {
getList() {},
onLoad() {
this.getList()
},
toCreatePage(type) {
this.$router.push({
name: 'create',
query: Object.assign(this.$route.query, { publish_type: type })
})
}
}
}
</script>
<style lang="scss">
.list {
}
.publish-button {
position: fixed;
left: 50%;
bottom: 20px;
width: 72px;
height: 72px;
background: url('~@/assets/img/icon_plus.png') no-repeat;
background-size: contain;
z-index: 100;
cursor: pointer;
transform: translateX(-50%);
}
.publish {
padding: 24px 0;
ul {
display: flex;
align-items: center;
justify-content: center;
}
li {
width: 70px;
margin: 0 35px;
text-align: center;
color: #f38580;
}
img {
width: 100%;
}
}
</style>
<template>
<div class="login">
<div class="login-hd">
<div class="logo" title="紫荆教育"></div>
<h2 class="login-title">欢迎回来</h2>
</div>
<div class="login-bd">
<div class="login-form">
<div class="login-form__item">
<input
type="text"
class="login-input"
placeholder="手机/邮箱/用户名"
v-model="ruleForm.login_name"
/>
</div>
<div class="login-form__item">
<input
type="password"
class="login-input"
placeholder="密码"
v-model="ruleForm.password"
/>
</div>
<div class="login-form__item">
<van-checkbox v-model="checked" shape="square"
>下次自动登录</van-checkbox
>
</div>
<div class="login-form__item">
<div class="login-button" @click="onSubmit">登录</div>
</div>
</div>
</div>
<div class="login-ft">
<p class="login-tips">
登录遇到困难?请点击
<span class="forget-password" @click="passwordVisible = true">
找回密码
</span>
</p>
</div>
<password v-model="passwordVisible" />
</div>
</template>
<script>
import md5 from 'md5'
import * as api from '@/api/account'
import Password from './Password.vue'
export default {
components: { Password },
data() {
return {
ruleForm: {
login_name: '',
password: ''
},
checked: false,
passwordVisible: false
}
},
computed: {
// 重定向地址
redirectURI() {
const { query } = this.$route
return query.redirect_uri ? decodeURIComponent(query.redirect_uri) : ''
}
},
methods: {
// 提交
onSubmit() {
if (!this.ruleForm.login_name) {
this.$notify('请输入手机/邮箱/用户名')
} else if (!this.ruleForm.password) {
this.$notify('请输入密码')
} else {
this.loginRequest()
}
},
// 登录
loginRequest() {
let data = Object.assign({}, this.ruleForm, { service: 'h5.ezijing.com' })
data.password = md5(
'uokoaduw' +
data.password
.split('')
.reverse()
.join('') +
'auhgniq'
)
api
.login(data)
.then(response => {
this.loginSuccess(response)
})
.catch(error => {
error.response && this.$notify(error.response.data.message)
})
},
// 登录成功
loginSuccess(response) {
if (response.ticket) {
if (this.redirectURI) {
window.location.href = this.redirectURI
} else {
this.$router.replace('/')
}
} else {
this.$notify('登录失败,请重试')
}
}
}
}
</script>
<style lang="scss">
.login {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.logo {
width: 136px;
height: 44px;
background: url('~@/assets/img/logo.png') no-repeat;
background-size: contain;
}
.login-hd {
min-height: 170px;
padding: 30px 0 0 30px;
background: url('~@/assets/img/login_bg.png') no-repeat right top;
background-size: 152px 170px;
}
.login-title {
margin-top: 6px;
font-size: 50px;
color: #333;
}
.login-bd {
flex: 1;
}
.login-form {
padding: 40px 0 90px;
overflow: hidden;
}
.login-form__item {
padding: 0 30px;
}
.login-input {
padding: 0 20px;
width: 100%;
height: 40px;
font-size: 15px;
color: #999;
background: rgba(255, 255, 255, 1);
box-shadow: 0px 5px 15px 0px rgba(0, 0, 0, 0.06);
border-radius: 20px;
box-sizing: border-box;
margin-bottom: 30px;
}
.login-checkbox {
width: 15px;
height: 15px;
border: 1px solid rgba(153, 153, 153, 1);
}
.login-button {
float: right;
height: 60px;
padding-right: 90px;
font-size: 15px;
line-height: 60px;
background: url('~@/assets/img/login_button.png') no-repeat right center;
background-size: contain;
cursor: pointer;
}
.login-ft {
padding: 40px 0;
}
.login-tips {
text-align: center;
font-size: 12px;
color: #999;
.forget-password {
color: #1989fa;
}
}
</style>
<template>
<van-popup
v-model="show"
overlay-class="password-overlay"
class="password-popup"
position="top"
@closed="onClosed"
>
<div class="password" v-if="!isSuccess">
<van-form
ref="form"
class="form"
validate-trigger="onChange"
@submit="onSubmit"
>
<h2 class="password-title">修改密码</h2>
<van-field
v-model="ruleForm.contact"
name="contact"
placeholder="请输入手机号/邮箱"
:border="false"
:rules="[
{ required: true, message: '请输入手机号/邮箱' },
{ message: '手机号/邮箱格式错误' }
]"
/>
<van-field
v-model="ruleForm.code"
name="code"
placeholder="请输入验证码"
:border="false"
:rules="[{ required: true, message: '请输入验证码' }]"
>
<template slot="button">
<countdown-button
@click.native="onSendCode"
ref="countdown"
></countdown-button>
</template>
</van-field>
<van-field
v-model="ruleForm.new_password"
name="new_password"
type="password"
placeholder="6-20个字符,只能数字/字母/标点符号"
:border="false"
:rules="[{ required: true, message: '请输入密码' }]"
/>
<van-field
v-model="ruleForm.primary_password"
type="password"
name="primary_password"
placeholder="再次确认密码"
:border="false"
:rules="[
{ required: true, message: '请输入确认密码' },
{
trigger: 'onBlur',
validator: validatePass,
message: '两次输入密码不一致'
}
]"
/>
<div style="margin: 16px 16px 10px;">
<van-button block native-type="submit" class="password-button">
立即更改
</van-button>
</div>
</van-form>
</div>
<div class="password-success" v-else>
<span class="password-success__icon"></span>
<span class="password-success__text">密码修改成功</span>
<van-button block class="password-button" @click="onClosed">
立即登录
</van-button>
</div>
</van-popup>
</template>
<script>
import * as api from '@/api/account'
import CountdownButton from '@/components/CountdownButton'
export default {
components: { CountdownButton },
props: {
value: { type: Boolean, default: false }
},
data() {
return {
show: this.value,
isSuccess: false,
ruleForm: {
contact: '',
code: '',
new_password: '',
primary_password: ''
}
}
},
watch: {
value: {
immediate: true,
handler(value) {
this.show = value
}
}
},
methods: {
onClosed() {
this.isSuccess = false
this.$emit('input', false)
},
onSubmit() {
this.resetPasswordRequest()
},
// 发送验证码
onSendCode() {
this.$refs.form.validate('contact').then(response => {
if (!response) {
// 开始倒计时
this.$refs['countdown'].start()
this.sendCodeRequest()
}
})
},
// 验证码
sendCodeRequest() {
api
.sendResetPasswordCode({
contact: this.ruleForm.contact,
source_type: 3
})
.then(() => {
this.$notify({ type: 'success', message: '验证码发送成功' })
})
.catch(error => {
// 停止计时
this.$refs['countdown'].stop()
error.response && this.$notify(error.response.data.message)
})
},
// 重置密码
resetPasswordRequest() {
let data = Object.assign({}, this.ruleForm, { service: 'h5.ezijing.com' })
api
.resetPassword(data)
.then(() => {
this.isSuccess = true
})
.catch(error => {
error.response && this.$notify(error.response.data.message)
})
},
// 确认密码校验
validatePass(value) {
return value === this.ruleForm.new_password
}
}
}
</script>
<style lang="scss">
.password-popup {
margin: 30px auto;
right: 0;
max-width: 690px;
width: calc(100vw - 60px);
box-shadow: 0px 10px 20px 0px rgba(0, 0, 0, 0.1);
}
.password {
min-height: 440px;
}
.password-title {
padding: 30px 16px 10px;
font-size: 18px;
color: #333;
text-align: center;
}
.password-overlay {
background-color: transparent;
}
.password-button {
background: linear-gradient(
180deg,
rgba(255, 155, 150, 1) 0%,
rgba(206, 62, 58, 1) 100%
);
color: #fff;
border: 0;
}
.password-success {
display: flex;
min-height: 440px;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 30px;
}
.password-success__icon {
display: inline-block;
width: 100px;
height: 100px;
background: url('~@/assets/img/icon_success.png') no-repeat;
background-size: contain;
}
.password-success__text {
display: block;
margin: 40px 0 55px;
font-size: 24px;
color: #333;
}
</style>
module.exports = {
devServer: {
host: 'dev.ezijing.com',
proxy: {
'/api/user_center': {
target: 'https://e-learning3.ezijing.com'
}
}
}
}
......@@ -730,7 +730,7 @@
levenary "^1.1.1"
semver "^5.5.0"
"@babel/runtime@^7.8.4":
"@babel/runtime@7.x", "@babel/runtime@^7.0.0", "@babel/runtime@^7.8.4":
version "7.8.7"
resolved "https://registry.npm.taobao.org/@babel/runtime/download/@babel/runtime-7.8.7.tgz?cache=0&sync_timestamp=1583373792636&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fruntime%2Fdownload%2F%40babel%2Fruntime-7.8.7.tgz#8fefce9802db54881ba59f90bb28719b4996324d"
integrity sha1-j+/OmALbVIgbpZ+Quyhxm0mWMk0=
......@@ -872,6 +872,11 @@
resolved "https://registry.npm.taobao.org/@types/q/download/@types/q-1.5.2.tgz?cache=0&sync_timestamp=1580864603569&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fq%2Fdownload%2F%40types%2Fq-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
integrity sha1-aQoUdbhPKohP0HzXl8APXzE1bqg=
"@vant/icons@1.2.1":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@vant/icons/-/icons-1.2.1.tgz#309fecb97a4989866f045ce676b545c454701c8f"
integrity sha512-5ivsKQR4ySbdBW5UPoQDVqO6rdc1um3rvq/0VL+ZSA7Y3MdBQ3E4/NL0hoAY5/sZZeYfIDKEP21gpjUzdeEDQQ==
"@vue/babel-helper-vue-jsx-merge-props@^1.0.0":
version "1.0.0"
resolved "https://registry.npm.taobao.org/@vue/babel-helper-vue-jsx-merge-props/download/@vue/babel-helper-vue-jsx-merge-props-1.0.0.tgz#048fe579958da408fb7a8b2a3ec050b50a661040"
......@@ -1560,6 +1565,13 @@ aws4@^1.8.0:
resolved "https://registry.npm.taobao.org/aws4/download/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e"
integrity sha1-fjPY99RJs/ZzzXLeuavcVS2+Uo4=
axios@^0.19.2:
version "0.19.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==
dependencies:
follow-redirects "1.5.10"
babel-eslint@^10.0.3:
version "10.1.0"
resolved "https://registry.npm.taobao.org/babel-eslint/download/babel-eslint-10.1.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-eslint%2Fdownload%2Fbabel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232"
......@@ -1589,6 +1601,14 @@ babel-plugin-dynamic-import-node@^2.3.0:
dependencies:
object.assign "^4.1.0"
babel-plugin-import@^1.13.0:
version "1.13.0"
resolved "https://registry.yarnpkg.com/babel-plugin-import/-/babel-plugin-import-1.13.0.tgz#c532fd533df9db53b47d4d4db3676090fc5c07a5"
integrity sha512-bHU8m0SrY89ub2hBBuYjbennOeH0YUYkVpH6jxKFk0uD8rhN+0jNHIPtXnac+Vn7N/hgkLGGDcIoYK7je3Hhew==
dependencies:
"@babel/helper-module-imports" "^7.0.0"
"@babel/runtime" "^7.0.0"
balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
......@@ -2025,6 +2045,11 @@ chardet@^0.7.0:
resolved "https://registry.npm.taobao.org/chardet/download/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
integrity sha1-kAlISfCTfy7twkJdDSip5fDLrZ4=
charenc@~0.0.1:
version "0.0.2"
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
check-types@^8.0.3:
version "8.0.3"
resolved "https://registry.npm.taobao.org/check-types/download/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552"
......@@ -2491,6 +2516,11 @@ cross-spawn@^7.0.0:
shebang-command "^2.0.0"
which "^2.0.1"
crypt@~0.0.1:
version "0.0.2"
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
crypto-browserify@^3.11.0:
version "3.12.0"
resolved "https://registry.npm.taobao.org/crypto-browserify/download/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
......@@ -2691,6 +2721,13 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
dependencies:
ms "2.0.0"
debug@=3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
debug@^3.0.0, debug@^3.1.1, debug@^3.2.5:
version "3.2.6"
resolved "https://registry.npm.taobao.org/debug/download/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
......@@ -2737,6 +2774,11 @@ deepmerge@^1.5.2:
resolved "https://registry.npm.taobao.org/deepmerge/download/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753"
integrity sha1-EEmdhohEza1P7ghC34x/bwyVp1M=
deepmerge@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
default-gateway@^4.2.0:
version "4.2.0"
resolved "https://registry.npm.taobao.org/default-gateway/download/default-gateway-4.2.0.tgz?cache=0&sync_timestamp=1583993714392&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdefault-gateway%2Fdownload%2Fdefault-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b"
......@@ -3620,6 +3662,13 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3"
readable-stream "^2.3.6"
follow-redirects@1.5.10:
version "1.5.10"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==
dependencies:
debug "=3.1.0"
follow-redirects@^1.0.0:
version "1.10.0"
resolved "https://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.10.0.tgz#01f5263aee921c6a54fb91667f08f4155ce169eb"
......@@ -4402,7 +4451,7 @@ is-binary-path@~2.1.0:
dependencies:
binary-extensions "^2.0.0"
is-buffer@^1.1.5:
is-buffer@^1.1.5, is-buffer@~1.1.1:
version "1.1.6"
resolved "https://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha1-76ouqdqg16suoTqXsritUf776L4=
......@@ -5021,6 +5070,15 @@ md5.js@^1.3.4:
inherits "^2.0.1"
safe-buffer "^5.1.2"
md5@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9"
integrity sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=
dependencies:
charenc "~0.0.1"
crypt "~0.0.1"
is-buffer "~1.1.1"
mdn-data@2.0.4:
version "2.0.4"
resolved "https://registry.npm.taobao.org/mdn-data/download/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b"
......@@ -6450,6 +6508,11 @@ qs@6.7.0:
resolved "https://registry.npm.taobao.org/qs/download/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
integrity sha1-QdwaAV49WB8WIXdr4xr7KHapsbw=
qs@^6.9.1:
version "6.9.1"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.1.tgz#20082c65cb78223635ab1a9eaca8875a29bf8ec9"
integrity sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA==
qs@~6.5.2:
version "6.5.2"
resolved "https://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
......@@ -7943,6 +8006,16 @@ validate-npm-package-license@^3.0.1:
spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0"
vant@^2.5.5:
version "2.5.5"
resolved "https://registry.yarnpkg.com/vant/-/vant-2.5.5.tgz#4484e4224127a88a47147b35ab52a91bacc2e939"
integrity sha512-w7APepClXcEMFJvvYsJkNDWCCb+a5SR9eAMMIYM/1VCwn7r7AxoAtJSCaZsmw3vhSxnMSnM/+Ftz7t3o0eoK4Q==
dependencies:
"@babel/runtime" "7.x"
"@vant/icons" "1.2.1"
"@vue/babel-helper-vue-jsx-merge-props" "^1.0.0"
vue-lazyload "1.2.3"
vary@~1.1.2:
version "1.1.2"
resolved "https://registry.npm.taobao.org/vary/download/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
......@@ -7984,6 +8057,11 @@ vue-hot-reload-api@^2.3.0:
resolved "https://registry.npm.taobao.org/vue-hot-reload-api/download/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2"
integrity sha1-UylVzB6yCKPZkLOp+acFdGV+CPI=
vue-lazyload@1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/vue-lazyload/-/vue-lazyload-1.2.3.tgz#901f9ec15c7e6ca78781a2bae4a343686bdedb2c"
integrity sha512-DC0ZwxanbRhx79tlA3zY5OYJkH8FYp3WBAnAJbrcuoS8eye1P73rcgAZhyxFSPUluJUTelMB+i/+VkNU/qVm7g==
vue-loader@^15.8.3:
version "15.9.1"
resolved "https://registry.npm.taobao.org/vue-loader/download/vue-loader-15.9.1.tgz#bd2ab8f3d281e51d7b81d15390a58424d142243e"
......@@ -7995,6 +8073,13 @@ vue-loader@^15.8.3:
vue-hot-reload-api "^2.3.0"
vue-style-loader "^4.1.0"
vue-meta@^2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/vue-meta/-/vue-meta-2.3.3.tgz#2a097f62817204b0da78be4d62aee0cb566eaee0"
integrity sha512-FmeekLkd5+BI7NFBnU4bEnTpVZqmu3q8ztW4R4U3GBQljgDM7QAuwMXs8/aJP0U1tjtxobX8T6HcyZXimGj1DQ==
dependencies:
deepmerge "^4.2.2"
vue-router@^3.1.5:
version "3.1.6"
resolved "https://registry.npm.taobao.org/vue-router/download/vue-router-3.1.6.tgz#45f5a3a3843e31702c061dd829393554e4328f89"
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论