32ab1e6f by 杨炀

init

0 parents
Showing 309 changed files with 4881 additions and 0 deletions
.DS_Store
node_modules/
unpackage/
package-lock.json
yarn.lock
{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
// launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
"version": "0.0",
"configurations": [{
"default" :
{
"launchtype" : "local"
},
"mp-weixin" :
{
"launchtype" : "local"
},
"type" : "uniCloud"
}
]
}
<script>
import * as loginServer from '@/common/login.js';
import * as api from '@/common/api.js';
import config from '@/config.js';
let firstload = false
export default {
onLaunch: function() {
console.log('App Launch');
firstload = true
this.globalData.baseUrl = config.baseUrl;
this.globalData.baseUrl_api = config.baseUrl_api;
this.globalData.fileUrl = config.fileUrl;
uni.getSystemInfo({
success: function(res) {
console.log(111, res)
const model = res.model
let stt = ''
// 判断机型
if (model.includes('iPhone')) {
stt = 'iPhone'
} else if (model.includes('iPad')) {
stt = 'iPad'
} else if (model.includes('Android')) {
stt = 'Android'
} else {
stt = '其他'
}
uni.setStorageSync('systemType', stt);
}
})
new Promise((resolve, reject) => {
uni.checkSession({
success: res => {
loginServer
.getCurrUser(true)
.catch(() => {
return loginServer.pcLogin();
})
.then(user => {
resolve(user);
});
},
fail: res => {
loginServer
.wxLogin()
.then(loginRes => {
return loginServer.pcLogin(loginRes.code);
})
.then(user => {
resolve(user);
});
}
});
// loginServer
// .wxLogin()
// .then(loginRes => {
// return loginServer.pcLogin(loginRes.code)
// })
// .then(loginServer.getCurrUser)
// .then(user=>{
// resolve(user);
// });
})
.then(() => {
this.globalData.isLogin = true;
let firstLoadCallback = getApp().firstLoadCallback;
if (firstLoadCallback) {
firstLoadCallback();
}
});
},
onShow: function() {
console.log('App Show', uni.getStorageSync('isRegister'));
},
onHide: function() {
console.log('App Hide');
const isRegister = uni.getStorageSync('isRegister')
if (isRegister == '0') {
uni.setStorageSync('isRegister', '1');
}
}
};
</script>
<style lang="scss">
/*每个页面公共css */
@import '/common/uni.css';
@import '/common/mystyle.scss';
@import '@/static/font/iconfont.css';
</style>
\ No newline at end of file
import request from './request.js'
const accountInfo = uni.getAccountInfoSync()
const appId = accountInfo.miniProgram.appId;
import config from '@/config.js'
import * as loginServer from '@/common/login.js';
export function getUserExtByUserId(params) {
return request({
url: `/system/userExt/getUserExtByUserId`,
method: 'get'
})
}
export function getUserIsPay(params) {
return request({
url: `/system/order/getUserIsPay`,
method: 'get',
params: params
})
}
export function getVipPrice(params) {
return request({
url: `/system/config/configKey/sys.user.mem`,
method: 'get'
})
}
export function getMyCourses() {
return request({
url: `/system/course/getMyCourses`,
method: 'get'
})
}
export function getMyActivitys() {
return request({
url: `/system/activity/getMyActivitys`,
method: 'get'
})
}
export function getClassifyList() {
return request({
url: `/system/paper/getClassifyList`,
method: 'get'
})
}
export function getHomePageHot() {
return request({
url: `/system/paper/getHomePageHot`,
method: 'get'
})
}
export function getHomeTop() {
return request({
url: `/system/paper/list?isTop=1`,
method: 'get'
})
}
export function getPaperList(params) {
return request({
url: `/system/paper/list`,
method: 'get',
params: params
})
}
export function getCourseList(params) {
return request({
url: `/system/course/list`,
method: 'get',
params: params
})
}
export function getActivityList(params) {
return request({
url: `/system/activity/list`,
method: 'get',
params: params
})
}
export function getHomePageHotCourse(params) {
return request({
url: `/system/course/getHomePageHot`,
method: 'get',
params: params
})
}
export function getHomePageHotActive(params) {
return request({
url: `/system/activity/getHomePageHot`,
method: 'get',
params: params
})
}
export function getCourseById(courseId) {
return request({
url: `/system/course/${courseId}`,
method: 'get'
})
}
export function getActiveById(activityId) {
return request({
url: `/system/activity/${activityId}`,
method: 'get'
})
}
export function getUserAnswerList(params) {
return request({
url: `/system/userAnswer/getUserAnswersByUserId`,
method: 'get',
params: params
})
}
export function getUserAnswerInfo(params) {
return request({
url: `/system/userAnswer/getUserAnswerInfo`,
method: 'get',
params: params
})
}
export function getUserAnswerResult(params) {
return request({
url: `/system/userAnswer/getUserAnswerResult`,
method: 'get',
params: params
})
}
export function getPaperInfo(paperId) {
return request({
url: `/system/paper/${paperId}`,
method: 'get'
})
}
export function getCurrentUserInfo() {
return request({
url: `/system/user/getCurrentUserInfo`,
method: 'get'
})
}
export function updateUserInfo(form) {
return request({
url: `/system/user/updateUserInfo`,
method: 'put',
params: form
})
}
export function submitAnswer(form) {
return request({
url: `/system/userAnswer/submit`,
method: 'post',
params: form
})
}
export function unSubscribe(form) {
return request({
url: `/system/order/unSubscribe`,
method: 'post',
params: form
})
}
export function createOrder(form) {
return request({
url: `/system/pay/createOrder`,
method: 'post',
params: form
})
}
export function payForOrder(form) {
return request({
url: `/system/pay/payForOrder`,
method: 'post',
params: form
})
}
export function submitOrder(form) {
return request({
url: `/system/order/sumbit`,
method: 'post',
params: form
})
}
export function saveAnswer(form) {
return request({
url: `/system/userAnswer/save`,
method: 'post',
params: form
})
}
export function getExclusiveImage(id) {
return request({
url: `/system/exclusive/getExclusiveImage/${id}`,
method: 'get'
})
}
export function getScoreByUserId(id) {
return request({
url: `/system/user/getScoreByUserId`,
method: 'get'
})
}
// 图片上传
export function uploadImg(e) {
const tempFilePaths = e.tempFilePaths;
const imgUrl = tempFilePaths[0]
uni.showLoading({
title: '加载中'
});
return uni.uploadFile({
url: config.baseUrl_api + '/upload/fs',
header: {
'Authorization': uni.getStorageSync('token'),
},
filePath: imgUrl,
name: 'image'
}).then(res => {
let data = JSON.parse(res.data);
return data
}).finally(() => {
uni.hideLoading();
});
}
export function userShare(shareId) {
return request({
url: `/system/userShare/share?shareId=${shareId}`,
method: 'get'
})
}
export function getState(paperId) {
return request({
url: `/system/userAnswer/getState?paperId=${paperId}`,
method: 'get'
})
}
// 消费 充值
export function czList() {
const currUser = uni.getStorageSync('currUser')
return request({
url: `/system/pay/mylist?userId=${currUser.userId}&status=1`,
method: 'get'
})
}
export function xfList() {
const currUser = uni.getStorageSync('currUser')
return request({
url: `/system/order/mylist?userId=${currUser.userId}`,
method: 'get'
})
}
// 反馈页面提交
export function miniappData(params) {
return request({
url: `/systemj/miniappData`,
method: 'post',
params: params
})
}
int "-"?([0-9]|[1-9][0-9]+)
exp [eE][-+]?[0-9]+
frac "."[0-9]+
%%
\s+ /* skip whitespace */
{int}{frac}?{exp}?\b return 'NUMBER'
\"(?:'\\'[\\"bfnrt/]|'\\u'[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*\" yytext = yytext.substr(1,yyleng-2); return 'STRING'
"{" return '{'
"}" return '}'
"[" return '['
"]" return ']'
"," return ','
":" return ':'
"true" return 'TRUE'
"false" return 'FALSE'
"null" return 'NULL'
<<EOF>> return 'EOF'
. return 'INVALID'
%%
%start JSONText
/*
ECMA-262 5th Edition, 15.12.1 The JSON Grammar.
*/
%%
JSONString
: STRING
{ // replace escaped characters with actual character
$$ = yytext.replace(/\\(\\|")/g, "$"+"1")
.replace(/\\n/g,'\n')
.replace(/\\r/g,'\r')
.replace(/\\t/g,'\t')
.replace(/\\v/g,'\v')
.replace(/\\f/g,'\f')
.replace(/\\b/g,'\b');
}
;
JSONNumber
: NUMBER
{
//$$ = Number(yytext);
$$ = yytext == String(Number(yytext))? Number(yytext): yytext;
}
;
JSONNullLiteral
: NULL
{$$ = null;}
;
JSONBooleanLiteral
: TRUE
{$$ = true;}
| FALSE
{$$ = false;}
;
JSONText
: JSONValue EOF
{return $$ = $1;}
;
JSONValue
: JSONNullLiteral
| JSONBooleanLiteral
| JSONString
| JSONNumber
| JSONObject
| JSONArray
;
JSONObject
: '{' '}'
{{$$ = {};}}
| '{' JSONMemberList '}'
{$$ = $2;}
;
JSONMember
: JSONString ':' JSONValue
{$$ = [$1, $3];}
;
JSONMemberList
: JSONMember
{{$$ = {}; $$[$1[0]] = $1[1];}}
| JSONMemberList ',' JSONMember
{$$ = $1; $1[$3[0]] = $3[1];}
;
JSONArray
: '[' ']'
{$$ = [];}
| '[' JSONElementList ']'
{$$ = $2;}
;
JSONElementList
: JSONValue
{$$ = [$1];}
| JSONElementList ',' JSONValue
{$$ = $1; $1.push($3);}
;
import request from './request'
import * as api from '@/common/api.js';
const accountInfo = uni.getAccountInfoSync()
const appId = accountInfo.miniProgram.appId;
function wxLogin() {
return new Promise((resolve, reject) => {
uni.login({
provider: 'weixin',
success: (res) => {
// console.log(res.code);
resolve(res)
},
fail: (res) => {
reject(res)
}
})
})
}
function pcLogin(code) {
if (code) {
return pcLoginByCode(code)
} else {
const currUser = uni.getStorageSync('currUser') || {}
if (currUser.openId) {
return pcLoginByOpenId(currUser.openId);
} else {
return wxLogin().then((loginRes) => {
return pcLoginByCode(loginRes.code)
})
}
}
}
function repeatLogin() {
console.log('重新登录')
return wxLogin().then((loginRes) => {
return pcLoginByCode(loginRes.code)
})
}
function pcLoginByOpenId(openId) {
return request({
url: "/system/wx/loginByOpenId",
method: "POST",
params: {
appId: appId,
openId: openId
}
}).then((res) => {
let user = res.data;
// console.log("openId " + openId, user)
uni.setStorageSync('token', 'Bearer ' + user.token);
uni.setStorageSync('currUser', user);
return user;
}).catch(() => {
uni.removeStorageSync('currUser')
})
}
function pcLoginByCode(code) {
return request({
// url: "/weixin/api/login",
url: "/xcxLogin",
method: "POST",
params: {
appId: appId,
jsCode: code
}
}).then((res) => {
uni.setStorageSync('token', 'Bearer ' + res.data.token)
uni.setStorageSync('isRegister', res.data.isRegister)
console.log(uni.getStorageSync('isRegister'))
}).then(getCurrUser)
.catch((err) => {
uni.removeStorageSync('currUser')
})
}
function getCurrUser(isAuto) {
let token = uni.getStorageSync('token');
if (token) {
return request({
url: "/getInfo",
method: "GET",
opts: {
isAuto: isAuto
}
}).then((res) => {
let user = res.data.user;
uni.setStorageSync('currUser', user);
uni.setStorageSync('score', res.data.score);
return user
})
} else {
return Promise.reject()
}
}
function getWxUser() {
return new Promise((resolve, reject) => {
const currUser = uni.getStorageSync('currUser');
uni.getUserProfile({
desc: '用于完善用户信息',
success: function(infoRes) {
console.log(infoRes)
request({
url: `/system/wx/updateWxUser`,
method: "POST",
params: {
appId: appId,
userId: currUser.id,
encryptedData: infoRes.encryptedData,
errMsg: infoRes.errMsg,
iv: infoRes.iv,
rawData: infoRes.rawData,
signature: infoRes.signature
}
}).then((res) => {
let user = res.data;
uni.setStorageSync('currUser', user);
resolve(user);
}).catch(() => {
reject()
})
},
fail: (res) => {
reject(res)
}
});
});
}
function getWxUserPhone(phoneRes) {
// console.log(phoneRes)
const currUser = uni.getStorageSync('currUser');
return request({
url: `/system/wx/updateMobile`,
method: "POST",
params: {
appId: appId,
userId: currUser.id,
encryptedData: phoneRes.encryptedData,
errMsg: phoneRes.errMsg,
iv: phoneRes.iv,
rawData: phoneRes.rawData,
signature: phoneRes.signature
}
}).then((res) => {
let user = res.data;
uni.setStorageSync('currUser', user);
return user
})
}
function checkUserAuth(path) {
const currUser = uni.getStorageSync('currUser')
if (currUser.phonenumber) {
// if (currUser.nickName) {
return true
} else {
uni.navigateTo({
url: '/pages/index/start?path=' + encodeURIComponent(path)
})
return false;
}
}
export {
wxLogin,
pcLogin,
getCurrUser,
getWxUser,
getWxUserPhone,
checkUserAuth
}
\ No newline at end of file
import config from '@/config.js'
import {
pcLogin
} from './login'
const excludeUrls = ['/system/wx/getUserInfo']
// 获取Token
function getToken() {
try {
const token = uni.getStorageSync('token');
if (token) {
return token
} else {
return ''
}
} catch (e) {
console.log(e)
}
}
// 获取请求头
function getHeaders() {
let token = getToken()
let header = {
"Authorization": token,
"Content-Type": "application/json" //根据自己的数据类型
// "Content-Type":"application/x-www-form-urlencoded",
}
return header
}
let request = function(req) {
req.method = req.method.toUpperCase()
if (!['GET', 'POST', 'PUT', 'DELETE'].includes(req.method)) {
uni.showToast({
title: `暂不支持的请求方式: ${req.method}`,
icon: 'none'
});
return
}
// if (req.method == 'POST' && !req.hideLoding) {
// uni.showLoading({
// title: '提交中...'
// })
// }
return new Promise((resolve, reject) => {
uni.request({
url: config.baseUrl_api + req.url,
method: req.method,
data: req.params,
header: getHeaders(),
}).then(res => {
switch (res.statusCode) {
case 200:
const data = res.data || {};
if (data.code == 200) {
resolve(data)
} else {
//登录超时
if (data.code == 60002 || data.code == 60001) {
reLogin();
} else {
uni.showToast({
title: data.msg,
icon: 'none',
duration: 3000
})
}
reject(res)
}
break
default:
reject(res)
}
}).catch(res => {
reject(res)
}).finally(() => {
// if (req.method == 'POST' && !req.hideLoding) {
// uni.hideLoading()
// }
})
})
}
function reLogin() {
const currUser = uni.getStorageSync('currUser') || {}
if (currUser.openId) {
const accountInfo = uni.getAccountInfoSync()
pcLoginByOpenId(accountInfo.miniProgram.appId, currUser.openId)
.then((res) => {
let user = res.data;
uni.setStorageSync('token', user.token);
uni.setStorageSync('currUser', user);
uni.showToast({
title: '一走神把您的操作遗漏了,请重试',
icon: 'none'
})
}).catch(() => {
uni.showToast({
title: '服务异常,请稍后重试',
icon: 'none'
})
})
}
}
function pcLoginByOpenId(appId, openId) {
return request({
url: "/system/wx/loginByOpenId",
method: "POST",
params: {
appId: appId,
openId: openId
}
})
}
export default request;
\ No newline at end of file
<template>
<view class="content">
<swiper class="swiper"
:autoplay="autoplay"
:duration="duration">
<swiper-item>
<view class="swiper-item">
<view class="swiper-item-img"><image src="../../static/guide/title_01.png" mode="aspectFit"></image></view>
<view class="swiper-item-img"><image src="../../static/guide/icon_01.png" mode="aspectFit"></image></view>
</view>
<view class="jump-over" @tap="launchFlag()">{{jumpover}}</view>
</swiper-item>
<swiper-item>
<view class="swiper-item">
<view class="swiper-item-img"><image src="../../static/guide/title_02.png" mode="aspectFit"></image></view>
<view class="swiper-item-img"><image src="../../static/guide/icon_02.png" mode="aspectFit"></image></view>
</view>
<view class="jump-over" @tap="launchFlag()">{{jumpover}}</view>
</swiper-item>
<swiper-item>
<view class="swiper-item">
<view class="swiper-item-img"><image src="../../static/guide/title_03.png" mode="aspectFit"></image></view>
<view class="swiper-item-img"><image src="../../static/guide/icon_03.png" mode="aspectFit"></image></view>
</view>
<view class="jump-over" @tap="launchFlag()">{{jumpover}}</view>
</swiper-item>
<swiper-item>
<view class="swiper-item">
<view class="swiper-item-img"><image src="../../static/guide/title_04.png" mode="aspectFit"></image></view>
<view class="swiper-item-img"><image src="../../static/guide/icon_04.png" mode="aspectFit"></image></view>
</view>
<view class="experience" @tap="launchFlag()">{{experience}}</view>
</swiper-item>
</swiper>
<view class="uniapp-img"><image src="../../static/guide/uniapp4@2x.png" mode="aspectFit"></image></view>
</view>
</template>
<script>
export default {
data() {
return {
background: ['color1', 'color2', 'color3'],
autoplay: false,
duration: 500,
jumpover: '跳过',
experience: '立即体验'
}
},
methods: {
launchFlag: function(){
/**
* 向本地存储中设置launchFlag的值,即启动标识;
*/
uni.setStorage({
key: 'launchFlag',
data: true,
});
uni.switchTab({
url: '/pages/tabBar/component/component'
});
}
}
}
</script>
<style>
page,
.content{
width: 100%;
height: 100%;
background-size: 100% auto ;
padding: 0;
}
.swiper{
width: 100%;
height: 80%;
background: #FFFFFF;
}
.swiper-item {
width: 100%;
height: 100%;
text-align: center;
position: relative;
display: flex;
/* justify-content: center; */
align-items:flex-end;
flex-direction:column-reverse
}
.swiper-item-img{
width: 100%;
height: auto;
margin: 0 auto;
}
.swiper-item-img image{
width: 80%;
}
.uniapp-img{
height: 20%;
background: #FFFFFF;
display: flex;
justify-content: center;
align-items:center;
overflow: hidden;
}
.uniapp-img image{
width: 40%;
}
.jump-over,.experience{
position: absolute;
height: 60upx;
line-height: 60upx;
padding: 0 40upx;
border-radius: 30upx;
font-size: 32upx;
color: #454343;
border: 1px solid #454343;
z-index: 999;
}
.jump-over{
right: 45upx;
top: 125upx;
}
.experience{
right: 50%;
margin-right: -105upx;
bottom: 0;
}
</style>
# 引导页
### 基于uni-app框架的swiper组件打开的时候启动。
> 首次启动展示引导页,之后启动不再展示。那么就意味着,我们需要一个标识来确定,App是否已经启动过。
> 我们可以在本地存储一个key来做为已经启动过App的标识。那么,我们在入口这里,就可以读取这个key,来决定是否展示引导页。
> 因工作繁忙目前该程序金对安卓做了适配,IOS可根据环境自己适配。谢谢
## 目录结构
* /pages/index/index.vue //入口页
### 存储key
* 向本地存储中设置launchFlag的值,即启动标识;
### 获取key
* 向本地存储中设置launchFlag的值,即启动标识;
* 获取本地存储中launchFlag的值
* 若存在,说明不是首次启动,直接进入首页;
* 若不存在,说明是首次启动,进入引导页;
```html
<view class="main">
<code-elf-guide v-if="guidePages"></code-elf-guide>
</view>
```
```javascript
import codeElfGuide from '@/components/code-elf-guide/code-elf-guide.vue'
export default {
components: {
codeElfGuide
},
data() {
return {
guidePages:true
}
},
onLoad(){
this.loadExecution()
},
methods: {
loadExecution: function(){
/**
* 获取本地存储中launchFlag的值
* 若存在,说明不是首次启动,直接进入首页;
* 若不存在,说明是首次启动,进入引导页;
*/
try {
// 获取本地存储中launchFlag标识
const value = uni.getStorageSync('launchFlag');
if (value) {
// launchFlag=true直接跳转到首页
uni.switchTab({
url: '/pages/tabBar/component/component'
});
} else {
// launchFlag!=true显示引导页
this.guidePages = true
}
} catch(e) {
// error
uni.setStorage({
key: 'launchFlag',
data: true,
success: function () {
console.log('error时存储launchFlag');
}
});
this.guidePages = true
}
}
}
}
```
```css
page,.main{
width: 100%;
height: 100%;
}
```
### 首页清除key,进行测试
* 清除本地存储中设置launchFlag的值,即启动标识;
* 两秒后重启APP,进行测试
```javascript
uni.showModal({
title: '清除launchFlag值',
content: '确定要清除launchFlag值,进行重启测试?',
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
// 清除缓存
uni.clearStorage();
uni.showToast({
icon: 'none',
duration:3000,
title: '清除成功2秒后重启'
});
// 两秒后重启
setTimeout(function() {
uni.hideToast();
plus.runtime.restart();
}, 2000);
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
```
\ No newline at end of file
# slider-range
uni-app 滑块区间选择组件
可根据具体需求,修改、自定义其他内容。
## 属性说明
|属性名|类型|默认值|说明|
| -- | -- | --|--|
| value | Array<Number, Number> | [0,100] |滑块已选中区间的值|
| min | Number| 0 | 滑块区间最小值 |
| max | Number | 100 | 滑块区间最大值 |
| step | Number | 1 | 拖动时的步长 |
| disabled | Boolean | false | 是否为禁用状态 |
| height | Number | 50 | 滑块容器高度 |
| barHeight | Number | 5 | 滑块进度条高度 |
| backgroundColor | String | #e9e9e9| 滑块进度条背景色|
| activeColor | String | #1aad19 | 已选中区间进度条颜色|
| blockSize | Number | 20 | 滑块大小 |
| blockColor | String | #fff | 滑块颜色 |
| decorationVisible | Boolean | false | 是否显示滑块内装饰元素|
| tipVisible | Boolean | true | 是否显示滑块值提示文本 |
| fomat| Function | | 滑块值提示文本格式化函数,**注意**:小程序中此属性必传,否则会报错,如果无需格式化,可以简单返回原始值: `format(val) { return val }`;H5中可以不传。|
## 使用示例
```html
<slider-range
:value="rangeValue"
:min="rangeMin"
:max="rangMax"
:step="5"
:bar-height="3"
:block-size="26"
background-color="#EEEEF6"
active-color="#FF6B00"
:format="format"
:decorationVisible="true"
@change="handleRangeChange"
></slider-range>
```
```javascript
import SliderRange from '../components/slider-range/index.vue'
export default {
components: {
SliderRange
},
data() {
return {
rangeMin: 5,
rangMax: 200,
rangeValue: [10, 50]
}
},
methods: {
format(val) {
return val + '%'
},
handleRangeChange(e) {
this.rangeValue = e
}
}
}
```
效果图
![](http://images.alisali.cn/img_20190715175325.png)
<template>
<view
class="slider-range"
:class="{ disabled: disabled }"
:style="{ paddingLeft: blockSize / 2 + 'px', paddingRight: blockSize / 2 + 'px' }"
>
<view class="slider-range-inner" :style="{ height: height + 'px' }">
<view
class="slider-bar"
:style="{
height: barHeight + 'px',
}"
>
<!-- 背景条 -->
<view
class="slider-bar-bg"
:style="{
backgroundColor: backgroundColor,
}"
></view>
<!-- 滑块实际区间 -->
<view
class="slider-bar-inner"
:style="{
width: ((values[1] - values[0]) / (max - min)) * 100 + '%',
left: lowerHandlePosition + '%',
backgroundColor: activeColor,
}"
></view>
</view>
<!-- 滑动块-左 -->
<view
class="slider-handle-block"
:class="{ decoration: decorationVisible }"
:style="{
backgroundColor: blockColor,
width: blockSize + 'px',
height: blockSize + 'px',
left: lowerHandlePosition + '%',
}"
@touchstart="_onTouchStart"
@touchmove="_onBlockTouchMove"
@touchend="_onBlockTouchEnd"
data-tag="lowerBlock"
></view>
<!-- 滑动块-右 -->
<view
class="slider-handle-block"
:class="{ decoration: decorationVisible }"
:style="{
backgroundColor: blockColor,
width: blockSize + 'px',
height: blockSize + 'px',
left: higherHandlePosition + '%',
}"
@touchstart="_onTouchStart"
@touchmove="_onBlockTouchMove"
@touchend="_onBlockTouchEnd"
data-tag="higherBlock"
></view>
<!-- 滑块值提示 -->
<view v-if="tipVisible" class="range-tip" :style="lowerTipStyle">{{ format(values[0]) }}</view>
<view v-if="tipVisible" class="range-tip" :style="higherTipStyle">{{ format(values[1]) }}</view>
</view>
</view>
</template>
<script>
export default {
components: {},
props: {
//滑块区间当前取值
value: {
type: Array,
default: function() {
return [0, 100]
},
},
//最小值
min: {
type: Number,
default: 0,
},
//最大值
max: {
type: Number,
default: 100,
},
step: {
type: Number,
default: 1,
},
format: {
type: Function,
default: function(val) {
return val
},
},
disabled: {
type: Boolean,
default: false,
},
//滑块容器高度
height: {
height: Number,
default: 50,
},
//区间进度条高度
barHeight: {
type: Number,
default: 5,
},
//背景条颜色
backgroundColor: {
type: String,
default: '#e9e9e9',
},
//已选择的颜色
activeColor: {
type: String,
default: '#1aad19',
},
//滑块大小
blockSize: {
type: Number,
default: 20,
},
blockColor: {
type: String,
default: '#fff',
},
tipVisible: {
type: Boolean,
default: true,
},
decorationVisible: {
type: Boolean,
default: false,
},
},
data() {
return {
values: [this.min, this.max],
startDragPos: 0, // 开始拖动时的坐标位置
startVal: 0, //开始拖动时较小点的值
}
},
computed: {
// 较小点滑块的坐标
lowerHandlePosition() {
return ((this.values[0] - this.min) / (this.max - this.min)) * 100
},
// 较大点滑块的坐标
higherHandlePosition() {
return ((this.values[1] - this.min) / (this.max - this.min)) * 100
},
lowerTipStyle() {
if (this.lowerHandlePosition < 90) {
return `left: ${this.lowerHandlePosition}%;`
}
return `right: ${100 - this.lowerHandlePosition}%;transform: translate(50%, -100%);`
},
higherTipStyle() {
if (this.higherHandlePosition < 90) {
return `left: ${this.higherHandlePosition}%;`
}
return `right: ${100 - this.higherHandlePosition}%;transform: translate(50%, -100%);`
},
},
created: function() {},
onLoad: function(option) {},
watch: {
//滑块当前值
value: {
immediate: true,
handler(newVal, oldVal) {
if (this._isValuesValid(newVal) && (newVal[0] !== this.values[0] || newVal[1] !== this.values[1])) {
this._updateValue(newVal)
}
},
},
},
methods: {
_updateValue(newVal) {
// 步长大于区间差,或者区间最大值和最小值相等情况
if (this.step >= this.max - this.min) {
throw new RangeError('Invalid slider step or slider range')
}
let newValues = []
if (Array.isArray(newVal)) {
newValues = [newVal[0], newVal[1]]
}
if (typeof newValues[0] !== 'number') {
newValues[0] = this.values[0]
} else {
newValues[0] = Math.round((newValues[0] - this.min) / this.step) * this.step + this.min
}
if (typeof newValues[1] !== 'number') {
newValues[1] = this.values[1]
} else {
newValues[1] = Math.round((newValues[1] - this.min) / this.step) * this.step + this.min
}
// 新值与原值相等,不做处理
if (this.values[0] === newValues[0] && this.values[1] === newValues[1]) {
return
}
// 左侧滑块值小于最小值时,设置为最小值
if (newValues[0] < this.min) {
newValues[0] = this.min
}
// 右侧滑块值大于最大值时,设置为最大值
if (newValues[1] > this.max) {
newValues[1] = this.max
}
// 两个滑块重叠或左右交错,使两个滑块保持最小步长的间距
if (newValues[0] >= newValues[1]) {
// 左侧未动,右侧滑块滑到左侧滑块之左
if (newValues[0] === this.values[0]) {
newValues[1] = newValues[0] + this.step
} else {
// 右侧未动, 左侧滑块滑到右侧之右
newValues[0] = newValues[1] - this.step
}
}
this.values = newValues
this.$emit('change', this.values)
},
_onTouchStart: function(event) {
if (this.disabled) {
return
}
this.isDragging = true
let tag = event.target.dataset.tag
//兼容h5平台及某版本微信
let e = event.changedTouches ? event.changedTouches[0] : event
this.startDragPos = e.pageX
this.startVal = tag === 'lowerBlock' ? this.values[0] : this.values[1]
},
_onBlockTouchMove: function(e) {
if (this.disabled) {
return
}
this._onDrag(e)
},
_onBlockTouchEnd: function(e) {
if (this.disabled) {
return
}
this.isDragging = false
this._onDrag(e)
},
_onDrag(event) {
if (!this.isDragging) {
return
}
let view = uni
.createSelectorQuery()
.in(this)
.select('.slider-range-inner')
view
.boundingClientRect(data => {
let sliderWidth = data.width
const tag = event.target.dataset.tag
let e = event.changedTouches ? event.changedTouches[0] : event
let diff = ((e.pageX - this.startDragPos) / sliderWidth) * (this.max - this.min)
let nextVal = this.startVal + diff
if (tag === 'lowerBlock') {
this._updateValue([nextVal, null])
} else {
this._updateValue([null, nextVal])
}
})
.exec()
},
_isValuesValid: function(values) {
return Array.isArray(values) && values.length == 2
},
},
}
</script>
<style scoped>
.slider-range {
position: relative;
padding-top: 40rpx;
}
.slider-range-inner {
position: relative;
width: 100%;
}
.slider-range.disabled .slider-bar-inner {
opacity: 0.35;
}
.slider-range.disabled .slider-handle-block {
cursor: not-allowed;
}
.slider-bar {
position: absolute;
top: 50%;
left: 0;
right: 0;
transform: translateY(-50%);
}
.slider-bar-bg {
position: absolute;
width: 100%;
height: 100%;
border-radius: 10000px;
z-index: 10;
}
.slider-bar-inner {
position: absolute;
width: 100%;
height: 100%;
border-radius: 10000px;
z-index: 11;
}
.slider-handle-block {
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
border-radius: 50%;
box-shadow: 0 0 3px 2px rgba(227, 229, 241, 0.5);
z-index: 12;
}
.slider-handle-block.decoration::before {
position: absolute;
content: '';
width: 6upx;
height: 24upx;
top: 50%;
left: 29%;
transform: translateY(-50%);
background: #eeedf2;
border-radius: 3upx;
z-index: 13;
}
.slider-handle-block.decoration::after {
position: absolute;
content: '';
width: 6upx;
height: 24upx;
top: 50%;
right: 29%;
transform: translateY(-50%);
background: #eeedf2;
border-radius: 3upx;
z-index: 13;
}
.range-tip {
position: absolute;
top: 0;
font-size: 24upx;
color: #666;
transform: translate(-50%, -100%);
}
</style>
<template>
<view class="demo-slider-range">
<view class="section-title">普通用法</view>
<view class="slider-item">
<slider-range
:value="slider1.rangeValue"
:min="slider1.min"
:max="slider1.max"
:step="slider1.step"
:bar-height="barHeight"
:block-size="blockSize"
:background-color="backgroundColor"
:format="format1"
@change="handleRangeChange"
></slider-range>
</view>
<view class="section-title">自定义</view>
<view class="slider-item">
<slider-range
:value="slider2.rangeValue"
:min="slider2.min"
:max="slider2.max"
:step="slider2.step"
:bar-height="barHeight"
:block-size="blockSize"
:background-color="backgroundColor"
:active-color="slider2.activeColor"
:format="format2"
:decorationVisible="slider2.decorationVisible"
@change="handleRangeChange"
></slider-range>
</view>
</view>
</template>
<script>
import SliderRange from '../../components/slider-range/index.vue'
export default {
components: {
SliderRange,
},
data() {
return {
barHeight: 3,
blockSize: 26,
backgroundColor: '#EEEEF6',
slider1: {
min: 50,
max: 200,
step: 10,
rangeValue: [50, 150],
},
slider2: {
rangeMin: 0,
rangMax: 100,
rangeValue: [8, 80],
step: 1,
activeColor: '#FF6B00',
decorationVisible: true,
},
}
},
methods: {
format1(val) {
return val
},
format2(val) {
return `${val}%`
},
handleRangeChange(e) {
this.rangeValue = e
},
},
}
</script>
<style>
.demo-slider-range {
background-color: #fff;
padding: 100rpx 40rpx 0;
}
.section-title {
padding: 0 0 20rpx;
color: #666;
}
.slider-item:not(:last-child) {
margin-bottom: 100rpx;
}
</style>
// prod
// const baseUrl = 'https://research.wtwuxicenter.com/';
// const baseUrl_api=`${baseUrl}/prod-api`;
// uat
// const baseUrl = 'https://jxt.itechtop.cn';
// const baseUrl_api = `${baseUrl}/prod-api`;
// staging
// const baseUrl = "http://192.168.1.118:5599"
// const baseUrl = "https://xtavqfekqb5r.guyubao.com"
const baseUrl = "https://ceping.itechtop.cn/stage-api";
const baseUrl_api = `${baseUrl}`;
const fileUrl = "http://r.itechtop.cn";
export default {
baseUrl: baseUrl,
fileUrl: fileUrl,
baseUrl_api: baseUrl_api,
}
\ No newline at end of file
<template>
<view>
<view class="whitebg">
<image class="ccover" mode="aspectFit" :src="config.baseUrl_api+form.activityPic"></image>
<view class="name">{{form.activityName}}
<view v-if="isBuy" style="font-size: 32rpx;color: #1EC886;display: inline-block;float: right;">
<uni-icons color="#1EC886" size="22" type="checkbox-filled"></uni-icons>已报名
</view>
</view>
<view class="text-warning pp" v-if="form.isFree==1">
<text v-if="form.allGold>0">金币{{form.allGold}}</text>
<text v-if="form.allGold>0&&form.allScore>0">/</text>
<text v-if="form.allScore>0">积分{{form.allScore}}</text>
<text v-if="form.gold>0">/金币{{form.gold}}+积分{{form.score}}</text>
</view>
<view v-else class="text-warning pp">免费</view>
<view class="pp">活动时间:{{form.startTime}}{{form.endTime}}</view>
<view class="pp">活动地址:{{form.address}}</view>
</view>
<view class="plane">
<view class="phead">
<view>
<image class="tag01" src="@/course/img/tag01.png" style="width:30rpx;height: 30rpx;"></image>
活动介绍
</view>
<view class="text-warning">讲师:{{form.speaker}}</view>
</view>
<view class="pbody">
{{form.description}}
</view>
</view>
<view style="height: 100rpx;"></view>
<view class="fixedBottom">
<button class="btn btn-submit" v-if="isBuy">已报名</button>
<button class="btn btn-submit" v-else @click="goBill">立即报名</button>
</view>
</view>
</template>
<script setup>
import {
onLoad,
onShow
} from '@dcloudio/uni-app';
import config from '@/config.js';
import {
ref,
getCurrentInstance
} from 'vue';
import * as api from '@/common/api.js';
const form = ref({})
const isBuy = ref(false)
let goodsId
onLoad((option) => {
uni.showLoading({
title: '加载中'
})
if (option.id) {
goodsId = option.id
}
})
onShow(() => {
if (goodsId)
getData(goodsId)
})
function getData(id) {
api.getActiveById(id).then(res => {
form.value = res.data
uni.hideLoading()
api.getUserIsPay({
orderType: 1,
goodsId: goodsId
}).then(Response => {
isBuy.value = Response.data
})
})
}
function goBill() {
if(form.value.isFree=='1'){
const obj = encodeURIComponent(JSON.stringify(form.value))
let path = `/course/courseBill?form=${obj}`
uni.navigateTo({
url: path
});
} else {
api.submitOrder({
orderType: 1,
goodsId: form.value.activityId,
payType: "0"
}).then(res => {
uni.showModal({
content:'报名成功!',
success:function(respons){
if(respons.confirm){
getData(goodsId)
}
}
})
})
}
}
</script>
<style scoped lang="scss">
.whitebg {
background: #fff;
padding: 25rpx;
}
.plane {
background: #fff;
width: 700rpx;
border-radius: 15rpx;
margin: 30rpx auto;
padding: 25rpx;
box-sizing: border-box;
.phead {
border-bottom: 1rpx solid #eee;
display: flex;
justify-content: space-between;
padding: 0 0 15rpx;
align-items: center;
font-size: 30rpx;
box-sizing: border-box;
.text-warning {
font-size: 28rpx;
}
.tag01 {}
}
.pbody {
padding: 15rpx 0;
box-sizing: border-box;
line-height: 40rpx;
font-size: 28rpx;
color: #4C5359;
}
}
.wList {
background: #fff;
padding: 36rpx 23rpx;
box-sizing: border-box;
border-radius: 15rpx;
width: 700rpx;
margin: 0 auto 30rpx;
position: relative;
.pp {
display: flex;
color: #8F8E94;
font-size: 24rpx;
align-items: center;
image {
margin-right: 6rpx;
}
}
.name {
color: #2B3133;
font-size: 30rpx;
margin: 15rpx 0 0;
}
.playBtn {
position: absolute;
right: 24rpx;
top: 0;
bottom: 0;
margin: auto;
height: 48rpx;
}
}
.ccover {
width: 700rpx;
margin: 0 auto 30rpx;
display: block;
height: 320rpx;
border-radius: 15rpx;
}
.whitebg {
.name {
font-size: 32rpx;
}
.pp {
color: #8F8E94;
font-size: 26rpx;
margin: 10rpx 0 0;
}
.text-warning {
color: #F39800;
}
}
</style>
\ No newline at end of file
<template>
<view>
<view class="list">
<view class="kcitem">
<image v-if="form.coursePic" :src="config.baseUrl_api+form.coursePic" mode="aspectFill"></image>
<image v-if="form.activityPic" :src="config.baseUrl_api+form.activityPic" mode="aspectFill"></image>
<view class="info">
<view class="tt esp_2" v-if="form.courseName">{{form.courseName}}</view>
<view class="tt esp_2" v-if="form.activityName">{{form.activityName}}</view>
<!-- <view class="pp"><uni-icons type="chatboxes" size="12" />209w 学习</view> -->
<!-- <view class="text-warning">{{form.explains}}</view> -->
</view>
</view>
</view>
<view class="rrcard">
<view class="t" v-if="system!='iPhone'&&system!='iPad'">支付方式</view>
<view class="t" v-else>兑换方式</view>
<view class="whitebg">
<radio-group @change="payChange">
<label class="uni-list-cell uni-list-cell-pd" v-if="form.allScore>0">
<view class="littleimgBox">
{{form.allScore}} 积分
</view>
<view>
<radio checked="checked" value="0" />
</view>
</label>
<label class="uni-list-cell uni-list-cell-pd" v-if="form.allGold>0&&system!='iPhone'&&system!='iPad'">
<view class="littleimgBox">
{{form.allGold}} 金币
</view>
<view>
<radio value="1" />
</view>
</label>
<label class="uni-list-cell uni-list-cell-pd" v-if="form.gold>0&&form.score>0&&system!='iPhone'&&system!='iPad'">
<view class="littleimgBox">
{{form.gold}} 金币 + {{form.score}} 积分
</view>
<view>
<radio value="2" />
</view>
</label>
</radio-group>
</view>
</view>
<view class="rrcard mt-30" v-if="form.sale">
<view class="t">可支持的优惠</view>
<view class="whitebg">
<radio-group>
<label class="uni-list-cell uni-list-cell-pd">
<view class="littleimgBox text-warning">
VIP会员
<text>{{form.sale/10}}</text>
</view>
<view v-if="system!='iPhone'&&system!='iPad'">
<radio v-if="mm.memType=='1'" checked="checked"/>
<view v-else @click="beVip">成为VIP 享受此优惠></view>
</view>
</label>
</radio-group>
</view>
</view>
<view class="rrcard mt-30">
<view class="t">我的余额</view>
<view class="whitebg">
<label class="uni-list-cell uni-list-cell-pd">
<view class="littleimgBox">
金币:{{mm.gold||0}}
</view>
<view style="color: #999;" v-if="system!='iPhone'&&system!='iPad'" @click="goPath('/usercenter/mycard/renew')">去充值></view>
</label>
<label class="uni-list-cell uni-list-cell-pd">
<view class="littleimgBox">
积分:{{mm.score||0}}
</view>
<view>
</view>
</label>
</view>
<view class="explains" v-if="form.explains">{{form.explains}}</view>
</view>
<view class="fixedBottom">
<view class="flexbox">
<view>
<view class="text-warning" v-if="mm.memType=='1'">
<text v-if="form.payType==1">{{form.allGold*form.sale/100}} 金币</text>
<text v-if="form.payType==0">{{form.allScore*form.sale/100}} 积分</text>
<text v-if="form.payType==2">{{form.gold*form.sale/100}} 金币 + {{form.score*form.sale/100}} 积分</text>
</view>
<view class="text-del" v-if="mm.memType=='1'">
<text v-if="form.payType==1">{{form.allGold}} 金币</text>
<text v-if="form.payType==0">{{form.allScore}} 积分</text>
<text v-if="form.payType==2">{{form.gold}} 金币 + {{form.score}} 积分</text>
</view>
<view class="text-warning" v-else>
<text v-if="form.payType==1">{{form.allGold}} 金币</text>
<text v-if="form.payType==0">{{form.allScore}} 积分</text>
<text v-if="form.payType==2">{{form.gold}} 金币 + {{form.score}} 积分</text>
</view>
</view>
<view v-if="system!='iPhone'&&system!='iPad'">
<button class="btn btn-submit" v-if="orderType==0" @click="pay">确定购买</button>
<button class="btn btn-submit" v-else @click="pay">确定报名</button>
</view>
<view v-else>
<button class="btn btn-submit" @click="pay">立即兑换</button>
</view>
</view>
</view>
<uni-popup ref="vippay" type="center">
<view style="position: relative;">
<image src="@/usercenter/img/popup2.png" style="width: 620rpx;height: 568rpx;"></image>
<view class="bigPrice">{{vipPrice}}</view>
<button class="btn btn-submit priceBtn" style="width: 400rpx;" @click="payVip">
立即支付 ¥{{vipPrice}}/年</button>
</view>
</uni-popup>
</view>
</template>
<script setup>
import {
onLoad,
onShow,onReady
} from '@dcloudio/uni-app';
import config from '@/config.js';
import {
ref,
getCurrentInstance
} from 'vue';
import * as api from '@/common/api.js';
const form = ref({})
const mm = ref({})
const orderType = ref(0)
const vipPrice = ref(0)
const vippay = ref(null)
const system = uni.getStorageSync('systemType')
onLoad((option) => {
if ('form' in option) {
form.value = JSON.parse(decodeURIComponent(option.form))
if (form.value.courseId) {
orderType.value = 0
} else {
orderType.value = 1
}
}
getUserExt()
})
onReady(() => {
if (orderType.value = 1) {
uni.setNavigationBarTitle({
title: '活动兑换'
});
} else {
uni.setNavigationBarTitle({
title: '课程兑换'
});
}
})
function getUserExt(){
api.getUserExtByUserId().then(res=>{
mm.value = res.data
})
}
function payChange(e) {
console.log(e.detail.value)
form.value.payType = e.detail.value
}
function pay() {
console.log(form.value.payType,mm.value.gold,mm.value.score)
if(form.value.payType==1&&(form.value.allGold>mm.value.gold)){
let msg = '去充值'
uni.showModal({
content: '金币不足',
confirmText: msg,
success:function(res){
if(res.confirm){
goPath('/usercenter/mycard/renew')
}
}
})
return
}
if(form.value.payType==0&&(form.value.allScore>mm.value.score)){
uni.showModal({
content: '积分不足',
success:function(res){
if(res.confirm){
}
}
})
return
}
if(form.value.payType==2&&(form.value.score>mm.value.score||form.value.gold>mm.value.gold)){
uni.showModal({
content: '余额不足',
confirmText:'去充值',
success:function(res){
if(res.confirm){
goPath('/usercenter/mycard/renew')
}
}
})
return
}
var obj = {}
if (orderType.value == 0) {
obj = {
orderType: 0,
goodsId: form.value.courseId,
payType: form.value.payType
}
} else {
obj = {
orderType: 1,
goodsId: form.value.activityId,
payType: form.value.payType
}
}
uni.showModal({
content:'确定购买吗',
success:function(resp){
if(resp.confirm){
api.submitOrder(obj).then(res => {
console.log(res)
if(res.data == -100){
uni.showToast({
title: '余额不足',
icon:'none'
})
} else {
uni.showToast({
title: '操作成功'
})
uni.navigateBack()
}
})
}
}
})
}
function goPath(path) {
uni.navigateTo({
url: path
});
}
function beVip(){
api.getVipPrice().then(res => {
vipPrice.value = res.msg
vippay.value.open()
})
}
function payVip() {
api.createOrder({
total: vipPrice.value,
payType: 0
}).then(res => {
const openId = currUser.openId
// const openId = 'oRufa4ifoP2I3hnoLAwoAreKkppA'
api.payForOrder({
payId: res.data.payId,
openId: openId
}).then(Response => {
// wePay(Response.data.weixinData)
})
})
}
function wePay(configdata) {
console.log(configdata)
// 微信支付
uni.requestPayment({
"provider": "wxpay",
"appId": configdata.appId,
"nonceStr": configdata.nonceStr,
"package": configdata.packageValue, // 随机字符串
"timeStamp": configdata.timeStamp, // 时间戳(单位:秒)
"signType": configdata.signType, // 签名,这里用的 MD5/RSA 签名
"paySign": configdata.paySign,
success(res) {
console.log(res)
uni.showModal({
content: '支付成功',
success: function(resp) {
if (resp.confirm) {
init()
}
}
})
},
fail(e) {
console.log(e)
uni.showToast({
title: '支付取消',
icon: 'none'
});
}
})
}
</script>
<style lang="scss" scoped>
.explains{font-size: 28rpx;color: #999;margin-top: 40rpx;line-height: 2;}
:deep(.uni-list-cell::after) {
background-color: #eee;
width: 94%;
left: 3%;
}
.kcitem {
margin: 30rpx auto;
width: 700rpx;
box-sizing: border-box;
}
.whitebg {
background: #fff;
}
.rrcard .box {
padding: 0 0 1px;
margin: 20rpx 0 0;
}
.rrcard {
position: relative;
padding: 0 25rpx;
box-sizing: border-box;
}
.rrcard .t {
font-weight: 500;
color: #2B3133;
margin: 0 0 20rpx;
font-size: 32rpx;
}
.fixedBottom {
.flexbox {
width: 100%;
justify-content: space-between;
padding: 0 30rpx;
}
}
</style>
\ No newline at end of file
<template>
<view>
<!-- <web-view :src="vUrl"></web-view> -->
<view class="whitebg">
<image class="ccover" v-if="form.coursePic&&!playVideo&&!playAudio" mode="aspectFill" :src="config.baseUrl_api + form.coursePic"></image>
<video v-if="playVideo" @timeupdate="videoing" id="myVideo" :autoplay="false"
:src="vUrl" controls @error="videoErrorCallback"
play-btn-position="center" controlslist="nodownload"
style="width: 100%;"
></video>
<audio v-if="playAudio" style="text-align: left" :src="config.baseUrl_api+form.audioUrl?.url"
:poster="config.baseUrl_api+form.coursePic" :name="form.audioUrl?.name" :author="form.speaker" controls
@timeupdate="audioing" id="myAudio"></audio>
<view class="name">{{form.courseName}}
<view v-if="isBuy" style="font-size: 32rpx;color: #1EC886;display: inline-block;float: right;">
<uni-icons color="#1EC886" size="22" type="checkbox-filled"></uni-icons>已兑换
</view>
</view>
<!-- <view class="text-warning pp">{{form.explains}}</view> -->
<view class="text-warning pp" v-if="form.isFree==1">
<text v-if="form.allGold>0">金币{{form.allGold}}</text>
<text v-if="form.allGold>0&&form.allScore>0">/</text>
<text v-if="form.allScore>0">积分{{form.allScore}}</text>
<text v-if="form.gold>0">/金币{{form.gold}}+积分{{form.score}}</text>
</view>
<view class="text-warning pp" v-else>免费</view>
</view>
<view class="plane">
<view class="phead">
<view>
<image class="tag01" src="@/course/img/tag01.png" style="width:30rpx;height: 30rpx;"></image>
课程介绍
</view>
<view class="text-warning">讲师:{{form.speaker}}</view>
</view>
<view class="pbody">
{{form.description}}
</view>
</view>
<!-- list -->
<view class="wList" v-if="form.audioUrl">
<view class="pp">
<image src="@/course/img/book.png" style="width:24rpx;height: 24rpx;"></image>
音频
</view>
<view class="name">{{form.audioUrl.name}}</view>
<view class="playBtn" @click="play('a')">
<image src="@/course/img/play.png" style="width:48rpx;height: 48rpx;"></image>
</view>
</view>
<view class="wList" v-if="form.videoUrl">
<view class="pp">
<image src="@/course/img/book.png" style="width:24rpx;height: 24rpx;"></image>
视频
</view>
<view class="name">{{form.videoUrl.name}}</view>
<view class="playBtn" @click="play('v')">
<image src="@/course/img/play.png" style="width:48rpx;height: 48rpx;"></image>
</view>
</view>
<!-- <view v-if="!isBuy" style="padding:0 30rpx;">
<view class="text-warning">未购买可体验十秒</view>
</view> -->
<view style="height: 200rpx;"></view>
<view class="fixedBottom">
<!-- form.isFree==1&&!isBuy -->
<button class="btn btn-submit" v-if="!isBuy" @click="goBill">立即兑换</button>
<button class="btn btn-submit" v-else @click="goBill">立即学习</button>
</view>
</view>
</template>
<script setup>
import {
onLoad,
onShow,onReady
} from '@dcloudio/uni-app';
import config from '@/config.js';
import {
ref,
getCurrentInstance
} from 'vue';
import * as api from '@/common/api.js';
const form = ref({})
const playVideo = ref(false)
const playAudio = ref(false)
const isBuy = ref(false)
const myvideo = ref(null)
const myaudio = ref(null)
const vUrl = ref('')
const system = uni.getStorageSync('systemType')
let goodsId = ''
onLoad((option) => {
if (option.id) {
goodsId = option.id
}
uni.showShareMenu({
withShareTicket: true,
menus: ['shareAppMessage', 'shareTimeline']
});
getData(goodsId)
})
onShow(() => {
api.getUserIsPay({
orderType: 0,
goodsId: goodsId
}).then(Response => {
isBuy.value = Response.data
})
})
function getData(id) {
uni.showLoading({
title: '加载中'
})
api.getCourseById(id).then(res => {
form.value = res.data
if (form.value.audioUrl) {
form.value.audioUrl = JSON.parse(form.value.audioUrl)
myaudio.value = uni.createVideoContext('myAudio', this)
}
if (form.value.videoUrl) {
form.value.videoUrl = JSON.parse(form.value.videoUrl)
vUrl.value = config.baseUrl_api+form.value.videoUrl?.url
myvideo.value = uni.createVideoContext('myVideo', this)
myvideo.value.stop()
}
uni.hideLoading()
console.log(vUrl.value)
})
}
function goBill() {
if(isBuy.value){
if(form.value.videoUrl){
play('v')
} else if(form.value.audioUrl){
play('a')
}
}else{
if(form.value.isFree == 0){
api.submitOrder({
orderType: 0,
goodsId: form.value.courseId,
payType: "0"
}).then(res => {
uni.showModal({
content:'已兑换!',
success:function(respons){
if(respons.confirm){
api.getUserIsPay({
orderType: 0,
goodsId: goodsId
}).then(Response => {
isBuy.value = Response.data
})
}
}
})
})
} else {
const obj = encodeURIComponent(JSON.stringify(form.value))
let path = `/course/courseBill?form=${obj}`
uni.navigateTo({
url: path
});
}
}
}
function play(flag) {
// const mate = encodeURIComponent(JSON.stringify(form.value))
if(flag=='v'){
console.log(vUrl.value)
playVideo.value = true
playAudio.value = false
myvideo.value.play()
}
if(flag=='a'){
playAudio.value = true
playVideo.value = false
myaudio.value.play()
}
// if (isBuy.value) {
// let path = `/course/play/play?obj=${mate}&flag=${flag}&isBuy=${isBuy.value}`
// uni.navigateTo({
// url: path
// });
// } else {
// uni.showToast({
// title: '请购买课程',
// icon: 'none'
// })
// }
}
function videoErrorCallback(e){
console.log(e)
}
function videoing(e) {
// console.log(e.detail.currentTime)
if (form.value.isFree==1 && !isBuy.value && e.detail.currentTime > 10) {
console.log('111')
myvideo.value.pause()
playVideo.value = false
uni.showModal({
content: '试看结束,请兑换课程',
success: function(res) {
if (res.confirm) {
goBill()
} else {
myvideo.value.stop()
}
}
})
}
}
function audioing(e) {
// console.log(e.detail.currentTime)
if (form.value.isFree==1 && !isBuy.value && e.detail.currentTime >= 10) {
console.log('111')
myaudio.value.stop()
playAudio.value = false
uni.showModal({
content: '试看结束,请兑换课程',
success: function(res) {
if (res.confirm) {
goBill()
}
}
})
}
}
</script>
<style scoped lang="scss">
.whitebg {
background: #fff;
padding: 25rpx;
}
.plane {
background: #fff;
width: 700rpx;
border-radius: 15rpx;
margin: 30rpx auto;
padding: 25rpx;
box-sizing: border-box;
.phead {
border-bottom: 1rpx solid #eee;
display: flex;
justify-content: space-between;
padding: 0 0 15rpx;
align-items: center;
font-size: 30rpx;
box-sizing: border-box;
.text-warning {
font-size: 28rpx;
}
.tag01 {}
}
.pbody {
padding: 15rpx 0;
box-sizing: border-box;
line-height: 40rpx;
font-size: 28rpx;
color: #4C5359;
}
}
.wList {
background: #fff;
padding: 36rpx 23rpx;
box-sizing: border-box;
border-radius: 15rpx;
width: 700rpx;
margin: 0 auto 30rpx;
position: relative;
.pp {
display: flex;
color: #8F8E94;
font-size: 24rpx;
align-items: center;
image {
margin-right: 6rpx;
}
}
.name {
color: #2B3133;
font-size: 30rpx;
margin: 15rpx 0 0;
}
.playBtn {
position: absolute;
right: 24rpx;
top: 0;
bottom: 0;
margin: auto;
height: 48rpx;
}
}
.text-warning {
color: #F39800;
}
.ccover {
width: 700rpx;
margin: 0 auto 30rpx;
display: block;
height: 320rpx;
background: #85A6E0;
border-radius: 15rpx;
}
.whitebg {
.name {
font-size: 32rpx;
}
.text-warning {
font-size: 26rpx;
margin: 10rpx 0 0;
}
}
</style>
\ No newline at end of file
<template>
<view class="playBox" v-show="!loading">
<audio v-if="flag=='a'" style="text-align: left" :src="config.baseUrl_api+form.audioUrl?.url"
:poster="config.baseUrl_api+form.coursePic" :name="form.audioUrl?.name" :author="form.speaker" controls
@timeupdate="audioing" id="myAudio"></audio>
<video v-if="flag=='v'" ref="myvideo" @timeupdate="videoing" id="myVideo"
:src="config.baseUrl_api+form.videoUrl?.url" controls></video>
<view v-if="isBuy=='false'">
<view class="text-warning" v-if="flag=='v'">未购买可试看十秒</view>
<view class="text-warning" v-if="flag=='a'">未购买可试听十秒</view>
</view>
</view>
</template>
<script setup>
import {
onLoad,
onShow,
onReady
} from '@dcloudio/uni-app';
import config from '@/config.js';
import {
ref,
getCurrentInstance
} from 'vue';
import * as api from '@/common/api.js';
const form = ref({})
const flag = ref('')
const isBuy = ref()
const myvideo = ref(null)
const myaudio = ref(null)
const loading = ref(true)
onLoad((option) => {
console.log(option)
if ('obj' in option) {
form.value = JSON.parse(decodeURIComponent(option.obj))
console.log(form.value.videoUrl.url)
loading.value = false
}
flag.value = option.flag
isBuy.value = option.isBuy
})
onReady(() => {
if (flag.value == 'a') {
uni.setNavigationBarTitle({
title: form.value.audioUrl.name
});
myaudio.value = uni.createVideoContext('myAudio', this)
} else if (flag.value == 'v') {
uni.setNavigationBarTitle({
title: form.value.videoUrl.name
});
myvideo.value = uni.createVideoContext('myVideo', this)
}
})
function videoing(e) {
// console.log(e.detail.currentTime)
if (e.detail.currentTime > 10) {
myvideo.value.pause()
uni.showModal({
content: '试看结束,请购买课程',
success: function(res) {
if (res.confirm) {
uni.navigateBack()
} else {
myvideo.value.stop()
}
}
})
}
}
function audioing(e) {
// console.log(e.detail.currentTime)
if (e.detail.currentTime > 10) {
myaudio.value.pause()
uni.showModal({
content: '试看结束,请购买课程',
success: function(res) {
if (res.confirm) {
uni.navigateBack()
} else {
myaudio.value.stop()
}
}
})
}
}
</script>
<style scoped lang="scss">
.playBox {
text-align: center;
margin: 5vh 0;
}
</style>
\ No newline at end of file
<template>
<view>
<view style="height: calc(100vh - 150rpx);overflow: auto;">
<view class="coverbox">
<!-- <image class="cover" :src="config.baseUrl_api+form.images"/> -->
<image class="cover" src="@/exam/img/bg@2x.png"/>
<view class="name">{{form.paperName}}</view>
</view>
<view class="card">
<view class="beif">{{form.instruction}}</view>
<view class="garybox">
<view>关键字:{{form.tags}}</view>
<view>适用范围:{{form.radius}}</view>
<view>题目数量:10</view>
<view>评定时间:{{form.evalTime}}分钟</view>
</view>
<view class="redbox">
<view class="tt">指导语</view>
<view>{{form.description}}</view>
</view>
</view>
</view>
<view class="bottomFunc">
<button class="submit-btn" v-if="status==-1" style="width: 380rpx;" @click="start(0)">开始测评</button>
<button class="submit-btn" v-if="status==0" style="width: 380rpx;" @click="start(1)">继续测评</button>
<button class="submit-btn" v-if="status==1" @click="start(2)">重新测评</button>
<button class="submit-btn2" v-if="status==1" @click="goResult">查看结果</button>
</view>
<uni-popup ref="popYanZheng" type="center">
<view class="popup-body">
<view class="tt">请输入个人信息</view>
<uni-forms>
<uni-forms-item label="姓名">
<uni-easyinput v-model="formPut.nickName" placeholder="请输入姓名" />
</uni-forms-item>
<uni-forms-item label="手机号码">
<uni-easyinput v-model="formPut.phonenumber" placeholder="请输入手机号码" />
</uni-forms-item>
<button class="submit-btn" style="width: 380rpx;" @click="submitForm">开始测评</button>
</uni-forms>
</view>
</uni-popup>
</view>
</template>
<script setup>
import {
onLoad,onShow
} from '@dcloudio/uni-app'
import * as api from '@/common/api.js';
import config from '@/config.js';
import * as loginServer from '@/common/login.js';
import _ from 'lodash'
import {
ref,
getCurrentInstance
} from 'vue';
import dayjs from 'dayjs'
const app = getApp();
const {
proxy
} = getCurrentInstance()
const current = ref(0);
const popYanZheng = ref(null);
const form = ref({});
const status = ref(0);
const formPut = ref({});
let paperId = ''
onShow(() => {
if (app.globalData.isLogin) {
init();
} else {
app.firstLoadCallback = () => {
init();
};
}
})
onLoad((option) => {
uni.showLoading({
title: '加载中'
});
paperId = option.id
})
function init(){
api.getPaperInfo(paperId).then(res=>{
form.value = res.data
uni.hideLoading()
})
api.getState(paperId).then(res=>{
status.value = res.msg
})
}
let currUser
function checkUserPhone() {
currUser = uni.getStorageSync('currUser')
if (!currUser) {
loginServer.pcLogin().then(() => {
currUser = uni.getStorageSync('currUser')
if (currUser.phonenumber) {
return true
} else {
popYanZheng.value.open()
return false;
}
});
} else {
if (currUser.phonenumber) {
return true
} else {
popYanZheng.value.open()
return false;
}
}
}
function start(flag){
//验证手机号
if (checkUserPhone()) {
goDoText(flag)
}
}
function goDoText(flag){
let path = `/exam/subject?id=${paperId}&flag=${flag}`;
uni.navigateTo({
url: path
});
}
function goResult(){
let path = `/exam/result?id=${paperId}`;
uni.navigateTo({
url: path
});
}
// 订阅
function subscribe() {
// 场馆预订成功通知 订场取消提醒 订单退款通知
uni.requestSubscribeMessage({
tmplIds: ['p7_a1SGyGvJeOdwx_GKl6UlrWiWpNnejUArbnEPf-k4'],
success: (res) => {
console.log('success:', res)
}
})
}
function submitForm(flag){
if(!formPut.value.nickName){
uni.showToast({
title:`请输入姓名`,
icon:'none'
})
return
}
if(!formPut.value.phonenumber){
uni.showToast({
title:`请输入手机号码`,
icon:'none'
})
return
}
api.updateUserInfo(formPut.value).then(res=>{
goDoText()
loginServer.getCurrUser()
})
}
</script>
<style lang="scss" scoped>
.card{background: #fff;border-radius: 30rpx;padding: 50rpx 40rpx;
position: relative;top:-30rpx;
.beif{font-size: 30rpx;}
}
.garybox{border-radius: 15rpx;background: #F5F8FA;padding: 30rpx 38rpx;margin-top: 30rpx;
font-size: 30rpx;line-height: 2;color: #030303;
}
.redbox{border-radius: 15rpx;background: rgba(242, 156, 159, 0.36);padding: 30rpx 38rpx;
margin-top: 30rpx;line-height: 1.5;
.tt{color: RGBA(230, 0, 18, 1);margin-bottom:26rpx;
font-weight: 600;}
}
.popup-body{ background-color: #fff;padding: 50rpx;
.tt{margin-bottom:40rpx;}
}
.coverbox{height: 240rpx;position: relative;
.cover{width: 100%;height: 240rpx;}
.name{position: absolute;color: #fff;
font-size: 36rpx;top:40%;left: 40rpx;width: 8em;}
}
</style>
<template>
<view>
<view class="whitebg">
<view class="resultbox" v-for="(form,index) in formlist" :key="index">
<view class="ppbar">
<view class="bar-text">
<view v-for="n in form.evalTutorVoList" :style="{width: ((n.maxScore-n.minScore)/(form.evalTutorVoList[form.evalTutorVoList.length-1]?.maxScore-form.evalTutorVoList[0]?.minScore)*100) +'%'}">
<text class="brr">123</text>
<!-- <view>
<text>{{Math.floor(n.minScore)}}</text>
<text>{{Math.floor(n.maxScore)}}</text>
</view> -->
</view>
</view>
<view class="bar-bg"></view>
<view class="dotbox" :style="{left: (form.score/(form.evalTutorVoList[form.evalTutorVoList.length-1]?.maxScore-form.evalTutorVoList[0]?.minScore)*100) +'%'}">
<text>{{form.score}}</text>
<image src="@/exam/img/dian.png" />
</view>
</view>
<view>
<view class="flexline" v-if="formlist.length>1">
<label>测评条目</label>
<view>{{form.title}}</view>
</view>
<view class="flexline">
<label>测评结果</label>
<view>{{form.desc}}</view>
</view>
<view class="flexline">
<label>辅导建议</label>
<view>{{form.expression}}</view>
</view>
</view>
</view>
<view class="content">
{{paperInfo.instruction}}
</view>
<button class="sharebtn" @click="showRecmand">分享测试</button>
<!-- <button class="sharebtn" open-type="share" @click="showRecmand">分享测试</button> -->
</view>
<view v-if="reclist?.length>0">
<view class="tbar">
相关测评
</view>
<view class="list">
<view class="item" v-for="n in reclist" :key="n" @click="goDetail">
<image :src="config.baseUrl_api + n.images"></image>
<view class="info">
<view class="tt esp_2">{{n.paperName}}</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import * as api from '@/common/api.js';
import config from '@/config.js';
import {
onLoad,
onShow,
onShareAppMessage,
onShareTimeline,
onPullDownRefresh
} from '@dcloudio/uni-app';
import {
ref,
getCurrentInstance
} from 'vue';
const app = getApp();
const formlist = ref([])
const paperInfo = ref({})
const reclist = ref([])
const recImg = ref('')
let paperId = ''
onLoad((option)=>{
paperId = option.id
})
onShow(() => {
if (app.globalData.isLogin) {
init();
} else {
app.firstLoadCallback = () => {
init();
};
}
})
function init(){
uni.showLoading({
title:'加载中'
})
api.getUserAnswerResult({paperId:paperId}).then(res=>{
formlist.value = res.data
uni.hideLoading()
})
api.getPaperInfo(paperId).then(res=>{
paperInfo.value = res.data
})
getReclist()
}
function getReclist(){
api.getHomePageHot().then(res=>{
reclist.value = res.data
})
}
onShareAppMessage(() => {
return {
title: '',
path: `/exam/subject?id=${paperId}`
// imageUrl: app.globalData.baseUrl + project.value.proPic
};
});
onShareTimeline(() => {
return {
title: '',
path: '/pages/index/index'
// imageUrl: app.globalData.baseUrl + project.value.proPic
};
});
function showRecmand(){
uni.showLoading({
title:'加载中'
})
const currUser = uni.getStorageSync('currUser')
api.getExclusiveImage(currUser.userId).then(res=>{
recImg.value = 'data:image/png;base64,' + res.msg
// showRecImg.value = true
clickImg()
uni.hideLoading()
})
}
function clickImg() {
uni.previewImage({
urls: [recImg.value],
// current: 0,
success: function(res) {
console.log('success', res)
},
fail: function(res) {
console.log('fail', res)
},
complete: function(res) {
console.log('complete', res)
}
})
}
</script>
<style lang="scss" scoped>
.whitebg {
background: #fff;
padding: 60rpx 30rpx;
}
.resultbox {
color: #fff;margin: 0 0 20rpx;
padding: 30rpx;border-radius: 20rpx;overflow: hidden;
background: linear-gradient(90deg, #81A7F3, #A2CCF1);
.ppbar {
position: relative;margin-bottom: 40rpx;
.bar-bg {
height: 10rpx;
background: #fff;
opacity: 0.4;
border-radius: 0rpx;position: absolute;width: 100%;
left: 0;top: 100rpx;
}
.bar-text {background:linear-gradient(90deg,rgba(255,255,255,0),rgba(255,255,255,0.6));
text-align: center;
display: flex;
justify-content: space-between;
font-size: 28rpx;
// line-height: 100rpx;
.brr{border-right: 1rpx solid #82a7f3;height: 100rpx;display: inline-block;
width: 100%;text-align: center;color: transparent;}
view {flex: 1 1 auto;
view{display: flex;justify-content: space-between;
text{padding: 0 4rpx;opacity: 0;}
}
&:last-child .brr{border-right:none;}
}
}
.dotbox {text-align: center;margin-left: -32rpx;
position: absolute;top: 26rpx;
text{display: block;font-size: 34rpx;font-weight: bold;padding: 0 10rpx;
color: #82a7f3; margin: 0 0 14rpx 0;background-color: #fff;border-radius: 10rpx;
position: relative;
&::after{
content: '';position: absolute;bottom: -10rpx;left: 0;right: 0;
margin: auto;
width: 0;
height: 0;
border-left: 10rpx solid transparent;
border-right: 10rpx solid transparent;
border-top: 10rpx solid #fff;
}
}
image {
width: 42rpx;
height: 42rpx;
}
}
}
.flexline {
display: flex;margin: 0 0 20rpx;
label {
opacity: 0.6; flex: 0 0 auto;
margin-right: 40rpx;
}
view{
flex: 1 1 auto;
}
}
}
.content {padding: 20rpx;
margin: 20rpx 0;
font-size: 30rpx;
font-weight: 400;
line-height: 44rpx;
color: #030303;
}
.sharebtn {
height: 70rpx;
width: 50%;
color: #FFFFFF;
font-size: 30rpx;
background: #F89D46;
border-radius: 35rpx;
}
.list {
padding: 24rpx 0 0 24rpx;
overflow: hidden;
}
.item {
border-radius: 15rpx;
background: #fff;
width: 338rpx;
float: left;
margin: 0 24rpx 24rpx 0;
image {
height: 180rpx;
width: 100%;
}
.info {
padding: 20rpx 26rpx;
height: 100rpx;
box-sizing: border-box;
.tt {
font-size: 28rpx;
line-height: 36rpx;
}
}
}
.tbar {
padding: 0 25rpx;
margin: 40rpx 0 10rpx;
text {
float: right;
color: #929AA0;
background: #fff;
border-radius: 20rpx;
padding: 0 14rpx;
}
}
</style>
\ No newline at end of file
<template>
<view>
<view>
<!-- 进度条 -->
<view class="progress">
<view><text class="bigsize">{{current}}</text>/{{list.length}}</view>
<view class="pbody">
<view class="pxin" :style="{width: current/list.length*100 +'%'}"></view>
</view>
</view>
<view class="sArea" v-for="(s,index) in list" :key="index" v-show="current == Number(s.quesNo)">
<view class="tgan">
<text class="must">*</text>
{{s.quesNo}}. {{s.quesTitle}}
</view>
<view class="option" v-for="(o, oindex) in s.evalOptionsList" :key="oindex" :class="o.status==1?'active':''"
@click="changeOption(o,s.evalOptionsList)">
<view class="check">
<image src="@/exam/img/xz@2x.png" />
</view>
<view class="checked">
<image src="@/exam/img/xz_dwn@2x.png" />
</view>
{{opArr[oindex]}}. {{o.title}}
</view>
</view>
<view class="bottomFunc">
<view v-if="current==1" style="opacity: 0.5"><image src="@/exam/img/prev@2x.png"/>上一题</view>
<view v-else @click="goPrev"><image src="@/exam/img/prev@2x.png"/>上一题</view>
<view @click="submit" class="submit-btn" v-if="current == list.length">提交测评</view>
<view v-if="canNext&&current != list.length" @click="goNext">下一题<image src="@/exam/img/next@2x.png"/></view>
<view v-if="!canNext&&current != list.length" style="opacity: 0.5" @click="showTip">下一题<image src="@/exam/img/next@2x.png"/></view>
</view>
</view>
</view>
</template>
<script setup>
import {
nextTick,
ref
} from 'vue';
import {
onLoad,
onShow
} from '@dcloudio/uni-app';
import _ from 'lodash';
import dayjs from 'dayjs';
import * as api from '@/common/api.js';
const app = getApp();
const list = ref([])
const options = ref([])
const query = ref({
state:0
})
const current = ref(1)
const canNext = ref(false)
const opArr = ref(['A','B','C','D','E','F'])
let answerId = ''
let flag = 0
onLoad(option=>{
query.value.paperId = option.id
if(option.flag){
flag = option.flag
}
console.log(option.flag)
})
onShow(() => {
if (app.globalData.isLogin) {
init()
} else {
app.firstLoadCallback = () => {
init()
};
}
});
function init(){
uni.showLoading({
title:'加载中'
})
if(flag==2){
// 重新测评
query.value.state = 1
}
api.getUserAnswerInfo(query.value).then(res=>{
list.value = res.data.userAnswerList
answerId = res.data.answerId
if(flag==1){
skip()
}
uni.hideLoading()
})
}
function skip(){
for(var item of list.value){
for(var option of item.evalOptionsList){
if(option.status == 1){
current.value = current.value + 1
}
}
}
console.log(current.value)
}
function changeOption(t,list){
// 单选
for(var item of list){
if(item.optionId == t.optionId){
if(item.status == 1){
item.status = 0
canNext.value = false
}else{
item.status = 1
canNext.value = true
}
} else {
item.status = 0
}
}
}
function showTip(){
uni.showToast({
title:'请选择后前往下一题',
icon:'none'
})
}
function goNext(){
current.value = current.value + 1
canNext.value = false
for(var item of list.value){
if(item.quesNo==current.value){
for(var option of item.evalOptionsList){
if(option.status == 1){
canNext.value = true
}
}
}
}
save()
}
function goPrev(){
current.value = current.value - 1
canNext.value = true
}
function save(){
var obj = {
answerId:answerId,
paperId:query.value.paperId,
userAnswerList:list.value
}
api.saveAnswer(obj).then(res=>{
})
}
function submit(){
if(canNext.value){
uni.showLoading({
title:'提交中'
})
var obj = {
answerId:answerId,
paperId:query.value.paperId,
userAnswerList:list.value
}
api.submitAnswer(obj).then(res=>{
uni.hideLoading()
let path = `/exam/result?id=${query.value.paperId}`
uni.redirectTo({
url: path
});
})
} else {
uni.showToast({
title:'请选择后提交',
icon:'none'
})
}
}
</script>
<style lang="scss" scoped>
.progress {
color: #8F8E94;
font-size: 30rpx;
padding: 20rpx;
display: flex;
align-items: center;
.bigsize {
color: #030303;
font-size: 48rpx;
}
.pbody {
height: 10rpx;
background: #D0D5D8;
border-radius: 5rpx;
width: 100%;
margin-left: 20px;
position: relative;
overflow: hidden;
.pxin {
background: linear-gradient(90deg, #FFCE56, #F79A45);
height: 100%;
border-radius: 5rpx;
}
}
}
.must {
color: #DC0032;
}
.sArea {
background: #fff;
padding: 25rpx;
border-radius: 30rpx;
.tgan {
padding: 20rpx;
line-height: 1.6;
text-align: justify;
}
.option {
padding: 30rpx;
color: #000000;
font-size: 30rpx;
background: #F5F8FA;
margin-bottom: 20rpx;
border-radius: 20rpx;
display: flex;
&.active {
color: #fff;
// background: #F89D46;
background: linear-gradient(90deg, #fec45a, #F89D46);
.check {
display: none;
}
.checked {
display: block;
}
}
.check {
display: block;
margin-right: 20rpx;
}
.checked {
display: none;
margin-right: 20rpx;
}
.check image {
width: 40rpx;
height: 40rpx;
}
.checked image {
width: 40rpx;
height: 40rpx;
}
}
}
</style>
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<title>心理测评</title>
<!--preload-links-->
<!--app-context-->
<style>
* {
box-sizing: border-box;
}
</style>
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/main.js"></script>
</body>
</html>
import App from './App'
// #ifndef VUE3
import Vue from 'vue'
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()
// #endif
// #ifdef VUE3
import {
createSSRApp
} from 'vue'
export function createApp() {
const app = createSSRApp(App)
return {
app
}
}
// #endif
{
"name" : "baize",
"appid" : "__UNI__580BCB0",
"description" : "",
"versionName" : "1.0.1",
"versionCode" : "100",
"transformPx" : false,
/* 5+App特有相关 */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
/* 模块配置 */
"modules" : {},
/* 应用发布信息 */
"distribute" : {
/* android打包配置 */
"android" : {
"permissions" : [],
"autoSdkPermissions" : true
},
/* ios打包配置 */
"ios" : {
"permissions" : [],
"autoSdkPermissions" : true
},
/* SDK配置 */
"sdkConfigs" : {}
}
},
/* 快应用特有相关 */
"quickapp" : {},
/* 小程序特有相关 */
"mp-weixin" : {
"appid" : "wxc1e303a29052b843", //
"setting" : {
"urlCheck" : false,
"minified" : false,
"es6" : true
},
"usingComponents" : true,
"permission" : {},
"optimization" : {
"subPackages" : true
}
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "3"
}
{
"dependencies": {
"dayjs": "^1.11.6",
"lodash": "^4.17.21"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^22.0.0"
}
}
{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页",
"backgroundColor": "#ffffff",
"navigationStyle": "default",
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "#ffffff"
}
},
{
"path": "pages/form/index",
"style": {
"navigationStyle": "default",
"navigationBarBackgroundColor": "#F7F8FA",
"navigationBarTextStyle": "black",
"navigationBarTitleText": "反馈",
"enablePullDownRefresh": false
}
}, {
"path": "pages/index/list",
"style": {
"navigationStyle": "default",
"navigationBarBackgroundColor": "#F7F8FA",
"navigationBarTextStyle": "black",
"navigationBarTitleText": "列表",
"enablePullDownRefresh": false
}
},
{
"path": "pages/course/course",
"style": {
"navigationBarTitleText": "课程",
"enablePullDownRefresh": false
}
},
{
"path": "pages/active/active",
"style": {
"navigationBarTitleText": "活动",
"enablePullDownRefresh": false
}
},
{
"path": "pages/usercenter",
"style": {
"navigationBarTitleText": "个人中心",
"enablePullDownRefresh": false
}
}
],
"globalStyle": {
"navigationStyle": "default",
"navigationBarBackgroundColor": "#F7F8FA",
"navigationBarTextStyle": "black",
"navigationBarTitleText": "测评"
},
"subPackages": [{
"root": "usercenter",
"pages": [ {
"path": "myInfo",
"style": {
"navigationStyle": "default",
"navigationBarBackgroundColor": "#F7F8FA",
"navigationBarTextStyle": "black",
"navigationBarTitleText": "个人信息",
"enablePullDownRefresh": false,
"onReachBottomDistance": 100,
"backgroundColor": "#ffffff"
}
},
{
"path": "myPaper",
"style": {
"navigationBarTitleText": "我的报告",
"enablePullDownRefresh": false
}
},
{
"path": "myCompany",
"style": {
"navigationBarTitleText": "机构认证",
"enablePullDownRefresh": false
}
},
{
"path": "about",
"style": {
"navigationBarTitleText": "关于我们",
"enablePullDownRefresh": false
}
},
{
"path": "myReservation",
"style": {
"navigationBarTitleText": "我的预约",
"enablePullDownRefresh": false
}
},
{
"path": "myCourse",
"style": {
"navigationBarTitleText": "我的课程",
"enablePullDownRefresh": false
}
},
{
"path": "mycard/renew",
"style": {
"navigationBarTitleText": "金币充值",
"enablePullDownRefresh": false
}
},
{
"path": "mycard/mycard",
"style": {
"navigationBarTitleText": "消费记录",
"enablePullDownRefresh": false
}
}
]
}, {
"root": "course",
"pages": [{
"path": "courseDetail",
"style": {
"navigationBarTitleText": "课程详情",
"enablePullDownRefresh": false
}
}, {
"path": "activeDetail",
"style": {
"navigationBarTitleText": "活动详情",
"enablePullDownRefresh": false
}
}, {
"path": "courseBill",
"style": {
"navigationBarTitleText": "课程订单",
"enablePullDownRefresh": false
}
}, {
"path": "play/play",
"style": {
"navigationBarTitleText": "播放",
"enablePullDownRefresh": false
}
}]
},{
"root": "exam",
"pages": [{
"path": "booking",
"style": {
"navigationBarTitleText": "详情",
"enablePullDownRefresh": false,
"navigationStyle": "default",
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "#F7F8FA"
}
},{
"path": "result",
"style": {
"navigationBarTitleText": "测评结果",
"enablePullDownRefresh": false
}
}, {
"path": "subject",
"style": {
"navigationBarTitleText": "测试",
"enablePullDownRefresh": false,
"navigationStyle": "default",
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "#fff"
}
}]
}],
"preloadRule": {
"pages/index/index": {
"network": "all",
"packages": ["usercenter", "course","exam"]
}
},
"tabBar": {
"color": "#929AA0",
"selectedColor": "#EA8320",
"borderStyle": "white",
"backgroundColor": "#ffffff",
"list": [{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "static/home.png",
"selectedIconPath": "static/home_dwn.png"
},
{
"pagePath": "pages/index/list",
"text": "测评",
"iconPath": "static/cp.png",
"selectedIconPath": "static/cp_dwn.png"
},
{
"pagePath": "pages/course/course",
"text": "课程",
"iconPath": "static/kc.png",
"selectedIconPath": "static/kc_dwn.png"
},
{
"pagePath": "pages/active/active",
"text": "活动",
"iconPath": "static/hd.png",
"selectedIconPath": "static/hd_dwn.png"
},
{
"pagePath": "pages/usercenter",
"text": "我的",
"iconPath": "static/mine.png",
"selectedIconPath": "static/mine_dwn.png"
}
]
}
}
\ No newline at end of file
<template>
<view>
<view class="search-area">
<uni-easyinput prefixIcon="search" v-model="query.activityName" placeholder="搜索活动名称"
@clear="getList" @change="getList">
</uni-easyinput>
</view>
<view class="imageFlowBox">
<view class="imageFlow">
<view v-for="(b,index) in alist" :key="b.activityId" @click="goDetail(b)">
<image mode="aspectFit" :src="config.baseUrl_api+b.activityPic" class="cover"></image>
</view>
</view>
</view>
<view class="tbar">
全部活动
</view>
<view class="list">
<view class="acitem" v-for="n in list" :key="n.activityId" @click="goDetail(n)">
<view class="acbody">
<image :src="config.baseUrl_api+n.activityPic" mode="aspectFit"></image>
<view class="info">
<view class="tt">{{n.activityName}}</view>
<view class="pp">
<uni-icons type="notification" size="12" />
{{n.startTime}} ~ {{n.endTime}}
</view>
<view class="pp mt20">
<uni-icons type="location" size="12" />
{{n.address}}
</view>
<view class="text-warning" v-if="n.isFree==1">金币{{n.allGold}}/积分{{n.allScore}}</view>
<view class="text-warning" v-else>免费</view>
</view>
</view>
<view class="acfoot">
<view>
<!-- <uni-icons type="person" size="12"></uni-icons> -->
<!-- 已有 222人报名参加 -->
</view>
<button class="btn btn1">我要报名</button>
</view>
</view>
</view>
<view class="nodata" v-if="list.length==0">
<image mode="aspectFit" src="/static/nodata.png"></image>
</view>
</view>
</template>
<script setup>
import {
onLoad,
onShow
} from '@dcloudio/uni-app';
import config from '@/config.js';
import {
ref,
getCurrentInstance
} from 'vue';
import * as api from '@/common/api.js';
const list = ref([])
const alist = ref([])
const query = ref({
activityName: ''
})
const system = uni.getStorageSync('systemType');
onShow(() => {
init()
})
function init() {
uni.showLoading({
title: `加载中`
})
getList()
getHotList()
}
function getHotList(){
api.getHomePageHotActive().then(res => {
alist.value = res.data
uni.hideLoading()
})
}
function getList() {
api.getActivityList(query.value).then(res => {
list.value = res.rows
uni.hideLoading()
})
}
function goDetail(item) {
let path = `/course/activeDetail?id=${item.activityId}`;
uni.navigateTo({
url: path
});
}
</script>
<style lang="scss" scoped>
.imageFlowBox {
position: relative;
height: 300rpx;
overflow: auto;
}
.imageFlow {
display: flex;
position: absolute;
left: 0;
padding: 0 10rpx;
&>view {
border-radius: 10px;
overflow: hidden;
width: 630rpx;
height: 300rpx;
margin: 0 10rpx;
position: relative;
}
image {
width: 630rpx;
height: 300rpx;
}
.info {
position: absolute;
color: #fff;
top: 0;
width: 100%;
height: 100%;
padding: 30rpx 40rpx;
overflow: hidden;
box-sizing: border-box;
.name {
font-size: 34rpx;
color: #fff;
padding-bottom: 20rpx;
margin-bottom: 20rpx;
border-bottom: 1px solid RGBA(255, 255, 255, 0.7);
}
}
.esp_2 {
font-size: 28rpx;
margin-bottom: 26rpx;
}
.timeblock {
background: rgba(27, 27, 27, 0.1);
border-radius: 25rpx;
font-size: 22rpx;
padding: 12rpx 17rpx;
display: inline-flex;
align-items: center;
image {
width: 28rpx;
height: 28rpx;
margin-left: 22rpx;
}
}
}
.list {
padding: 24rpx 0 0 24rpx;
overflow: hidden;
}
</style>
\ No newline at end of file
<template>
<view>
<view class="search-area">
<uni-easyinput prefixIcon="search" v-model="query.courseName" placeholder="搜索课程名称"
@change="getList" @clear="getList">
</uni-easyinput>
</view>
<view class="imageFlowBox">
<view class="imageFlow">
<view v-for="(b,index) in clist" :key="b.courseId" @click="goDetail(b)">
<image mode="aspectFill" :src="config.baseUrl_api+b.coursePic" class="cover"></image>
<!-- <div class="info">
<h3 class="name esp">{{b.paperName}}</h3>
<p class="esp_2">{{b.description}}</p>
<view class="timeblock">预计用时 {{b.evalTime}}分钟
</view>
</div> -->
</view>
</view>
</view>
<view class="tbar">
全部课程
</view>
<view class="list">
<view class="kcitem" v-for="n in list" :key="n.courseId" @click="goDetail(n)">
<image :src="config.baseUrl_api+n.coursePic" mode="aspectFill"></image>
<view class="info">
<view class="tt esp_2">{{n.courseName}}</view>
<!-- <view class="pp"><uni-icons type="chatboxes" size="12" />209w 学习</view> -->
<view class="text-warning" v-if="n.isFree==0">免费</view>
<view class="text-warning" v-else>金币{{n.allGold}}/积分{{n.allScore}}</view>
</view>
</view>
</view>
<view class="nodata" v-if="list.length==0">
<image mode="aspectFit" src="/static/nodata.png"></image>
</view>
</view>
</template>
<script setup>
import {
onLoad,
onShow
} from '@dcloudio/uni-app';
import config from '@/config.js';
import {
ref,
getCurrentInstance
} from 'vue';
import * as api from '@/common/api.js';
const list = ref([])
const clist = ref([])
const kindList = ref([])
const kindId = ref('')
const query = ref({
courseName:''
})
const system = uni.getStorageSync('systemType');
onShow(() => {
init()
})
function init() {
getList()
getHot()
}
function getHot(){
uni.showLoading({
title:`加载中`
})
api.getHomePageHotCourse().then(res => {
clist.value = res.data
uni.hideLoading()
})
}
function getList() {
uni.showLoading({
title:`加载中`
})
api.getCourseList(query.value).then(res => {
list.value = res.rows
uni.hideLoading()
})
}
function goDetail(item) {
let path = `/course/courseDetail?id=${item.courseId}`;
uni.navigateTo({
url: path
});
}
</script>
<style lang="scss" scoped>
.imageFlowBox {
position: relative;
height: 300rpx;
overflow: auto;
}
.imageFlow {
display: flex;
position: absolute;
left: 0;
padding: 0 10rpx;
&>view { border-radius: 10px;
overflow: hidden;
width: 630rpx;
height: 300rpx;
margin: 0 10rpx;
position: relative;
}
image {
width: 630rpx;
height: 300rpx;
}
.info {
position: absolute;
color: #fff;
top: 0;
width: 100%;
height: 100%;
padding: 30rpx 40rpx;
overflow: hidden;
box-sizing: border-box;
.name {
font-size: 34rpx;
color: #fff;
padding-bottom: 20rpx;
margin-bottom: 20rpx;
border-bottom: 1px solid RGBA(255, 255, 255, 0.7);
}
}
.esp_2 {
font-size: 28rpx;
margin-bottom: 26rpx;
}
.timeblock {
background: rgba(27, 27, 27, 0.1);
border-radius: 25rpx;
font-size: 22rpx;
padding: 12rpx 17rpx;
display: inline-flex;
align-items: center;
image {
width: 28rpx;
height: 28rpx;
margin-left: 22rpx;
}
}
}
.list {
padding: 24rpx 0 0 24rpx;
overflow: hidden;
}
.item {
border-radius: 15rpx;
background: #fff;
width: 338rpx;
float: left;
margin: 0 24rpx 24rpx 0;
image {
height: 180rpx;
width: 100%;
}
.info {
padding: 20rpx 26rpx;
height: 100rpx;
box-sizing: border-box;
.tt {
font-size: 28rpx;
line-height: 36rpx;
}
}
}
</style>
\ No newline at end of file
<template>
<view class="graybg">
<view v-if="formData.type=='0'">
<view v-html="formData.content" class="richContent"></view>
</view>
<view v-if="formData.type=='1'" class="formBox">
<view @click="clickImg">
<image style="width: 100%;height: 50vw;" mode="aspectFit" v-for="p in formData.picArr" :src="p"/>
</view>
<view v-if="formData.content2" v-html="formData.content2" class="richContent2"></view>
<uni-forms ref="baseForm" :modelValue="baseFormData">
<uni-forms-item label="姓名" required v-if="formData.fields.indexOf('0')>-1">
<uni-easyinput v-model="baseFormData.name" placeholder="请输入姓名" />
</uni-forms-item>
<uni-forms-item label="手机号" required v-if="formData.fields.indexOf('1')>-1">
<uni-easyinput v-model="baseFormData.telno" placeholder="请输入手机号" />
</uni-forms-item>
<uni-forms-item label="需求描述" required v-if="formData.fields.indexOf('2')>-1">
<uni-easyinput type="textarea" v-model="baseFormData.requirement" placeholder="请输入需求描述" />
</uni-forms-item>
</uni-forms>
<button type="primary" @click="submit">提交</button>
</view>
</view>
<uni-popup ref="alertPayOk" type="dialog">
<uni-popup-dialog type="success" confirmText="返回主页" content="提交成功" @confirm="goIndex">
</uni-popup-dialog>
</uni-popup>
</template>
<script setup>
import {
ref,getCurrentInstance
} from 'vue';
import {
onLoad,
onShow,onReady
} from '@dcloudio/uni-app';
import * as api from '@/common/api.js';
const { proxy } = getCurrentInstance()
const app = getApp();
const telNo = ref('');
const alertPayOk = ref(null);
const isActive = ref(null);
const formData = ref({})
const baseFormData = ref({})
const rules= ref({
name: {rules: [{required: true,errorMessage: '请输入姓名'}]},
telno: {rules: [{required: true,errorMessage: '请输入手机号'}]},
requirement: {rules: [{required: true,errorMessage: '请输入需求描述'}]},
})
onReady(()=>{
// 修改页头标题
uni.setNavigationBarTitle({
title: formData.value.name
});
})
onShow(() => {
formData.value = JSON.parse(app.globalData.venue.miniappCustConfig)
formData.value.picArr = formData.value.pics.split(',')
});
function goIndex() {
uni.redirectTo({
url: `/pages/index/index`
})
}
function submit(){
// 姓名
if((formData.value.fields.indexOf('0')>-1) && baseFormData.value.name==undefined){
uni.showToast({
title: '请输入姓名',
icon: 'none',
duration: 2000
});
return
}
// 手机号
if(formData.value.fields.indexOf('1')>-1&&baseFormData.value.telno==undefined){
uni.showToast({
title: '请输入手机号',
icon: 'none',
duration: 2000
});
return
}
// 需求描述
if(formData.value.fields.indexOf('2')>-1&&baseFormData.value.requirement==undefined){
uni.showToast({
title: '请输入需求描述',
icon: 'none',
duration: 2000
});
return
}
api.miniappData(baseFormData.value).then((res)=>{
baseFormData.value = []
alertPayOk.value.open()
})
}
function clickImg() {
uni.previewImage({
urls: formData.value.picArr,
// current: 0,
success: function(res) {
console.log('success', res)
},
fail: function(res) {
console.log('fail', res)
},
complete: function(res) {
console.log('complete', res)
}
})
}
</script>
<style scoped>
button{ font-size: 32rpx; background: linear-gradient(90deg, #00C176, #3ed89b);}
.richContent{padding: 40rpx 40rpx 100rpx;
line-height: 1.6;
background: #fff;}
.richContent2{padding: 0 0 40rpx;
line-height: 1.6;
background: #fff;}
.graybg {
background: #f7f8fa;
height: 100vh;
padding: 0 0 100rpx;
width: 100vw;
overflow: auto;
}
.whitebg {
background: #fff;
margin-top: 15rpx;
border-radius: 20rpx;
margin-bottom: 90rpx;
}
.payBtn {
width: 750rpx;
line-height: 90rpx;
height: 120rpx;
text-align: center;
background: #ff8124;
color: #ffffff;
font-size: 36rpx;
border-radius: 20rpx 20rpx 0px 0px;
position: fixed;
bottom: 0;
}
.uni-list-cell::after {
display: none;
}
.formBox{ background: #fff;
padding: 50rpx 40rpx;
margin: 0 30rpx;
border-radius: 20rpx;}
</style>
This diff could not be displayed because it is too large.
<template>
<view>
<zb-tab :activeStyle="{
fontWeight: 'bold',
transform: 'scale(1.1)'
}" lineColor='linear-gradient(90deg, #FF9D33, #F56E06);' :data="kindList" :scrollable="true" lineWidth='30rpx'
@change="getList" v-model="query.category"></zb-tab>
<view class="list">
<view class="item" v-for="n in list" :key="n.paperId" @click="goDetail(n)">
<image :src="config.baseUrl_api+n.images"></image>
<view class="info">
<view class="tt esp_2">{{n.paperName}}</view>
</view>
</view>
</view>
<view class="nodata" v-if="list.length==0">
<image mode="aspectFit" src="/static/nodata.png"></image>
</view>
</view>
</template>
<script setup>
import {
onLoad,
onShow
} from '@dcloudio/uni-app';
import config from '@/config.js';
import {
ref,
getCurrentInstance
} from 'vue';
import * as api from '@/common/api.js';
const list = ref([])
const kindList = ref([])
const kindId = ref(0)
const query = ref({
category: 2
})
onLoad((option) => {
if(option.kindId){
kindId.value = Number(option.kindId)
}
})
onShow(()=>{
init()
})
function init() {
uni.showLoading({
title:`加载中`
})
api.getClassifyList().then(res => {
kindList.value = res.data
query.value.category = kindId
getList()
})
}
function getList() {
console.log(query.value.category)
api.getPaperList(query.value).then(res => {
list.value = res.rows
uni.hideLoading()
})
}
function goDetail(item) {
let path = `/exam/booking?id=${item.paperId}`;
uni.navigateTo({
url: path
});
}
</script>
<style lang="scss" scoped>
.list {
padding: 24rpx 0 0 24rpx;
overflow: hidden;
}
.item {
border-radius: 15rpx;
background: #fff;
width: 338rpx;
float: left;
margin: 0 24rpx 24rpx 0;
image {
height: 180rpx;
width: 100%;
}
.info {
padding: 20rpx 26rpx;
height: 100rpx;
box-sizing: border-box;
.tt {
font-size: 28rpx;
line-height: 36rpx;
}
}
}
</style>
\ No newline at end of file
{
"appid": "wx5d51e8ed31bbdbb7",
"compileType": "miniprogram",
"libVersion": "3.0.0",
"packOptions": {
"ignore": [],
"include": []
},
"setting": {
"coverView": true,
"es6": true,
"postcss": true,
"minified": true,
"enhance": true,
"showShadowRootInWxmlPanel": true,
"packNpmRelationList": [],
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
},
"condition": false
},
"condition": {},
"editorSetting": {
"tabIndent": "insertSpaces",
"tabSize": 2
}
}
\ No newline at end of file
{
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
"projectname": "Venue",
"setting": {
"compileHotReLoad": true
}
}
\ No newline at end of file
@font-face {
font-family: "iconfont";
/* Project id 3873999 */
src: url('/static/font/iconfont.ttf') format('woff2'),
url('/static/font/iconfont.ttf') format('woff'),
url('/static/font/iconfont.ttf') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-31dingwei:before {
content: "\e600";
}
.icon-ai253:before {
content: "\e6f1";
}
.icon-loufangfangzi:before {
content: "\e729";
}
No preview for this file type
No preview for this file type
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
$uni-color-primary: #00C176;
$uni-color-success: #4cd964;
$uni-color-warning: #f0ad4e;
$uni-color-error: #dd524d;
/* 文字基本颜色 */
$uni-text-color:#333;//基本色
$uni-text-color-inverse:#fff;//反色
$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
$uni-text-color-placeholder: #808080;
$uni-text-color-disable:#c0c0c0;
/* 背景颜色 */
$uni-bg-color:#ffffff;
$uni-bg-color-grey:#f8f8f8;
$uni-bg-color-hover:#f1f1f1;//点击状态颜色
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
/* 边框颜色 */
$uni-border-color:#c8c7cc;
/* 尺寸变量 */
/* 文字尺寸 */
$uni-font-size-sm:12px;
$uni-font-size-base:14px;
$uni-font-size-lg:16;
/* 图片尺寸 */
$uni-img-size-sm:20px;
$uni-img-size-base:26px;
$uni-img-size-lg:40px;
/* Border Radius */
$uni-border-radius-sm: 2px;
$uni-border-radius-base: 3px;
$uni-border-radius-lg: 6px;
$uni-border-radius-circle: 50%;
/* 水平间距 */
$uni-spacing-row-sm: 5px;
$uni-spacing-row-base: 10px;
$uni-spacing-row-lg: 15px;
/* 垂直间距 */
$uni-spacing-col-sm: 4px;
$uni-spacing-col-base: 8px;
$uni-spacing-col-lg: 12px;
/* 透明度 */
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
/* 文章场景相关 */
$uni-color-title: #2C405A; // 文章标题颜色
$uni-font-size-title:20px;
$uni-color-subtitle: #555555; // 二级标题颜色
$uni-font-size-subtitle:26px;
$uni-color-paragraph: #3F536E; // 文章段落颜色
$uni-font-size-paragraph:15px;
## 1.2.0(2021-11-19)
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-badge](https://uniapp.dcloud.io/component/uniui/uni-badge)
## 1.1.7(2021-11-08)
- 优化 升级ui
- 修改 size 属性默认值调整为 small
- 修改 type 属性,默认值调整为 error,info 替换 default
## 1.1.6(2021-09-22)
- 修复 在字节小程序上样式不生效的 bug
## 1.1.5(2021-07-30)
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.1.4(2021-07-29)
- 修复 去掉 nvue 不支持css 的 align-self 属性,nvue 下不暂支持 absolute 属性
## 1.1.3(2021-06-24)
- 优化 示例项目
## 1.1.1(2021-05-12)
- 新增 组件示例地址
## 1.1.0(2021-05-12)
- 新增 uni-badge 的 absolute 属性,支持定位
- 新增 uni-badge 的 offset 属性,支持定位偏移
- 新增 uni-badge 的 is-dot 属性,支持仅显示有一个小点
- 新增 uni-badge 的 max-num 属性,支持自定义封顶的数字值,超过 99 显示99+
- 优化 uni-badge 属性 custom-style, 支持以对象形式自定义样式
## 1.0.7(2021-05-07)
- 修复 uni-badge 在 App 端,数字小于10时不是圆形的bug
- 修复 uni-badge 在父元素不是 flex 布局时,宽度缩小的bug
- 新增 uni-badge 属性 custom-style, 支持自定义样式
## 1.0.6(2021-02-04)
- 调整为uni_modules目录规范
<template>
<view class="uni-badge--x">
<slot />
<text v-if="text" :class="classNames" :style="[badgeWidth, positionStyle, customStyle, dotStyle]"
class="uni-badge" @click="onClick()">{{displayValue}}</text>
</view>
</template>
<script>
/**
* Badge 数字角标
* @description 数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景
* @tutorial https://ext.dcloud.net.cn/plugin?id=21
* @property {String} text 角标内容
* @property {String} size = [normal|small] 角标内容
* @property {String} type = [info|primary|success|warning|error] 颜色类型
* @value info 灰色
* @value primary 蓝色
* @value success 绿色
* @value warning 黄色
* @value error 红色
* @property {String} inverted = [true|false] 是否无需背景颜色
* @property {Number} maxNum 展示封顶的数字值,超过 99 显示 99+
* @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] 开启绝对定位, 角标将定位到其包裹的标签的四角上
* @value rightTop 右上
* @value rightBottom 右下
* @value leftTop 左上
* @value leftBottom 左下
* @property {Array[number]} offset 距定位角中心点的偏移量,只有存在 absolute 属性时有效,例如:[-10, -10] 表示向外偏移 10px,[10, 10] 表示向 absolute 指定的内偏移 10px
* @property {String} isDot = [true|false] 是否显示为一个小点
* @event {Function} click 点击 Badge 触发事件
* @example <uni-badge text="1"></uni-badge>
*/
export default {
name: 'UniBadge',
emits: ['click'],
props: {
type: {
type: String,
default: 'error'
},
inverted: {
type: Boolean,
default: false
},
isDot: {
type: Boolean,
default: false
},
maxNum: {
type: Number,
default: 99
},
absolute: {
type: String,
default: ''
},
offset: {
type: Array,
default () {
return [0, 0]
}
},
text: {
type: [String, Number],
default: ''
},
size: {
type: String,
default: 'small'
},
customStyle: {
type: Object,
default () {
return {}
}
}
},
data() {
return {};
},
computed: {
width() {
return String(this.text).length * 8 + 12
},
classNames() {
const {
inverted,
type,
size,
absolute
} = this
return [
inverted ? 'uni-badge--' + type + '-inverted' : '',
'uni-badge--' + type,
'uni-badge--' + size,
absolute ? 'uni-badge--absolute' : ''
].join(' ')
},
positionStyle() {
if (!this.absolute) return {}
let w = this.width / 2,
h = 10
if (this.isDot) {
w = 5
h = 5
}
const x = `${- w + this.offset[0]}px`
const y = `${- h + this.offset[1]}px`
const whiteList = {
rightTop: {
right: x,
top: y
},
rightBottom: {
right: x,
bottom: y
},
leftBottom: {
left: x,
bottom: y
},
leftTop: {
left: x,
top: y
}
}
const match = whiteList[this.absolute]
return match ? match : whiteList['rightTop']
},
badgeWidth() {
return {
width: `${this.width}px`
}
},
dotStyle() {
if (!this.isDot) return {}
return {
width: '10px',
height: '10px',
borderRadius: '10px'
}
},
displayValue() {
const {
isDot,
text,
maxNum
} = this
return isDot ? '' : (Number(text) > maxNum ? `${maxNum}+` : text)
}
},
methods: {
onClick() {
this.$emit('click');
}
}
};
</script>
<style lang="scss" scoped>
$uni-primary: #2979ff !default;
$uni-success: #4cd964 !default;
$uni-warning: #f0ad4e !default;
$uni-error: #dd524d !default;
$uni-info: #909399 !default;
$bage-size: 12px;
$bage-small: scale(0.8);
.uni-badge--x {
/* #ifdef APP-NVUE */
// align-self: flex-start;
/* #endif */
/* #ifndef APP-NVUE */
display: inline-block;
/* #endif */
position: relative;
}
.uni-badge--absolute {
position: absolute;
}
.uni-badge--small {
transform: $bage-small;
transform-origin: center center;
}
.uni-badge {
/* #ifndef APP-NVUE */
display: flex;
overflow: hidden;
box-sizing: border-box;
/* #endif */
justify-content: center;
flex-direction: row;
height: 20px;
line-height: 18px;
color: #fff;
border-radius: 100px;
background-color: $uni-info;
background-color: transparent;
border: 1px solid #fff;
text-align: center;
font-family: 'Helvetica Neue', Helvetica, sans-serif;
font-size: $bage-size;
/* #ifdef H5 */
z-index: 999;
cursor: pointer;
/* #endif */
&--info {
color: #fff;
background-color: $uni-info;
}
&--primary {
background-color: $uni-primary;
}
&--success {
background-color: $uni-success;
}
&--warning {
background-color: $uni-warning;
}
&--error {
background-color: $uni-error;
}
&--inverted {
padding: 0 5px 0 0;
color: $uni-info;
}
&--info-inverted {
color: $uni-info;
background-color: transparent;
}
&--primary-inverted {
color: $uni-primary;
background-color: transparent;
}
&--success-inverted {
color: $uni-success;
background-color: transparent;
}
&--warning-inverted {
color: $uni-warning;
background-color: transparent;
}
&--error-inverted {
color: $uni-error;
background-color: transparent;
}
}
</style>
{
"id": "uni-badge",
"displayName": "uni-badge 数字角标",
"version": "1.2.0",
"description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。",
"keywords": [
"",
"badge",
"uni-ui",
"uniui",
"数字角标",
"徽章"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": ""
},
"directories": {
"example": "../../temps/example_temps"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "y",
"联盟": "y"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}
\ No newline at end of file
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!