丰都投票界面已完成
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import http from "./http";
|
||||
import Vue from "vue";
|
||||
import CryptoJS from "./crypto-js";
|
||||
import qs from 'query-string'
|
||||
|
||||
/**
|
||||
* 用户登录信息和方法
|
||||
@@ -136,6 +137,41 @@ export const user = {
|
||||
} else return Promise.reject(res.msg)
|
||||
})
|
||||
},
|
||||
getWechatToken({commit, dispatch}, params) {
|
||||
const encryptByDES = password => {
|
||||
let isIos = uni.getSystemInfoSync().system.toUpperCase == 'ios'
|
||||
let key = "thanks,villcloud"
|
||||
let iv = CryptoJS.enc.Latin1.parse(key)
|
||||
let encrypted = CryptoJS.AES.encrypt(password, iv, {
|
||||
iv: iv,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.ZeroPadding
|
||||
})
|
||||
if (isIos) {
|
||||
return encodeURIComponent(encrypted.toString());
|
||||
} else {
|
||||
return encrypted.toString();
|
||||
}
|
||||
}
|
||||
let {module} = params, action = "/auth/wechat-mp/token"
|
||||
return http.post(action, params, {
|
||||
withoutToken: true,
|
||||
module,
|
||||
params: {
|
||||
...params, grant_type: 'password',
|
||||
password: encryptByDES(params.password)
|
||||
},
|
||||
headers: {
|
||||
Authorization: "Basic d3htcDp3eG1w"
|
||||
}
|
||||
}).then(res => {
|
||||
if (res?.access_token) {
|
||||
const token = [res?.token_type, res?.access_token].join(" ").trim()
|
||||
commit("setToken", token)
|
||||
return token
|
||||
} else return Promise.reject(res.msg)
|
||||
})
|
||||
},
|
||||
getAccount({dispatch, commit}, config) {
|
||||
//获取企业微信后台账号信息
|
||||
return http.post("/admin/user/detail-phone", null, config).then(res => {
|
||||
@@ -161,6 +197,20 @@ export const user = {
|
||||
* 企微jssdk功能
|
||||
*/
|
||||
let timer = {}
|
||||
/**
|
||||
* 微信oauth2跳转链接
|
||||
* https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&agentid=AGENTID#wechat_redirect
|
||||
* @param params
|
||||
*/
|
||||
const oauth2Weixin = params => qs.stringifyUrl({
|
||||
url: "https://open.weixin.qq.com/connect/oauth2/authorize",
|
||||
query: {
|
||||
response_type: 'code',
|
||||
url: encodeURIComponent(location.href),
|
||||
...params
|
||||
},
|
||||
fragmentIdentifier: "wechat_redirect"
|
||||
})
|
||||
export const wxwork = {
|
||||
state: () => ({
|
||||
agentSignURL: "",
|
||||
@@ -218,27 +268,34 @@ export const wxwork = {
|
||||
})
|
||||
}
|
||||
},
|
||||
getCode({state, dispatch}, tryAgentSign = false) {
|
||||
let {corpid: corpId, suiteId, agentid: agentId} = state.config, url = location.href, REDIRECT_URI = encodeURIComponent(url), scope = "snsapi_privateinfo"
|
||||
getCode({state, dispatch}, params) {
|
||||
const excute = (tryAgentSign = false) => {
|
||||
if (!params.appid) {
|
||||
let {corpid: corpId, suiteId, agentid} = state.config, scope = "snsapi_privateinfo"
|
||||
if (/AppForm/.test(location.pathname)) {
|
||||
scope = "snsapi_base"
|
||||
} else if (suiteId) {
|
||||
corpId = suiteId
|
||||
scope = "snsapi_privateinfo"
|
||||
}
|
||||
params = {appid: corpId, agentid, scope}
|
||||
return new Promise((resolve, reject) => {
|
||||
if (corpId && scope) {
|
||||
let oauthURL = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&agentid=AGENTID#wechat_redirect'
|
||||
.replace(/APPID/g, corpId)
|
||||
.replace(/REDIRECT_URI/g, REDIRECT_URI)
|
||||
.replace(/SCOPE/g, scope)
|
||||
.replace(/AGENTID/g, agentId)
|
||||
console.log(location, oauthURL)
|
||||
const oauthURL = oauth2Weixin(params)
|
||||
location.replace(oauthURL)
|
||||
} else if (!tryAgentSign && corpId) {
|
||||
dispatch("agentSign", {corpId, suiteId}).then(() => dispatch("getCode", true)).then(() => resolve())
|
||||
dispatch("agentSign", {corpId, suiteId}).then(() => excute(true)).then(() => resolve())
|
||||
} else reject("URL缺少必要参数(corpId)")
|
||||
})
|
||||
} else new Promise((resolve, reject) => {
|
||||
const {appid} = params
|
||||
if (!!appid) {
|
||||
const oauthURL = oauth2Weixin(params)
|
||||
location.replace(oauthURL)
|
||||
} else reject("URL缺少必要参数(appid)")
|
||||
})
|
||||
}
|
||||
return excute()
|
||||
},
|
||||
injectJWeixin({state, commit, rootState}, apis) {
|
||||
const inject = (jsApiList) => new Promise((resolve, reject) => {
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
<slot/>
|
||||
</div>
|
||||
<u-gap v-else height="112"/>
|
||||
<div class="fixed" @click="$emit('click')">
|
||||
<div class="fixed" @click="$emit('click')" :style="{background}">
|
||||
<slot v-if="$slots.default"/>
|
||||
<div class="text" v-text="text"/>
|
||||
<div v-else class="text" :class="{circle}" v-text="text"/>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
@@ -15,7 +15,9 @@
|
||||
export default {
|
||||
name: "AiBottomBtn",
|
||||
props: {
|
||||
text: {default: ""}
|
||||
text: {default: ""},
|
||||
circle: Boolean,
|
||||
background: {default: "inherit"}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -37,6 +39,14 @@ export default {
|
||||
color: #FFFFFF;
|
||||
background: #1365DD;
|
||||
box-shadow: inset 0px 1px 0px 0px #EEEEEE;
|
||||
|
||||
&.circle {
|
||||
border-radius: 52px;
|
||||
line-height: 80px;
|
||||
flex-shrink: 0;
|
||||
padding: 0 70px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.transport {
|
||||
|
||||
55
src/components/AiHighlight.vue
Normal file
55
src/components/AiHighlight.vue
Normal file
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<section class="AiHighlight" :class="{bold,color}" v-html="html"/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AiHighlight",
|
||||
props: {
|
||||
value: {default: ""},
|
||||
content: {default: ""},
|
||||
keywords: {default: () => []},
|
||||
color: {default: ""},
|
||||
bold: Boolean
|
||||
},
|
||||
computed: {
|
||||
words: v => [v.keywords].flat(),
|
||||
html() {
|
||||
let {content, words, value} = this
|
||||
const reg = new RegExp(`(${words.join("|")})`, 'g')
|
||||
content = content?.replace(/(@v)/g, this.keywordRender(value))
|
||||
return !!words.join("|") ? content?.replace(reg, this.keywordRender('$1')) : content
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
keywordRender(word) {
|
||||
const {color} = this
|
||||
return `<p class="keyword" style="color:${color}">${word}</p>`
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
::v-deep.AiHighlight {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
|
||||
.keyword {
|
||||
display: block;
|
||||
width: auto;
|
||||
color: #26f;
|
||||
}
|
||||
|
||||
&.color {
|
||||
.keyword {
|
||||
}
|
||||
}
|
||||
|
||||
&.bold {
|
||||
.keyword {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -42,5 +42,7 @@ if (/saas/.test(location.pathname)) {//上架版
|
||||
if (/AppCountryAlbum/.test(location.pathname)) {//乡村相册版
|
||||
params = {action: "/app/wxcptp/portal/agentSign", corpId: "wpytYEDgAAcpXjmlYkYwKO60JDGDWrXg", suiteId: "ww0da13777658d1262"}
|
||||
}
|
||||
store.dispatch("agentSign", params).finally(() => app.$mount())
|
||||
if (/AppVote/.test(location.pathname)) {//微信公众号网页开发
|
||||
app.$mount()
|
||||
} else store.dispatch("agentSign", params).finally(() => app.$mount())
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
}
|
||||
},
|
||||
"/ns": {
|
||||
"target": "http://dvcp.sinoecare.net",
|
||||
"target": "http://192.168.1.87:12525",
|
||||
"changeOrigin": true,
|
||||
"pathRewrite": {
|
||||
"^/ns": "/"
|
||||
|
||||
108
src/project/fengdu/AppVote/AppVote.vue
Normal file
108
src/project/fengdu/AppVote/AppVote.vue
Normal file
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<section class="AppVote">
|
||||
<AiGroup title="前置图文" noBorder description>
|
||||
<u-parse :html="detail.frontDisplay"/>
|
||||
</AiGroup>
|
||||
<div class="voteItem" flex @click="handleDetail(1)">
|
||||
<div class="fill">
|
||||
<b class="mar-b8" v-text="`月落乌啼霜满天`"/>
|
||||
<div class="color-999 line3" v-text="`微信公众号是开发者或商家在微信公众平台上申请的应用账号,该帐号与QQ账号互通,该帐号与账号互通…`"/>
|
||||
</div>
|
||||
<div class="thumb">
|
||||
<span v-text="`12345票`"/>
|
||||
</div>
|
||||
</div>
|
||||
<AiGroup title="结尾图文" noBorder description>
|
||||
<u-parse :html="detail.endDisplay"/>
|
||||
</AiGroup>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState, mapActions} from "vuex"
|
||||
|
||||
export default {
|
||||
name: "AppVote",
|
||||
appName: "公众投票",
|
||||
computed: {
|
||||
...mapState(['user']),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
detail: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['getWechatToken', 'getCode']),
|
||||
getDetail() {
|
||||
this.$http.post("/app/vote/detail", null, {})
|
||||
},
|
||||
getList() {
|
||||
this.$http.post("/app/vote/list", null, {})
|
||||
},
|
||||
handleDetail(id) {
|
||||
uni.navigateTo({url: './voteDetail?id=' + id})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// this.getDetail()
|
||||
// this.getList()
|
||||
},
|
||||
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AppVote {
|
||||
min-height: 100vh;
|
||||
background: #fff;
|
||||
|
||||
.voteItem {
|
||||
height: 240px;
|
||||
border: 1px solid #CCCCCC;
|
||||
border-radius: 16px;
|
||||
margin: 0 32px 24px;
|
||||
padding: 24px;
|
||||
box-sizing: border-box;
|
||||
font-family: PingFangSC;
|
||||
|
||||
b {
|
||||
font-size: 34px;
|
||||
color: #333333;
|
||||
display: block;
|
||||
line-height: 48px;
|
||||
}
|
||||
|
||||
.line3 {
|
||||
display: -webkit-box;
|
||||
overflow: hidden;
|
||||
-webkit-line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.thumb {
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
margin-left: 24px;
|
||||
width: 192px;
|
||||
height: 192px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100%;
|
||||
background-color: #eee;
|
||||
|
||||
& > span {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
padding: 0 8px;
|
||||
line-height: 44px;
|
||||
background: #FF883C;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
57
src/project/fengdu/AppVote/voteDetail.vue
Normal file
57
src/project/fengdu/AppVote/voteDetail.vue
Normal file
@@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<section class="voteDetail">
|
||||
<u-parse :html="detail.endDisplay"/>
|
||||
<AiBottomBtn background="#fff">
|
||||
<div flex class="pad-l32 pad-r16 pad-b16 pad-t16">
|
||||
<AiHighlight class="fill color-999" content="当前票数:@v" value="21345" color="#FF6900"/>
|
||||
<div class="text circle mar-l16" @click="handleVote">投票</div>
|
||||
</div>
|
||||
</AiBottomBtn>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AiHighlight from "../../../components/AiHighlight";
|
||||
|
||||
export default {
|
||||
name: "voteDetail",
|
||||
components: {AiHighlight},
|
||||
appName: "投票详情",
|
||||
data() {
|
||||
return {
|
||||
detail: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getDetail() {
|
||||
this.$http.post("/app/vote/detail", null, {}).then(res => {
|
||||
if (res?.data) {
|
||||
this.detail = res.data
|
||||
document.title = this.detail.name
|
||||
}
|
||||
})
|
||||
},
|
||||
handleVote() {
|
||||
if (!this.user.token) {//未登录,获取openId和token
|
||||
this.$http.get("/app/appdvcpconfig/getMpAppid", {withoutToken: true}).then(res => {
|
||||
if (res?.code == 0 && res?.data) {
|
||||
this.getCode({scope: "snsapi_userinfo", appid: res.data})
|
||||
}
|
||||
})
|
||||
} else {//已登录,直接投票
|
||||
|
||||
}
|
||||
},
|
||||
},
|
||||
onShow() {
|
||||
this.getDetail()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.voteDetail {
|
||||
background: #F3F6F9;
|
||||
min-height: 100vh;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user