丰都投票界面已完成
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import http from "./http";
|
import http from "./http";
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import CryptoJS from "./crypto-js";
|
import CryptoJS from "./crypto-js";
|
||||||
|
import qs from 'query-string'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户登录信息和方法
|
* 用户登录信息和方法
|
||||||
@@ -136,6 +137,41 @@ export const user = {
|
|||||||
} else return Promise.reject(res.msg)
|
} 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) {
|
getAccount({dispatch, commit}, config) {
|
||||||
//获取企业微信后台账号信息
|
//获取企业微信后台账号信息
|
||||||
return http.post("/admin/user/detail-phone", null, config).then(res => {
|
return http.post("/admin/user/detail-phone", null, config).then(res => {
|
||||||
@@ -161,6 +197,20 @@ export const user = {
|
|||||||
* 企微jssdk功能
|
* 企微jssdk功能
|
||||||
*/
|
*/
|
||||||
let timer = {}
|
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 = {
|
export const wxwork = {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
agentSignURL: "",
|
agentSignURL: "",
|
||||||
@@ -218,27 +268,34 @@ export const wxwork = {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getCode({state, dispatch}, tryAgentSign = false) {
|
getCode({state, dispatch}, params) {
|
||||||
let {corpid: corpId, suiteId, agentid: agentId} = state.config, url = location.href, REDIRECT_URI = encodeURIComponent(url), scope = "snsapi_privateinfo"
|
const excute = (tryAgentSign = false) => {
|
||||||
if (/AppForm/.test(location.pathname)) {
|
if (!params.appid) {
|
||||||
scope = "snsapi_base"
|
let {corpid: corpId, suiteId, agentid} = state.config, scope = "snsapi_privateinfo"
|
||||||
} else if (suiteId) {
|
if (/AppForm/.test(location.pathname)) {
|
||||||
corpId = suiteId
|
scope = "snsapi_base"
|
||||||
scope = "snsapi_privateinfo"
|
} else if (suiteId) {
|
||||||
|
corpId = suiteId
|
||||||
|
scope = "snsapi_privateinfo"
|
||||||
|
}
|
||||||
|
params = {appid: corpId, agentid, scope}
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (corpId && scope) {
|
||||||
|
const oauthURL = oauth2Weixin(params)
|
||||||
|
location.replace(oauthURL)
|
||||||
|
} else if (!tryAgentSign && corpId) {
|
||||||
|
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 new Promise((resolve, reject) => {
|
return excute()
|
||||||
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)
|
|
||||||
location.replace(oauthURL)
|
|
||||||
} else if (!tryAgentSign && corpId) {
|
|
||||||
dispatch("agentSign", {corpId, suiteId}).then(() => dispatch("getCode", true)).then(() => resolve())
|
|
||||||
} else reject("URL缺少必要参数(corpId)")
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
injectJWeixin({state, commit, rootState}, apis) {
|
injectJWeixin({state, commit, rootState}, apis) {
|
||||||
const inject = (jsApiList) => new Promise((resolve, reject) => {
|
const inject = (jsApiList) => new Promise((resolve, reject) => {
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
<slot/>
|
<slot/>
|
||||||
</div>
|
</div>
|
||||||
<u-gap v-else height="112"/>
|
<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"/>
|
<slot v-if="$slots.default"/>
|
||||||
<div class="text" v-text="text"/>
|
<div v-else class="text" :class="{circle}" v-text="text"/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
@@ -15,7 +15,9 @@
|
|||||||
export default {
|
export default {
|
||||||
name: "AiBottomBtn",
|
name: "AiBottomBtn",
|
||||||
props: {
|
props: {
|
||||||
text: {default: ""}
|
text: {default: ""},
|
||||||
|
circle: Boolean,
|
||||||
|
background: {default: "inherit"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -37,6 +39,14 @@ export default {
|
|||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
background: #1365DD;
|
background: #1365DD;
|
||||||
box-shadow: inset 0px 1px 0px 0px #EEEEEE;
|
box-shadow: inset 0px 1px 0px 0px #EEEEEE;
|
||||||
|
|
||||||
|
&.circle {
|
||||||
|
border-radius: 52px;
|
||||||
|
line-height: 80px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
padding: 0 70px;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.transport {
|
.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)) {//乡村相册版
|
if (/AppCountryAlbum/.test(location.pathname)) {//乡村相册版
|
||||||
params = {action: "/app/wxcptp/portal/agentSign", corpId: "wpytYEDgAAcpXjmlYkYwKO60JDGDWrXg", suiteId: "ww0da13777658d1262"}
|
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": {
|
"/ns": {
|
||||||
"target": "http://dvcp.sinoecare.net",
|
"target": "http://192.168.1.87:12525",
|
||||||
"changeOrigin": true,
|
"changeOrigin": true,
|
||||||
"pathRewrite": {
|
"pathRewrite": {
|
||||||
"^/ns": "/"
|
"^/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