项目初始化

This commit is contained in:
mac·ufutx 2026-04-02 18:12:53 +08:00
commit 42bb0e2995
235 changed files with 81416 additions and 0 deletions

2
.browserslistrc Normal file
View File

@ -0,0 +1,2 @@
> 1%
last 2 versions

14
.editorconfig Normal file
View File

@ -0,0 +1,14 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false

4
.env.development Normal file
View File

@ -0,0 +1,4 @@
NODE_ENV='development'
# must start with VUE_APP_
VUE_APP_ENV = 'development'

4
.env.production Normal file
View File

@ -0,0 +1,4 @@
NODE_ENV='production'
# must start with VUE_APP_
VUE_APP_ENV = 'production'

4
.env.staging Normal file
View File

@ -0,0 +1,4 @@
NODE_ENV='production'
# must start with VUE_APP_
VUE_APP_ENV = 'staging'

5
.eslintignore Normal file
View File

@ -0,0 +1,5 @@
build/*.js
src/assets
src/config
public
dist

261
.eslintrc.js Normal file
View File

@ -0,0 +1,261 @@
module.exports = {
root: true,
env: {
node: true
},
extends: ['plugin:vue/essential', 'eslint:recommended'],
parserOptions: {
parser: 'babel-eslint'
},
rules: {
'vue/max-attributes-per-line': [
2,
{
singleline: 10,
multiline: {
max: 1,
allowFirstLine: false
}
}
],
'vue/singleline-html-element-content-newline': 'off',
'vue/multiline-html-element-content-newline': 'off',
'vue/name-property-casing': ['error', 'PascalCase'],
'vue/no-v-html': 'off',
'accessor-pairs': 2,
'arrow-spacing': [
2,
{
before: true,
after: true
}
],
'block-spacing': [2, 'always'],
'brace-style': [
2,
'1tbs',
{
allowSingleLine: true
}
],
camelcase: [
0,
{
properties: 'always'
}
],
'comma-dangle': [2, 'never'],
'comma-spacing': [
2,
{
before: false,
after: true
}
],
'comma-style': [2, 'last'],
'constructor-super': 2,
curly: [2, 'multi-line'],
'dot-location': [2, 'property'],
'eol-last': 2,
eqeqeq: ['error', 'always', { null: 'ignore' }],
'generator-star-spacing': [
2,
{
before: true,
after: true
}
],
'handle-callback-err': [2, '^(err|error)$'],
indent: [
2,
2,
{
SwitchCase: 1
}
],
'jsx-quotes': [2, 'prefer-single'],
'key-spacing': [
2,
{
beforeColon: false,
afterColon: true
}
],
'keyword-spacing': [
2,
{
before: true,
after: true
}
],
'new-cap': [
2,
{
newIsCap: true,
capIsNew: false
}
],
'new-parens': 2,
'no-array-constructor': 2,
'no-caller': 2,
'no-console': 'off',
'no-class-assign': 2,
'no-cond-assign': 2,
'no-const-assign': 2,
'no-control-regex': 0,
'no-delete-var': 2,
'no-dupe-args': 2,
'no-dupe-class-members': 2,
'no-dupe-keys': 2,
'no-duplicate-case': 2,
'no-empty-character-class': 2,
'no-empty-pattern': 2,
'no-eval': 2,
'no-ex-assign': 2,
'no-extend-native': 2,
'no-extra-bind': 2,
'no-extra-boolean-cast': 2,
'no-extra-parens': [2, 'functions'],
'no-fallthrough': 2,
'no-floating-decimal': 2,
'no-func-assign': 2,
'no-implied-eval': 2,
'no-inner-declarations': [2, 'functions'],
'no-invalid-regexp': 2,
'no-irregular-whitespace': 2,
'no-iterator': 2,
'no-label-var': 2,
'no-labels': [
2,
{
allowLoop: false,
allowSwitch: false
}
],
'no-lone-blocks': 2,
'no-mixed-spaces-and-tabs': 2,
'no-multi-spaces': 2,
'no-multi-str': 2,
'no-multiple-empty-lines': [
2,
{
max: 1
}
],
'no-native-reassign': 2,
'no-negated-in-lhs': 2,
'no-new-object': 2,
'no-new-require': 2,
'no-new-symbol': 2,
'no-new-wrappers': 2,
'no-obj-calls': 2,
'no-octal': 2,
'no-octal-escape': 2,
'no-path-concat': 2,
'no-proto': 2,
'no-redeclare': 2,
'no-regex-spaces': 2,
'no-return-assign': [2, 'except-parens'],
'no-self-assign': 2,
'no-self-compare': 2,
'no-sequences': 2,
'no-shadow-restricted-names': 2,
'no-spaced-func': 2,
'no-sparse-arrays': 2,
'no-this-before-super': 2,
'no-throw-literal': 2,
'no-trailing-spaces': 2,
'no-undef': 2,
'no-undef-init': 2,
'no-unexpected-multiline': 2,
'no-unmodified-loop-condition': 2,
'no-unneeded-ternary': [
2,
{
defaultAssignment: false
}
],
'no-unreachable': 2,
'no-unsafe-finally': 2,
'no-unused-vars': [
2,
{
vars: 'all',
args: 'none'
}
],
'no-useless-call': 2,
'no-useless-computed-key': 2,
'no-useless-constructor': 2,
'no-useless-escape': 0,
'no-whitespace-before-property': 2,
'no-with': 2,
'one-var': [
2,
{
initialized: 'never'
}
],
'operator-linebreak': [
2,
'after',
{
overrides: {
'?': 'before',
':': 'before'
}
}
],
'padded-blocks': [2, 'never'],
quotes: [
2,
'single',
{
avoidEscape: true,
allowTemplateLiterals: true
}
],
semi: [2, 'never'],
'semi-spacing': [
2,
{
before: false,
after: true
}
],
'space-before-blocks': [2, 'always'],
'space-before-function-paren': [2, 'never'],
'space-in-parens': [2, 'never'],
'space-infix-ops': 2,
'space-unary-ops': [
2,
{
words: true,
nonwords: false
}
],
'spaced-comment': [
2,
'always',
{
markers: ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
}
],
'template-curly-spacing': [2, 'never'],
'use-isnan': 2,
'valid-typeof': 2,
'wrap-iife': [2, 'any'],
'yield-star-spacing': [2, 'both'],
yoda: [2, 'never'],
'prefer-const': 2,
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'object-curly-spacing': [
2,
'always',
{
objectsInObjects: false
}
],
'array-bracket-spacing': [2, 'never']
}
}

27
.github/ISSUE_TEMPLATE/----bug.md vendored Normal file
View File

@ -0,0 +1,27 @@
---
name: 为项目提BUG
about: 为该项目一个BUG
title: ''
labels: bug
assignees: ''
---
你好,请使用下面的模板创建 issue 以帮助我们更快的排查问题,不规范的 issue 会被关闭,感谢配合。
Browser version [浏览器类型和版本]
vue-h5-template version [vue-h5-template 版本]
Vue version [Vue 版本]
reappear link [重现链接]
One-line summary [描述问题]
Other comments [其他信息]

11
.github/ISSUE_TEMPLATE/custom.md vendored Normal file
View File

@ -0,0 +1,11 @@
---
name: 其他问题
about: 为项目提出宝贵意见
title: ''
labels: ''
assignees: ''
---
您好,非常感谢对本项目的支持,您可以在此留下你的宝贵意见和想法。
也可以添加作者微信sunnie_song ,学习交流ლ(°◕‵ƹ′◕ლ)。

25
.gitignore vendored Normal file
View File

@ -0,0 +1,25 @@
.DS_Store
node_modules
/dist
/release
/docs
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
package-lock.json
yarn.lock

13
.postcssrc.js Normal file
View File

@ -0,0 +1,13 @@
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
plugins: {
// autoprefixer: {
// overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 8']
// },
'postcss-pxtorem': {
rootValue: 37.5,
propList: ['*'],
//selectorBlackList: ['van-']
}
}
}

24
.prettierrc Normal file
View File

@ -0,0 +1,24 @@
{
"printWidth": 120,
"tabWidth": 2,
"singleQuote": true,
"trailingComma": "none",
"semi": false,
"wrap_line_length": 120,
"wrap_attributes": "auto",
"proseWrap": "always",
"arrowParens": "avoid",
"bracketSpacing": true,
"jsxBracketSameLine": true,
"useTabs": false,
"eslintIntegration":true,
"overrides": [
{
"files": ".prettierrc",
"options": {
"parser": "json"
}
}
],
"endOfLine": "auto"
}

45
README.en.md Normal file
View File

@ -0,0 +1,45 @@
# vue-h5-template
基于vue-cli3.0+webpack 4+vant ui + sass+ rem适配方案+axios封装构建手机端模板脚手架
#### 介绍
[关于项目介绍](https://segmentfault.com/a/1190000019275330)
1. vuecli3.0
2. 多环境开发
3. axios封装
4. rem适配方案
5. 生产环境cdn优化首屏加速
6. babel低版本浏览器兼容
7. 环境发布脚本
#### 多环境
之前写过一个多环境的方案是基于vue-cli2.0的 [vue多环境配置方案-传送门](https://segmentfault.com/a/1190000019136606)
最近新的项目采用了vuecli3.0开始了一番折腾
这里参考了[vue-admin-template](https://github.com/PanJiaChen/vue-admin-template) 基本思路不变
在src的文件里新建config 根据不同的环境去引用不同的配置文件,不同的是在根目录下有三个设置环境变量的文件
这里可以参考vue-admin-template
#### rem适配方案
还是那句话用vw还是用rem这是个问题
选用rem的原因是因为vant直接给到了这个适配方案个人也比较喜欢这个方案
[vant](https://youzan.github.io/vant/#/zh-CN/quickstart)
#### 总结
因为项目刚刚构建起来,后面还会持续更新,实际使用过程中一定还有很多问题,如果文章中有错误希望能够被指正,一起成长
# 关于我
您可以扫描添加下方的微信并备注 Soul 加交流群,给我提意见,交流学习。
<p>
<img src="https://tweapp.top1buyer.com/mine.jpg" width="256" style="display:inline;">
</p>
如果对你有帮助送我一颗小星星づ ̄3 ̄づ╭❤

1153
README.md Normal file

File diff suppressed because it is too large Load Diff

22
babel.config.js Normal file
View File

@ -0,0 +1,22 @@
// 获取 VUE_APP_ENV 非 NODE_ENV测试环境依然 console
const IS_PROD = ['production', 'prod'].includes(process.env.VUE_APP_ENV)
const plugins = [
[
'import',
{
libraryName: 'vant',
libraryDirectory: 'es',
style: true
},
'vant'
]
]
// 去除 console.log
if (IS_PROD) {
// plugins.push('transform-remove-console')
}
module.exports = {
presets: [['@vue/cli-plugin-babel/preset', { useBuiltIns: 'usage', corejs: 3 }]],
plugins
}

60
package.json Normal file
View File

@ -0,0 +1,60 @@
{
"name": "vue-h5-template",
"version": "2.1.0",
"description": "A vue h5 template with Vant UI",
"author": "Zeng <web260320689@163.com>",
"private": true,
"scripts": {
"dev": "vue-cli-service serve --host 0.0.0.0",
"serve": "vue-cli-service serve --host 0.0.0.0",
"build": "vue-cli-service build",
"stage": "vue-cli-service build --mode staging",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.19.2",
"clipboard": "^2.0.8",
"core-js": "^3.6.4",
"echarts": "^4.9.0",
"hard-source-webpack-plugin": "^0.13.1",
"js-md5": "^0.7.3",
"lib-flexible": "^0.3.2",
"lodash": "^4.17.15",
"mescroll.js": "^1.4.2",
"regenerator-runtime": "^0.13.5",
"sass": "^1.49.0",
"sass-loader": "^8.0.2",
"vant": "^2.10.2",
"vcolorpicker": "^1.1.0",
"vue": "^2.6.11",
"vue-aliplayer-v2": "^1.3.0",
"vue-amap": "^0.5.10",
"vue-awesome-swiper": "^3.1.3",
"vue-canvas-poster": "^1.2.1",
"vue-i18n": "^8.25.0",
"vue-router": "^3.0.7",
"vue-wechat-title": "^2.0.4",
"vuex": "^3.4.0",
"weixin-js-sdk": "^1.6.0"
},
"devDependencies": {
"@vant/area-data": "^1.3.1",
"@vue/cli-plugin-babel": "^4.5.15",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"babel-plugin-import": "^1.13.0",
"babel-plugin-transform-remove-console": "^6.9.4",
"compression-webpack-plugin": "^6.1.1",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"postcss-pxtorem": "^5.1.1",
"script-ext-html-webpack-plugin": "^2.1.4",
"speed-measure-webpack-plugin": "^1.5.0",
"vue-template-compiler": "^2.6.11",
"webpack": "^4.46.0",
"webpack-bundle-analyzer": "^3.8.0"
}
}

BIN
public/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

67
public/index.html Normal file
View File

@ -0,0 +1,67 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover">
<meta name="referrer" content="origin">
<!-- <meta name="referrer" content="no-referrer" />-->
<meta name="format-detection" content="telephone=yes" />
<link rel="icon" href="<%= BASE_URL %>favicon.png">
<link rel="stylesheet" href="https://images.ufutx.com/js/H5/aliplayer-min.css" />
<link rel="stylesheet" href="https://images.ufutx.com/js/H5/cropper.min.css" />
<script src="https://images.ufutx.com/js/H5/cropper.min.js" type="text/javascript"></script>
<script src="https://images.ufutx.com/js/H5/sharetrace.min.js"></script>
<script src="https://images.ufutx.com/js/H5/aliplayer-min.js"></script>
<script src="https://images.ufutx.com/js/H5/aliplayer-h5-min.js"></script>
<script src="https://images.ufutx.com/js/admin_pro/xgplayer2.31.2.js"></script>
<!-- <script src="https://unpkg.byted-static.com/xgplayer/2.31.2/browser/index.js" type="text/javascript"></script>-->
<!-- <script src="https://unpkg.byted-static.com/xgplayer-mp4/2.0.0/browser/index.js"></script>-->
<script src="https://unpkg.byted-static.com/xgplayer/3.0.1/dist/index.min.js" charset="utf-8"></script>
<script src="https://unpkg.byted-static.com/xgplayer-mp4/3.0.1/dist/index.min.js" charset="utf-8"></script>
<script src="https://player.alicdn.com/aliplayer/presentation/js/aliplayercomponents.min.js"></script>
<title><%= webpackConfig.name %></title>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-KJDJ19HG6B"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-VEFH8PB85S');
</script>
</head>
<body>
<!-- <noscript>-->
<!-- <strong>We're sorry but <%= webpackConfig.name %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>-->
<!-- </noscript>-->
<div id="app"></div>
<!-- 使用CDN加速的JS文件配置在vue.config.js下 -->
<!-- <% for (var i in
htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
<% } %> -->
<!-- built files will be auto injected -->
</body>
<script>
// (function (i, s, o, g, r, a, m) {
// i['GoogleAnalyticsObject'] = r
// i[r] = i[r] || function () {
// (i[r].q = i[r].q || []).push(arguments)
// }, i[r].l = 1 * new Date()
// a = s.createElement(o),
// m = s.getElementsByTagName(o)[0]
// a.async = 1
// a.src = g
// m.parentNode.insertBefore(a, m)
// })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga')
// // ga('create', 'UA-98664364-10', 'auto','myTracker', {
// // userId: '12345')
// // ga('create', 'UA-98664364-11', 'auto', 'myTracker', { // 创建追踪器
// // userId: '12345'
// // })
// // ga((tracker) => {
// // console.log(tracker, 'adssssssss')
// // })
// ga('create', 'UA-98664364-10', 'auto')
// ga('send', 'pageview') // 是否要统计着陆页面访问,取决于你的需求,这个不一定需要,会和`router`统计有重复
</script>
</html>

11
sh.exe.stackdump Normal file
View File

@ -0,0 +1,11 @@
Stack trace:
Frame Function Args
00800000010 0018006401E (0018027DF10, 0018026EFD1, 00800000010, 000FFFFBA40)
00800000010 0018004973A (00100002000, 000FFFFCBE0, 00180353B88, 00000000001)
00800000010 00180049772 (00000000001, 00180353E98, 00800000010, 00000000008)
00800000010 0018005CDBD (000FFFFCCE0, 000FFFFCC73, 00000000000, 000FFFFCC70)
000FFFFCBEC 0018005CF1D (00000000028, 000FFFFCDF0, 00000000030, 00000000000)
000FFFFCCE0 00180049EE8 (00000000000, 00000000000, 00000000000, 00000000000)
000FFFFFFF0 00180048846 (00000000000, 00000000000, 00000000000, 00000000000)
000FFFFFFF0 001800488F4 (00000000000, 00000000000, 00000000000, 00000000000)
End of stack trace

626
src/App.vue Normal file
View File

@ -0,0 +1,626 @@
<template>
<div id="app">
<!-- <div v-wechat-title="titleName"></div> -->
<div class="app-container">
<div class="layout-content">
<keep-alive>
<router-view v-if="$route.meta.keepAlive" v-wechat-title="titleName"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive" v-wechat-title="titleName"></router-view>
</div>
<div class="layout-footer" v-show="!isTabbarDemo">
<TabBar :tabBarList="tabBarList" @change="handleChange" :toName="toName" />
</div>
</div>
</div>
</template>
<script>
import TabBar from '@/components/TabBar'
import { mapState } from 'vuex'
import service from '@/utils/request'
import { mapGetters } from 'vuex'
import wx from 'weixin-js-sdk'
export default {
computed: {
...mapGetters(['token', 'info']),
...mapState({}),
isTabbarDemo() {
if (this.$route.path === '/serve') return false
if (this.$route.path === '/activity') return false
if (this.$route.path === '/course') return false
if (this.$route.path === '/information') return false
if (this.$route.path === '/my') return false
return true
}
},
name: 'App',
components: {
TabBar
},
provide() {
return { reload: this.reload }
},
data() {
return {
toName: '',
Once_again: true,
isRouterAlive: true,
tabBarList: [],
//
customShare: [
'testV2',
'reviewResults',
'groupData',
'groupOrder',
'dynamicParticulars',
'serveDetails',
'mallDetail',
'recruitingTeacher',
'consultingDetail',
'activityDetails',
'userDetail',
'VIPDetail',
'VIPUserDetail',
'courseDetail',
'courseDetailList',
'serve',
'evaluateDetails',
'questionnaireV2',
'questionnaireV3',
'ordinaryWatchLive',
'appointmentDetail'
],
infoData: null,
returnPath: null,
returnName: null,
titleName: ''
}
},
watch: {
token(e) {
// if (location.href.includes('downloadApp') || location.href.includes('dynamicParticulars')) {
// console.log('e====')
// return
// }
if (location.href.includes('downloadApp')) {
console.log('e====')
return
}
console.log('3-=--')
this.getTemplate()
this.getInfoData()
this.getData()
this.getBusinessInfo()
},
$route(to, from) {
const isIOS = /(iPhone|iPad|iPod)/i.test(navigator.userAgent)
// 🔥 iOSwx.config
if (isIOS) {
this.getTitleName()
return
}
// if (location.href.includes('downloadApp') || location.href.includes('dynamicParticulars')) {
// return
// }
if (location.href.includes('downloadApp')) {
return
}
this.returnData = to
this.getTitleName()
console.log(to.name, 'name=== ')
if (to.name == 'PrivacyAgreement' || to.name == 'serviceAgreement' || to.name == 'platformServiceAgreement' || to.name == 'dynamicParticulars') {
return
}
console.log('222')
this.shareConfiguration()
localStorage.setItem('returnName', to.name)
if (to.params.id) {
localStorage.setItem('returnNameId', to.params.id)
}
if (to.query.anchor_openid) {
localStorage.setItem('anchor_openid', to.query.anchor_openid)
}
}
},
methods: {
reload() {
this.isRouterAlive = false
this.$nextTick(function() {
this.isRouterAlive = true
})
},
// config
// getWxConfig() {
// const vm = this
// const url = encodeURIComponent(location.href.split('#')[0])
// const parameter = { url: url }
// service
// .post(`/official/js/config`, parameter)
// .then(data => {
// console.log(data, '7897987')
// vm.$store.commit('eidtConfigData', data)
// this.shareConfiguration()
// })
// .catch(error => {
// console.log(error)
// })
// },
getWxConfig() {
const vm = this
// 👇 iOS URLAndroid URL
// const url = encodeURIComponent(
// /(iPhone|iPad|iPod)/i.test(navigator.userAgent)
// ? window.entryUrl
// : location.href.split('#')[0]
// )
// const parameter = { url: url }
const isIOS = /(iPhone|iPad|iPod)/i.test(navigator.userAgent)
// 🔥 iOS/AndroidURL
let signUrl = ''
if (isIOS) {
// iOSURL
signUrl = window.__WECHAT_FIRST_ENTRY_URL__
} else {
// AndroidURL#
const currentUrl = location.href.split('#')[0]
signUrl = currentUrl.endsWith('/') ? currentUrl : `${currentUrl}/`
}
// URL
const encodedUrl = encodeURIComponent(signUrl)
const parameter = { url: encodedUrl }
service.post(`/official/js/config`, parameter)
.then(data => {
if (!data || !data.appId) {
console.error('❌ 微信配置返回异常', data)
return
}
vm.$store.commit('eidtConfigData', data)
// 👇 config /
wx.config({
debug: false,
appId: data.appId,
timestamp: data.timestamp,
nonceStr: data.nonceStr,
signature: data.signature,
jsApiList: [
'chooseWXPay', //
'updateAppMessageShareData',
'updateTimelineShareData'
]
})
// config
wx.ready(() => {
console.log('微信 SDK 初始化成功 ✅')
vm.shareConfiguration()
})
wx.error((err) => {
console.log('微信 config 失败 ❌', err)
})
})
},
//
shareConfiguration() {
const vm = this
let urls = ''
var signOutIncludes = false
if (!this.$store.state.app.configData) {
return
}
if (!this.$store.state.app.info) {
return
}
// for (let item = 0; item < vm.customShare.length; item++) {
// if (location.href.includes(vm.customShare[item])) {
// signOutIncludes = true
// return
// }
// }
for (let item = 0; item < vm.customShare.length; item++) {
// 🔥
if (location.href.includes(vm.customShare[item]) && !location.href.includes('activityDetails')) {
signOutIncludes = true
return
}
}
if (signOutIncludes) {
return
}
if (this.$store.state.app.merchant_id) {
urls =
`${vm.$shareCallback}/api/official/live/wechat/FamilyAuth?from_openid=${localStorage.getItem(
'openid'
)}&anchor_openid=${localStorage.getItem('anchor_openid')}&merchant_id=${
this.$store.state.app.merchant_id
}&url=` + encodeURIComponent(`${vm.$shareCallback}/pu/#/`)
} else {
this.$router.replace({
name: 'missingPage'
})
}
if (localStorage.getItem('merchant_id') == 5) {
this.$shareList(
'https://image.fulllinkai.com/202111/19/fb7c79ae761012ac6bb92c7861e860c80.1551945067963747.png',
urls,
'副标题',
'标题'
)
return
}
this.$shareList(
this.$store.state.app.info.share_icon,
urls,
this.$store.state.app.info.designation,
this.$store.state.app.info.share_title
)
},
getData(to) {
const vm = this
const url = `s/h5/connect/us`
service
.get(url)
.then(data => {
if (data) {
vm.infoData = data.name
vm.getTitleName()
localStorage.setItem('openid', data.openid || '')
vm.$store.commit('eidtInfo', data)
vm.shareConfiguration()
}
localStorage.setItem('merchant_name', data.name)
localStorage.setItem('qrCode', data.qr_code)
})
.catch(error => {
console.log(error)
})
},
getInfoData() {
const url = `s/h5/business/show/info`
const show_status = []
service.get(url).then(data => {
if (data.show_service) {
this.$store.commit('eidtUserArr', data.show_service)
}
if (data.show_status && data.show_status.length !== 0) {
data.show_status.forEach((item) => {
show_status.push({ name: item, type: this.typeFn(item) })
})
this.$store.commit('eidtSortingState', false)
this.$store.commit('eidtSortingArr', show_status)
} else {
this.$store.commit('eidtSortingState', true)
}
}).catch(error => {
console.log(error)
})
},
typeFn(e) {
if (e === '活动') {
return 'activity'
} else if (e === '服务') {
return 'serve'
} else if (e === '课程') {
return 'course'
} else if (e === '咨询') {
return 'consult'
} else if (e === '测评') {
return 'evaluate'
} else if (e === '测试') {
return 'test'
} else if (e === '商城') {
return 'mall'
}
},
handleChange(v) {
console.log('tab value:', v)
},
getTemplate() {
const url = `s/h5/choosed/template?merchant_id=${localStorage.getItem(
'merchant_id'
)}&anchor_openid=${localStorage.getItem('anchor_openid')}`
service
.get(url)
.then(data => {
if (data.tabBarList && data.tabBarList.length > 0) {
this.$store.commit('editTemplate', data)
if (this.$store.state.app.template.templateType && this.$store.state.app.template.templateType.length > 0) {
this.$store.state.app.template.templateType.forEach(item => {
if (item.name == '我的') {
this.$store.commit('eidtMyPosition', item.position)
}
if (item.name == '资讯') {
this.$store.commit('eidtDsPosition', item.position)
}
if (item.name == '服务') {
this.$store.commit('eidtServePosition', item.position)
}
if (item.name == '活动') {
this.$store.commit('eidtActivityPosition', item.position)
}
if (item.name == '课程') {
this.$store.commit('eidtCoursePosition', item.position)
}
if (item.name == '咨询') {
this.$store.commit('eidtConsultPosition', item.position)
}
if (item.name === '商城') {
this.$store.commit('eidtMallPosition', item.position)
}
})
}
}
this.tabBarList = this.$store.state.app.template.tabBarList
this.getTitleName()
})
.catch(error => {
console.log(error)
})
},
getBusinessInfo() {
const url = `s/h5/BusinessUser`
service
.get(url)
.then(data => {
var userData = {
nickname: data.nickname,
avatar: data.avatar,
id: data.id,
qr_code: data.qr_code,
url: data.url
}
this.$store.commit('eidtUserData', userData)
localStorage.setItem('S_userAvatar', data.avatar)
})
.catch(error => {
console.log(error)
})
},
getTitleName() {
if (!this.infoData) {
return
}
if (!this.returnData) {
return
}
if (!this.tabBarList) {
return
} else {
if (
this.returnData.path == '/information' ||
this.returnData.path == '/serve' ||
this.returnData.path == '/my'
) {
this.tabBarList.forEach(item => {
if (item.to == this.returnData.path) {
this.titleName = item.title + '·' + this.infoData
return
}
})
} else {
this.titleName = this.$i18n.t(this.returnData.meta.title)
}
}
}
},
mounted() {
const isWechat = /micromessenger/i.test(navigator.userAgent);
const isIOS = /(iPhone|iPad|iPod)/i.test(navigator.userAgent);
if (isWechat && isIOS && location.href.indexOf("?#") === -1) {
// # ?#
location.href = location.href.replace("#", "?#");
// return; //
}
// if (!window.entryUrl) {
// window.entryUrl = location.href.split('#')[0]
// }
// 🔥 URLiOS
if (!window.__WECHAT_FIRST_ENTRY_URL__) {
const firstUrl = location.href.split('#')[0]
// /
window.__WECHAT_FIRST_ENTRY_URL__ = firstUrl.endsWith('/') ? firstUrl : `${firstUrl}/`
}
if (!window.entryUrl) {
window.entryUrl = location.href.split('#')[0]
}
// ==================== 🔥 merchant_id=40 URL ====================
if (this.$store.state.app.merchant_id == 40 || localStorage.getItem('merchant_id') == 40) {
alert(`【iOS 首次识别 URL】${window.__WECHAT_FIRST_ENTRY_URL__}`);
console.log(`【调试-测试商家40】iOS 初始识别 URL = ${window.__WECHAT_FIRST_ENTRY_URL__}`);
}
localStorage.setItem('authorize_at', '1')
console.log('3===')
// 🔥 downloadApp
if (location.href.includes('downloadApp')) {
return
}
// 🔥
this.getWxConfig()
localStorage.removeItem('first')
console.log('更新时间123', new Date())
if (
(localStorage.getItem('anchor_openid') || this.$store.state.app.merchant_id) &&
localStorage.getItem('saas_token')
) {
if (
this.$store.state.app.routerName == 'PrivacyAgreement' ||
this.$store.state.app.routerName == 'serviceAgreement' ||
this.$store.state.app.routerName == 'platformServiceAgreement'
) {
return
}
this.getBusinessInfo()
this.getData()
this.getTemplate()
this.getInfoData()
}
console.log('=====================================')
console.log('✅ 【打包编译时间】:', process.env.BUILD_TIME) //
console.log('✅ 当前页面完整URL', location.href)
console.log('✅ iOS 首次识别URL(entryUrl)', window.entryUrl) //
console.log('✅ 微信签名URL', window.__WECHAT_FIRST_ENTRY_URL__)
console.log('=====================================')
}
// mounted() {
// if (!window.entryUrl) {
// window.entryUrl = location.href.split('#')[0]
// }
//
// localStorage.setItem('authorize_at', '1')
// console.log('3===')
// if (location.href.includes('downloadApp') || location.href.includes('dynamicParticulars')) {
// return
// }
// if (this.$store.state.app.routerName == 'dynamicParticulars') {
// console.log('1234')
// return
// }
// this.getWxConfig()
// localStorage.removeItem('first')
// console.log('123', new Date())
// if (
// (localStorage.getItem('anchor_openid') || this.$store.state.app.merchant_id) &&
// localStorage.getItem('saas_token')
// ) {
// console.log(this.$store.state.app.routerName, 'this.$store.state.app.routerName')
// if (
// this.$store.state.app.routerName == 'PrivacyAgreement' ||
// this.$store.state.app.routerName == 'serviceAgreement' ||
// this.$store.state.app.routerName == 'platformServiceAgreement' ||
// this.$store.state.app.routerName == 'dynamicParticulars'
// ) {
// return
// }
// console.log(this.$store.state.app.routerName, 'this.$store.state.app.routerName')
// this.getBusinessInfo()
// this.getData()
// this.getTemplate()
// this.getInfoData()
// }
// }
}
</script>
<style lang="scss">
@import '../src/assets/style/reset';
.app-container{
//max-width: 480px;
}
#app {
width: 100vw;
height: 100%;
//overflow-y: scroll;
}
//html{
// height: 100%;
// width: 100%;
// //overflow: hidden;
// font-size: 14px;
//}
//body{
// width: 100%;
// height: 100%;
// overflow-y: scroll;
// background: #fff;
// font-size: 14px;
//}
html,
body {
width: 100%;
height: 100%;
//overflow: scroll;
}
html::-webkit-scrollbar,
body::-webkit-scrollbar {
width: 0;
height: 0;
}
body {
margin: 0;
font-size: 14px;
}
::-webkit-scrollbar {
width: 0;
height: 0;
display: none;
background-color: #fff;
}
::-webkit-scrollbar-track {
background-color: #fff;
}
::-webkit-scrollbar-thumb {
background-color: #fff;
}
// .prism-big-play-btn {
// width: initial !important;
// height: initial !important;
// position: initial !important;
// display: initial !important;
// }
.prism-big-play-btn {
position: absolute !important;
left: 0 !important;
bottom: 0 !important;
top: 0 !important;
right: 0 !important;
margin: auto !important;
width: 45px !important;
height: 45px !important;
background: url('https://images.ufutx.com/202101/29/fef68b642b5954d015f6d2740864e75d.png') !important;
background-size: contain !important;
display: block;
}
.outter {
width: initial !important;
height: initial !important;
border: initial !important;
}
.van-swipe__indicator {
background: #ffffff !important;
opacity: 0.59 !important;
}
.van-swipe__indicator--active {
opacity: 1 !important;
width: 10px !important;
border-radius: 4px !important;
}
.van-list__finished-text {
background: #fff !important;
}
.van-toast {
top: 42% !important;
z-index: 200000002 !important;
}
.van-dialog {
z-index: 100000001 !important;
}
.van-popup {
top: 42% !important;
border-radius: 12px !important;
overflow-y: initial !important;
z-index: 100000001 !important;
}
.van-picker {
border-radius: 12px !important;
}
.van-overlay {
z-index: 100000001 !important;
}
.van-image-preview{
z-index: 100000002 !important;
}
.inexa {
z-index: 200000002 !important;
}
</style>
<style>
/*section{*/
/*width: initial!important;*/
/*}*/
</style>

5
src/api/home.js Normal file
View File

@ -0,0 +1,5 @@
// import qs from 'qs'
// axios
// import request from '@/utils/request'
// home api

7
src/api/index.js Normal file
View File

@ -0,0 +1,7 @@
const api = {
Login: '/user/login',
UserInfo: '/user/userinfo',
UserName: '/user/name'
}
export default api

32
src/api/user.js Normal file
View File

@ -0,0 +1,32 @@
import api from './index'
// axios
import request from '@/utils/request'
// 登录
export function login(data) {
return request({
url: api.Login,
method: 'post',
data
})
}
// 用户信息 post 方法
export function getUserInfo(data) {
return request({
url: api.UserInfo,
method: 'post',
data,
hideloading: true
})
}
// 用户名称 get 方法
export function getUserName(params) {
return request({
url: api.UserName,
method: 'get',
params,
hideloading: true
})
}

13
src/assets/css/index.scss Normal file
View File

@ -0,0 +1,13 @@
@import './variables.scss';
@import './mixin.scss';
html,
body .app {
color: #333333;
font-family: Arial, Helvetica, 'STHeiti STXihei', 'Microsoft YaHei', Tohoma, sans-serif;
background-color: $background-color;
}
.app-container {
//padding-bottom: 50px;
}

36
src/assets/css/mixin.scss Normal file
View File

@ -0,0 +1,36 @@
// mixin
// 清除浮动
@mixin clearfix {
&:after {
content: "";
display: table;
clear: both;
}
}
// 多行隐藏
@mixin textoverflow($clamp:1) {
display: block;
overflow: hidden;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: $clamp;
/*! autoprefixer: ignore next */
-webkit-box-orient: vertical;
}
//flex box
@mixin flexbox($jc:space-between, $ai:center, $fd:row, $fw:nowrap) {
display: flex;
display: -webkit-flex;
flex: 1;
justify-content: $jc;
-webkit-justify-content: $jc;
align-items: $ai;
-webkit-align-items: $ai;
flex-direction: $fd;
-webkit-flex-direction: $fd;
flex-wrap: $fw;
-webkit-flex-wrap: $fw;
}

View File

@ -0,0 +1,3 @@
// variables
$background-color: #f8f8f8;

301
src/assets/i18n/zh-CN.json Normal file
View File

@ -0,0 +1,301 @@
{
"About_us": "关于我们",
"Already_bought": "已购买",
"Apply_here": "戳此报名",
"At_least_upload": "至少上传一张图片",
"Buy_now": "立即购买",
"Sign_up_now": "立即报名",
"Buy": "立即",
"specification": "规格",
"Buy_success": "购买成功后,即可加入学习",
"Can_watch": "可观看",
"Cancel_payment": "取消支付",
"Class_time": "课时",
"Confirm_payment": "确认支付",
"Contact_us": "联系我们",
"Course_introduce": "课程介绍",
"Did_not_get": "未获取",
"Did_not_learn": "你上节课还没学习,快去观看视频学习吧~",
"Full_Link_Ai": "福恋智能",
"Get_again": "重新获取",
"Have_evaluation": "您已经评价过该课程啦",
"I_have_a_line_in_the_sand": "我也是有底线的",
"In_the_authentication": "认证中...",
"In_the_land": "登陆中...",
"Know_the": "知道了",
"Language_Settings": "语言设置",
"Modify_homework": "修改作业",
"My_service": "我的服务",
"My_activities": "我的活动",
"My_course": "我的课程",
"My_homework": "我的作业",
"My_registration": "我的报名",
"my_Platform": "我的平台",
"My_order": "我的订单",
"Network_anomalies": "网络异常,请重试",
"No_evaluation": "暂未评价",
"No_less_than": "心得不少于5个字",
"No_more_than": "图片大小不能超过 5M",
"No_one_has_posted_it_yet": "还没有人发布",
"No_phone_number": "无手机号码",
"Not_taking_the_course": "你还没学习该课程,无法上传作业, 快去观看视频学习吧~",
"Not_to_buy": "你还未购买课程,购买成功后, 即可观看学习",
"Pay_success": "支付成功",
"Please_enter_the_verification_code": "请输入验证码",
"Please_enter_your_mobile_phone_number": "请输入手机号码",
"Please_read": "请阅读并同意",
"Please_read_and_agree_to_the_agreement": "请阅读并同意协议",
"Please_use_this_phone_number_to_log_in": "请使用该手机号登录",
"Privacy_agreement": "隐私政策",
"Purchase_course": "购买课程",
"Say_something": "说点什么吧...",
"Seconds_again": "秒后重试",
"Send_a_success": "发送成功",
"Service_agreement": "服务协议",
"Sign_up": "人报名",
"Submit_a_job": "你的课作业已全部提交,所有课程可回放,温故而知新哦~",
"Submitted_successfully": "提交成功",
"System_checking_login_please_wait": "系统检测登录中,请稍等...",
"Talk_about_the_lessons": "说说你的课程心得,至少五个字",
"Temporarily_no_activity": "暂无活动",
"Temporarily_no_service": "暂无服务",
"Temporarily_no_course": "暂无课程",
"Temporarily_no_consulting": "暂无咨询",
"Temporarily_no_data": "暂无数据",
"The_dean_spoke": "教务主任发话了",
"The_first": "第",
"The_loss_of": "对不起,你访问的页面走失了",
"The_student": "嘿,这位童鞋",
"The_wechat_has_been_bound": "该微信已绑定",
"To_learn": "去学习",
"Unsubmitted_job": "你还有上一课的作业未提交,完成即可观看此课程哦~",
"Upload_homework": "上传作业",
"Warm_prompt": "温馨提示",
"Wrong_mobile_phone_number": "手机号码错误",
"You_submit": "提交失败",
"activity": "活动",
"activity_Details": "活动详情",
"serve_Details": "服务详情",
"and": "与",
"browse": "浏览",
"cancel": "取消",
"cell_Number": "手机号:",
"class": "课",
"code_Tips": "请输入验证码",
"comments": "评论",
"contacts": "联系人:",
"course_Details": "课程详情",
"course_Members": "课程成员",
"course_Posters": "课程分享",
"determine": "确定",
"directory": "课程目录",
"directory_Details": "目录详情",
"empty": "无",
"free": "免费",
"get_code": "获取验证码",
"hello": "你好",
"hi": "你好",
"homework": "交作业",
"homework_Details": "作业详情",
"identify_Qr_code": "长按识别二维码",
"in_upload": "上传中...",
"in_watch": "正观看",
"introduce": "课程介绍",
"iphone_Tips": "请输入手机号",
"join_learning": "加入学习",
"language": "语言设置",
"limit_upload": "上传图片只能是 jpg、jpeg、png 格式",
"loading_text": "加载中...",
"login": "登录",
"loosing_text": "释放即可刷新...",
"minutes": "分钟",
"my": "我的",
"name_Tips": "请输入您的姓名",
"people": "人",
"personal": "个人中心",
"play_back": "可回放",
"playback": "回放课程",
"preferential": "限时优惠",
"purchase_success": "购买成功",
"pv": "浏览量",
"review": "课程心得",
"send": "发送",
"service": "服务",
"share": "分享",
"these_are_great_shoes": "嘿,这位童鞋很棒哦",
"tips_Detail": "心得详情",
"welcome": "欢迎来到福恋",
"Choice_of_translation_language": "请任意选择以下语言翻译",
"home": "首页",
"paySuccessful": "订单成功",
"Please_select_a": "请选择",
"The_number_of_languages_you_need": "您所需的语言种类",
"Multiple_language_functions_full_Link_heart_service_you": "多种语言功能,福恋用心服务您",
"more": "更多",
"Full_Link_intelligent_to_provide_technical_service_support": "福恋智能提供技术服务支持",
"Activity_group_chat": "活动群聊",
"dynamic": "资讯",
"dynamic_Particulars": "文章详情",
"dynamic_Classification": "文章分类",
"association": "社群",
"serve": "服务",
"information": "资讯",
"course": "课程",
"Join_learning": "加入学习",
"registered": "已报名",
"registration_success": "报名成功",
"Verification_code_login": "验证码登录",
"Unregistered_mobile_phone_numbers_will_be_automatically_registered_after_verification": "未注册的手机号验证通过后将自动注册",
"By_logging_in_You_agree": "登录即代表您已同意",
"my_recommend": "我的收益",
"recruiting_teacher": "商家入驻",
"rule": "规则",
"Recommended_number": "受邀人数",
"Revenue_amount": "收益金额",
"team_user": "团队成员",
"To_withdraw_cash": "去提现",
"Recommended_records": "推荐记录",
"Recommended_records_tips": "推荐用户或推荐项目促成消费才有收益喔",
"No_record": "暂无记录",
"Invite_friends_Earn_income": "推荐给好友赚收益",
"The_earned_income_can_be_withdrawn": "贏取的收益可提現",
"Recommend_to_friends": "推荐给朋友",
"Profit_three_strategies": "收益三大攻略",
"Profit_three_strategies_one": "邀请好友注册成功,并推荐服务项目促成交易,即可收益",
"Profit_three_strategies_two": "成功邀请的用户,在其他人的推荐产生消费,也可收益",
"Profit_three_strategies_three": "推荐其他用户成功消费,即可收益",
"Income_withdrawal": "收益提现",
"Withdrawal_record": "提现记录",
"unit": "元",
"Switch_account": "切换帐号",
"cash_withdrawal_amount": "提现金额",
"withdrawal_placeholder": "最低可提现1.00元",
"All_withdrawal": "全部提现",
"withdrawal_tips": "每次手续费收取",
"withdraw_deposit": "提现",
"consult": "咨询",
"mall": "商城",
"Voice_consultation": "语音咨询",
"consulting_Detail": "咨询详情",
"buy_Consulting": "购买服务",
"consultation_In": "咨询预约成功",
"evaluation": "评价咨询师",
"serveEvaluation": "评价详情",
"Consultation_confirmation": "咨询确认",
"Consulting_teacher": "咨询师",
"Consultation_mode": "咨询方式",
"My_message": "我的信息",
"My_name": "我的名字",
"My_phone": "我的电话",
"Consultation_description": "咨询描述",
"The_question_you_want_to_ask": "你想咨询的问题",
"problem_describe": "请尽量描述您要咨询的问题,以便咨询师提前准备",
"What_do_you_expect_to_gain_from_this_communication": "本次沟通你期望收获什么",
"I_have_read_and_agree": "我已阅读并同意",
"Consultation_Information": "辅导知情书",
"The_contents_of_the": "中的内容",
"consulting_fee": "咨询费",
"To_pay_for": "去支付",
"informed_consent": "知情同意书",
"informed_consent_one": "作为客户,我明白并同意为我在咨询电话中的任何行为负责,包括生理、心理、精神、情感方面,以及我的任何选择和决定。我清楚知道我可以在任何时候终止接受咨询服务。",
"informed_consent_two": "我明白“婚姻关系咨询”是一种我与咨询师之间的专业客户关系,用于帮助建立/发展个人经营婚姻能力,探寻跨越婚姻障碍的方法,找到关系修复的途径,拓展情感关系视角。",
"informed_consent_three": "我明白咨询的过程包含我婚姻中的方方面面:工作、财务、健康、人际关系、教育及娱乐。我承诺我为如何处理这些事务,并在这些领域的决定以及为我的选择和行为承担全部责任。",
"informed_consent_four": "我明白咨询不包括“精神病治疗协会”定义的诊断、或是精神失常的治疗。我了解婚姻关系咨询不是精神疗法、心理分析、精神健康保健的替代品,我不会将之用于任何形式的诊断与治疗中。",
"informed_consent_five": "我承诺如果我正接受治疗或是精神辅导我将先咨询精神辅导医生我是否适合接受婚姻关系咨询服务,如果我决定接受咨询服务,一定让医生知道。",
"informed_consent_six": "我明白我的资料是保密的,除非我授权公开或是法律要求。",
"informed_consent_seven": "我明白基于研讨和咨询的目的,一些议题可能通过使用化名或是以假设的方法在其它的案例拿来分享。",
"informed_consent_eight": "我明白婚姻关系咨询不是代替法律、医学、金融、商业、精神或是其它专业人士的。我会向法律、医学、金融、商业、精神或是其它专业人士寻求专业指导。我明白并承诺为自己的决定和行为承担一切后果。",
"Please_enter_a_name": "请输入你的名字",
"The_teacher_introduced": "老师介绍",
"experience": "资历经验",
"No_title": "无职称",
"conceal": "收起",
"view_more": "查看更多",
"unfold": "展开",
"entire_period_of_actual_operation": "从业年限",
"Consulting_people": "咨询人次",
"degree_of_praise": "好评度",
"second": "次",
"minute": "分钟",
"evaluate": "评价",
"relation": "联系咨询师",
"Contact_the_teacher": "联系老师",
"Call_your_teacher": "联系老师,请拨打",
"consulting": "咨询",
"make_an_appointment": "预约",
"Video_consultation": "视频咨询",
"my_Customer": "我的客户",
"customer_Detail": "客户详情",
"See_the_evaluation": "查看评价",
"click_on_the_button": "点击按钮",
"Remaining_talk_time": "剩余通话时间",
"End_of_the_order": "结束订单",
"Confirm_the_termination_of_the_order": "是否确认结束订单",
"affirm": "确认",
"Temporary_does_not_support": "暂不支持",
"Offline_consulting": "线下咨询",
"homepage": "主页",
"contact": "联系",
"customer_evaluation": "客户评价",
"Consultation_time": "咨询时间",
"surplus": "剩余",
"Consult_state": "咨询状态",
"order_time": "下单时间",
"Ask_questions": "咨询问题",
"Expect_to_harvest": "期望收获",
"search_record": "咨询记录",
"good_reputation": "好评",
"submit": "提交",
"Evaluate_the_consultant": "评价咨询师吧",
"Evaluate_text": "评价内容",
"Evaluate_star": "评分",
"ordinary_watch_live": "直播间",
"End_of_live_broadcast": "直播结束",
"watch_live": "直播",
"service_content": "服务内容",
"detailBtn": "详情",
"questionnaire": "问卷",
"shopping_mall": "商城",
"store_order_detail": "商城订单详情",
"test": "测试",
"discuss_personally": "面议",
"my_test": "我的测试",
"evaluateBtn": "评价",
"totalPrice": "总价",
"address": "地址",
"Get_the_shipping_address": "获取收货地址",
"number": "数量",
"view_the_order": "查看订单",
"Qualification_certificate": "资历证明",
"please_confirm_receipt_of_goods_upon_receipt": "支付完成,请在收到商品之后确认收货",
"Like_the_author_praise_and_support_it": "喜欢作者,赞赏支持一下吧",
"appreciates": "赞赏作者",
"custom": "自定义",
"people_appreciates": "人赞赏",
"What_would_you_like_to_say_to_the_author": "有什么想对作者说的?",
"Leave_a_message_to_the_author_and_encourage_the_author": "给作者留言,鼓励下作者吧",
"Deadline_for_registration": "截止报名",
"End_of_the_activity": "活动已结束",
"Video_details": "视频详情",
"place_order": "提交订单",
"full_name": "姓 名",
"full_name_Tips": "请输入您的真实姓名",
"ID_card": "身份证",
"ID_card_Tips": "请输入您的身份证号",
"appreciates_successful": "赞赏成功",
"service_has_been_removed": "该服务已删除",
"activity_has_been_removed": "该活动已删除",
"consult_has_been_removed": "该咨询已删除",
"course_has_been_removed": "该课程已删除",
"mall_has_been_removed": "该商品已删除",
"article_has_been_removed": "该文章已删除",
"test_has_been_removed": "该测试已删除",
"video_has_been_removed": "该视频已删除",
"service_already_taken_down": "服务已下架",
"activity_already_taken_down": "活动已下架",
"consult_already_taken_down": "咨询已下架",
"course_already_taken_down": "课程已下架",
"mall_already_taken_down": "商品已下架",
"already_close": "已下架",
"my_evaluate": "我的测评"
}

BIN
src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

1
src/assets/neplayer.min.css vendored Normal file

File diff suppressed because one or more lines are too long

223
src/assets/style/reset.scss Normal file
View File

@ -0,0 +1,223 @@
* {margin: 0;padding: 0;}
* { -webkit-overflow-scrolling: touch; }
.bold{font-weight: bold}
.font30 {font-size: 30px;}
.font29 {font-size: 29px;}
.font28 {font-size: 28px;}
.font27 {font-size: 27px;}
.font26 {font-size: 26px;}
.font25 {font-size: 25px;}
.font24 {font-size: 24px;}
.font22 {font-size: 22px;}
.font21 {font-size: 21px;}
.font20 {font-size: 20px;}
.font19 {font-size: 19px;}
.font18 {font-size: 18px;}
.font17 {font-size: 17px;}
.font16 {font-size: 16px;}
.font15 {font-size: 15px;}
.font14 {font-size: 14px;}
.font13 {font-size: 13px;}
.font12 {font-size: 12px;}
.font11 {font-size: 11px;}
.font10 {font-size: 10px;}
.font9 {font-size: 9px;}
.font8 {font-size: 8px;}
.colorb{color: #bbbbbb}
.colorb0{color: #b0b0b0}
.color9{color: #999999}
.color6{color: #666666}
.color3{color: #333333}
.colorbe{color: #bebebe}
.colorff{color: #ffffff}
.colorc2{color: #c2c2c2}
.color2a{color: #2A2A2A}
.colorTheme {color: #707FFA;} // 字体主题色
.ff{background: #ffffff!important;}
.bcTheme {background: #707FFA!important;} // 背景主题色
.flo_l{float: left}
.flo_r{float: right}
.clearfloat{clear:both}
.inline-block {display: inline-block}
.text-right{text-align: right}
.text-center{text-align: center}
.text-left{text-align: left}
.narrow{transform: scale(0.5)}
.vertical{
display: flex;
align-items: center;
justify-content: center;
}
.vertical_1{
display: flex;
align-items: center;
}
.alignment{
display: flex;
justify-content: space-between;
align-items: center;
}
.alignment_left{
display: flex;
justify-content: left;
align-items: center;
}
.alignment_right{
display: flex;
justify-content: right;
align-items: center;
}
.alignment_center{
display: flex;
justify-content: center;
align-items: center;
}
.ellipsis_1{
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.ellipsis_2{
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.ellipsis_3{
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
.backCover{
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
.animation-slide-left{
animation: fadeInLeft 800ms ease alternate forwards;
@keyframes fadeInLeft
{
from {
opacity: 1;
-webkit-transform: translate(100%, 0);
transform: translate(100%, 0);
}
to {
opacity:1;
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
}
}
.animation-slide-right{
animation: fadeInRight 800ms ease alternate forwards;
@keyframes fadeInRight
{
from {
opacity: 1;
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
to {
opacity:1;
-webkit-transform: translate(100%, 0);
transform: translate(100%, 0);
}
}
}
.animation-slide-top{
animation: fadeInTop 800ms ease alternate forwards;
@keyframes fadeInTop
{
from {
opacity: 1;
-webkit-transform: translate(0, -1000px);
transform: translate(0, -1000px);
}
to {
opacity:1;
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
}
}
.animation-slide-bottom{
animation: fadeInBottom 800ms ease alternate forwards;
@keyframes fadeInBottom
{
from {
opacity: 1;
-webkit-transform: translate(0, 1000px);
transform: translate(0, 1000px);
}
to {
opacity:1;
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
}
}
.f-fs {
display: flex;
align-items: stretch;
}
.f-fc {
display: flex;
align-items: center;
}
.f-ffs {
display: flex;
align-items: flex-start;
}
.f-fcc{
display: flex;
justify-content: center;
align-items: center;
}
.f-fdc {
flex-direction: column;
}
.f-fbc{
display: flex;
justify-content: space-between;
align-items: center;
}
.f-fcl{
display: flex;
justify-content: left;
align-items: center;
}
.f-fcr{
display: flex;
justify-content: right;
align-items: center;
}
.f-fac{
display: flex;
justify-content: space-around;
align-items: center;
}
.wrap {
flex-wrap: wrap;
}
.groupPurchaseBtnBox {
.groupPurchaseBtn {
width: 130px;
height: 36px;
background: linear-gradient(90deg, #FFC485 0%, #FFA653 100%);
border-radius: 18px 0 0 18px;
}
.groupPurchaseBtnV2 {
width: 130px;
height: 36px;
background: linear-gradient(90deg, #8C9BFF 0%, #707FFA 100%);
border-radius: 0 18px 18px 0;
}
}
.padding_lr_15{
padding: 0 15px;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,266 @@
<template>
<div>
<!-- <label for="tipinput">地址</label>-->
<!-- <div id="tipinput" class="input" placeholder="输入地址关键字" v-model="keyword"/>-->
<div id="container" style="width: 100%; border-radius: 8px" :style="`height:${height || '200'}px;`"></div>
</div>
</template>
<script>
export default {
props: ['setLocation', 'height'],
data() {
return {
keyword: '',
showCode: false,
address: {},
getLng: '', //
getLat: '', //
lnglat: []
}
},
watch: {},
methods: {
init() {
const vm = this
let marker
const map = new AMap.Map('container', {
//
center: vm.setLocation.length > 0 && vm.setLocation[0] !== null ? vm.setLocation : [114.05956, 22.54286],
resizeEnable: true,
zoom: 16,
keyboardEnable: false,
// resizeEnable: true,
viewMode: '3D',
pinch: 45
})
map.setFitView()
let geocoder
// const auto = new AMap.Autocomplete({ input: 'tipinput' }) // input
const infoWindow = new AMap.InfoWindow({
//
autoMove: true,
offset: new AMap.Pixel(10, 20) //
})
// const placeSearch = new AMap.PlaceSearch({ //
// map: map,
// pageSize: 1, //
// extensions: 'all' //
// })
function regeoCode(getLng, getLat) {
if (!geocoder) {
geocoder = new AMap.Geocoder({
// city: '010', //
radius: 1000 // 500
})
}
vm.lnglat = [getLng, getLat]
if (!marker) {
marker = new AMap.Marker({
icon: 'http:////a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-red.png',
position: [getLng, getLat],
offset: new AMap.Pixel(-13, -30),
draggable: true,
cursor: 'move',
raiseOnDrag: true
})
map.add(marker)
}
marker.setPosition(vm.lnglat)
map.setCenter(marker.getPosition())
AMap.event.addListener(marker, 'dragend', function (e) {
vm.lnglat = marker.getPosition()
geocoder.getAddress(vm.lnglat, function (status, result) {
if (status === 'complete' && result.regeocode) {
console.log(result.regeocode.addressComponent)
const address = result.regeocode.formattedAddress
const citycode = result.regeocode.addressComponent.citycode
const value = {
address: address,
province: result.regeocode.addressComponent.province,
city: result.regeocode.addressComponent.city,
dist: result.regeocode.addressComponent.district
}
vm.keyword = address
vm.address = value
infoWindow.setContent(createContent(address, vm.lnglat, citycode))
infoWindow.open(map, marker.getPosition())
vm.$emit('getLocation', value, vm.lnglat)
} else {
console.log('111')
vm.$Notice.error({
title: '温馨提示:',
desc: `位置有误!`
})
}
})
})
geocoder.getAddress(vm.lnglat, function (status, result) {
if (status === 'complete' && result.regeocode) {
console.log(result.regeocode.addressComponent)
const address = result.regeocode.formattedAddress
const citycode = result.regeocode.addressComponent.citycode
const value = {
address: address,
province: result.regeocode.addressComponent.province,
city: result.regeocode.addressComponent.city,
dist: result.regeocode.addressComponent.district
}
vm.keyword = address
vm.address = value
infoWindow.setContent(createContent(address, vm.lnglat, citycode))
infoWindow.open(map, marker.getPosition())
vm.$emit('getLocation', value, vm.lnglat)
} else {
vm.$Notice.error({
title: '温馨提示:',
desc: `位置有误!`
})
}
})
}
function createContent(address, lnglat, citycode) {
//
const s = []
// s.push(`<b>${lnglat}</b>`)
s.push(`地址:${address}`)
// s.push(`${citycode}`)
return s.join('<br>')
}
// function select(e) { //
// console.log(e, '7987')
// placeSearch.setCity(e.poi.adcode)
// placeSearch.search(e.poi.name, (status, result) => { //
// console.log(status)
// const { lng, lat } = result.poiList.pois[0].location
// regeoCode(lng, lat)
// })
// }
// AMap.event.addListener(auto, 'select', select) //
// AMap.event.addListener(placeSearch, 'markerClick', (e) => { //
// })
map.on('click', e => {
//
regeoCode(e.lnglat.getLng(), e.lnglat.getLat())
console.log('111')
})
map.on('dragend', () => {
//
regeoCode(map.getCenter().lng, map.getCenter().lat)
})
map.on('complete', () => {
//
regeoCode(map.getCenter().lng, map.getCenter().lat) //
})
AMap.plugin(
[
// 3D
'AMap.ControlBar'
],
() => {
map.addControl(new AMap.ControlBar())
}
)
}
},
mounted() {
setTimeout(() => {
this.init()
}, 800)
}
}
</script>
<style>
#iCenter {
height: 500px;
position: relative;
display: flex;
flex: 1;
}
#result {
width: 210px;
position: relative;
height: 500px;
overflow-y: scroll;
border-right: 1px solid #ccc;
}
.amap_lib_placeSearch {
height: 100%;
overflow-y: scroll;
}
.amap_lib_placeSearch_page {
position: absolute;
bottom: 0;
width: 100%;
}
#me {
border-top: 1px solid #ccc;
margin-top: 6px;
padding-top: 6px;
width: 100%;
display: block;
}
.amap_lib_placeSearch .poibox {
border-bottom: 1px solid #eaeaea;
cursor: pointer;
padding: 5px 0 5px 10px;
position: relative;
min-height: 35px;
}
.amap_lib_placeSearch_poi {
background: url(https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png) no-repeat;
height: 31px;
width: 19px;
cursor: pointer;
left: -1px;
text-align: center;
color: #fff;
font: 12px arial, simsun, sans-serif;
padding-top: 3px;
}
.amap_lib_placeSearch .poibox .poi-title {
margin-left: 25px;
font-size: 13px;
overflow: hidden;
}
.amap_lib_placeSearch .amap_lib_placeSearch_poi {
position: absolute;
}
.amap_lib_placeSearch .poibox .poi-info {
word-break: break-all;
margin: 0 0 0 25px;
overflow: hidden;
}
.amap_lib_placeSearch .poibox .poi-info p {
color: #999;
font-family: Tahoma;
line-height: 20px;
font-size: 12px;
}
.amap_lib_placeSearch .poibox .poibox-icon {
margin-left: 7px;
margin-top: 4px;
}
.amap-pl-pc .poi-img {
float: right;
margin: 3px 8px 0;
width: 90px;
height: 56px;
overflow: hidden;
}
.poibox {
cursor: pointer;
}
.poibox:hover {
background: #f6f6f6;
}
.selected {
background-image: url(https://webapi.amap.com/theme/v1.3/markers/n/mark_r.png) !important;
}
.amap-info-content {
width: 200px !important;
}
</style>

178
src/components/LikeHeart.js Normal file
View File

@ -0,0 +1,178 @@
/**
* LikeHeart
* @version: 1.0.0
* @author tennylv
* @date 2018-05-24
*
*/
'use strict';
(function(root, factory) {
if (typeof exports === 'object') {
module.exports = factory()
// CMD
} else if (typeof define === 'function' && define.amd) {
define(factory)
// AMD
} else {
// WINDOW
root.LikeHeart = factory()
}
})(this, function() {
const LikeHeart = function(opt) {
/**
* 初始化心
*
* @param {object}
* @object.x {number} 心起点位置x
* @object.y {number} 心起点位置y
* @object.endX {number} 心结束位置x
* @object.endY {number} 心结束位置y
* @object.height {number}
* @object.width {number}
* @object.angelBegin {number} 左右摇摆起始角度(可为负值)
* @object.angelEnd {number} 左右摇摆结束角度
* @object.angleLeft {bool} 是否起始从坐往右摇摆
* @object.noScale {bool} 是否使用缩放心动画
* @object.scaleDis {number} 缩放心临界值(默认从起始位置到升高50)
* @object.noFadeOut {bool} 是否使用fadeOut
* @object.opacityDis {number} fadeout心临界值(默认距离结束位置40)
* @object.speed {number} 上升速度
* @object.bezierPoint {obj} 贝塞尔曲线4个点的值参考https://aaaaaaaty.github.io/bezierMaker.js/playground/playground.html
* @object.fadeOut {function} 每个心fadeOut之后回调
* @object.image {obj} 图片对象
*/
this.id = opt.id
this.x = opt.x
this.y = opt.y
this.endX = opt.endX
this.endY = opt.endY
this.orignY = opt.y
this.height = opt.height
this.width = opt.width
this.angle = 0
this.angleLeft = opt.angleLeft
this.angelBegin = opt.angelBegin || (-20 + rand(1, 2))
this.angelEnd = opt.angelEnd || (20 + rand(1, 2))
this.scale = 0
this.scaleDis = opt.scaleDis || 30
this.opacityDis = opt.opacityDis || 20
this.noScale = opt.noScale
this.noAngel = opt.noAngel
this.opacity = 1
this.speed = opt.speed
this.bezierPoint = opt.bezierPoint
this.bezierDis = 0
this.onFadeOut = opt.onFadeOut
this.IMG = opt.image
this.move = function(ctx) {
if (this.opacity === 0) {
this.onFadeOut && this.onFadeOut(this)
}
this.y = getBezierLine(this).yt
this.x = getBezierLine(this).xt
this.angle = rangeAngle(this)
this.scale = getFScale(this)
this.opacity = getFAlpha(this)
ctx.save()
ctx.translate(this.x, this.y)
ctx.rotate(this.angle * (Math.PI / 180))
ctx.scale(this.scale, this.scale)
ctx.globalAlpha = this.opacity
ctx.drawImage(this.IMG, -(this.IMG.width / 2), -(this.IMG.height / 2), this.width, this.height)
ctx.restore()
}
}
/**
* 计算心左右摇摆的方法
*/
function rangeAngle(heart) {
if (heart.noAngel) {
return 0
}
let _angle = heart.angle
// 心介于[start, end]之间不断变化角度
if (_angle >= heart.angelEnd) {
// 角度不断变小,向左摇摆
heart.angleLeft = false
} else if (_angle <= heart.angelBegin) {
// 角度不断变大,向又摇摆
heart.angleLeft = true
}
// 动态改变角度
if (heart.angleLeft) {
_angle = _angle + 1
} else {
_angle = _angle - 1
}
return _angle
}
/**
* 计算缩放角度的方法
*/
function getFScale(heart) {
if (heart.noScale) {
return 1
}
let _scale = heart.scale
// 随着距离起始点的距离增加scale不断变大
const dis = heart.orignY - heart.y
_scale = (dis / heart.scaleDis)
// 当大于设置的阈值时变成1
if (dis >= heart.scaleDis) {
_scale = 1
}
return _scale
}
/**
* 计算透明度的方法
*/
function getFAlpha(heart) {
let _opacity = heart.opacity
const dis = heart.y - heart.endY
if (dis <= heart.opacityDis) {
_opacity = Math.max((dis / heart.opacityDis), 0)
} else {
_opacity = 1
}
return _opacity
}
/**
* 获得min-max的随机整数
*/
function rand(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}
/**
* 获得贝塞尔曲线路径
* 一共4个点
*/
function getBezierLine(heart) {
const obj = heart.bezierPoint
const p0 = obj.p0
const p1 = obj.p1
const p2 = obj.p2
const p3 = obj.p3
const t = heart.bezierDis
const cx = 3 * (p1.x - p0.x)
const bx = 2 * (p2.x - p1.x) - cx
const ax = p3.x - p0.x - cx - bx
const cy = 3 * (p1.y - p0.y)
const by = 3 * (p2.y - p1.y) - cy
const ay = p3.y - p0.y - cy - by
const xt = ax * (t * t * t) + bx * (t * t) + cx * t + p0.x
const yt = ay * (t * t * t) + by * (t * t) + cy * t + p0.y
heart.bezierDis += heart.speed
return {
xt: xt,
yt: yt
}
}
return LikeHeart
})

87
src/components/TabBar.vue Normal file
View File

@ -0,0 +1,87 @@
<template>
<div>
<van-tabbar
fixed
route
v-model="active"
@change="handleChange"
placeholder="placeholder"
:safe-area-inset-bottom="true"
style="background: #ffffff"
active-color="#707FFA"
inactive-color="#d8d8d8"
>
<van-tabbar-item v-for="(item, index) in tabBarList" :key="index" :to="item.to">
<span>{{ item.title }}</span>
<template #icon="props">
<img :src="props.active ? item.active : item.inactive" />
</template>
</van-tabbar-item>
</van-tabbar>
</div>
</template>
<script>
export default {
name: 'TabBar',
props: {
toName: {
type: String,
default: null
},
defaultActive: {
type: Number,
default: 0
},
tabBarList: {
type: Array,
default: () => {
return []
}
},
data: {
type: Array,
default: () => {
return []
}
}
},
data() {
return {
active: this.defaultActive,
placeholder: true
}
},
watch: {},
methods: {
handleChange(value) {
this.$emit('change', value)
}
},
mounted() {
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
<style lang="scss">
.van-tabbar {
z-index: 999999999999 !important;
}
</style>

100
src/components/XgPlayer.vue Normal file
View File

@ -0,0 +1,100 @@
<template>
<div id='video-player' className='video-player'></div>
</template>
<script>
// import Player from 'xgplayer'
export default {
props: {
url: {
//
type: String,
default: ''
}
},
data() {
return {
player: null //
}
},
mounted() {
console.log('传过来的url:', this.url)
//
this.initPlayer()
},
created() {
},
//
watch: {
url: {
handler(newValue, oldValue) {
if (!this.player) {
this.initPlayer()
return
}
this.player.src = this.url
}
}
},
methods: {
// =========================1===================
initPlayer() {
if (!this.url) return console.warn('url is not esist')
const config = {
id: 'video-player',
url: this.url,
fluid: true,
/** 倍速播放 */
playbackRate: [0.5, 0.75, 1, 1.5, 2],
defaultPlaybackRate: 1,
// lastPlayTime: 20, //
lastPlayTimeHideDelay: 5, //
playsinline: this.isAppleDevice(), // IOS
'x5-video-player-type': 'h5', //
'x5-video-orientation': 'portraint',
/** 画中画 */
pip: true,
pipConfig: {
bottom: 100,
right: 100,
width: 320,
height: 180
},
// download: true,
/** 初始化首帧 */
videoInit: true,
autoplay: true
}
// ========================== 2======================
const player = new Mp4Player(config)
if (player) {
this.player = player
//
//
this.player.on('play', () => {
this.$emit('triggerEvent', this.playerEvent)
})
//
this.player.on('pause', () => {
this.$emit('triggerEvent', this.playerEvent)
})
// 退
this.player.on('exitFullscreen', () => {
window.scrollTo(0, 0)
console.log('已经退出全屏了')
})
}
},
// IOS
isAppleDevice() {
const ua = navigator.userAgent.toLowerCase()
return /iphone|ipad|phone|Mac/i.test(ua)
}
}
}
</script>
<style></style>

126
src/components/address.vue Normal file
View File

@ -0,0 +1,126 @@
<template>
<div class=''>
<div class='addressBox'>
<van-popup v-model="showAddress" :lock-scroll="true" :duration="0.5" position="bottom">
<div style='padding: 0 30px;'>
<div class='alignment'>
<div class='cancelFill font15 color3' @click='close'>取消</div>
<div class='alignment_center completeFill font15 color9'>完成</div>
</div>
<div style='padding-top: 30px'>
<div class='alignment_left'>
<van-field class='inputBox' label="联系人" type="text" v-model="userData.name" placeholder="姓名" />
</div>
<div class='line'></div>
<div class='alignment_left'>
<van-field class='inputBox' label="手机号码" type="number" maxlength="11" v-model="userData.mobile" placeholder="请输入您的手机号码" />
</div>
<div class='line'></div>
<div class='alignment_left'>
<van-field class='inputBox' @click='showCloose = true' label="选择地区" type="number" maxlength="11" v-model="userData.mobile" placeholder="地区信息" />
</div>
<div class='line'></div>
<div class='alignment_left'>
<van-field class='inputBox1' label="详细地址" type="textarea" maxlength="11" v-model="userData.detailed" placeholder="街道门牌信息" />
</div>
<div class='line'></div>
</div>
</div>
</van-popup>
</div>
<div class='clooseAddress'>
<van-popup v-model="showCloose" :lock-scroll="true" :duration="0.5" position="bottom">
<van-area title="标题" :area-list="areaList" />
</van-popup>
</div>
</div>
</template>
<script>
import { areaList } from '@vant/area-data'
export default {
props: {
showAddress: {
type: Boolean,
default: null
}
},
data() {
return {
areaList: areaList,
showCloose: false,
userData: {
mobile: '',
name: '',
detailed: ''
}
}
},
watch: {
},
methods: {
close() {
this.$emit('closepop')
}
},
mounted() {
console.log(this.areaList, '7898797')
}
}
</script>
<style lang="scss" scoped>
.addressBox{
.completeFill{
padding: 2px 10px;
background: #f5f5f5;
border-radius: 3px;
}
.inputBox, .inputBox1{
outline: none;
appearance: none;
border: none;
}
.inputBox{
width: 84%;
padding: initial;
}
.inputBox1{
padding: initial;
width: 90%;
}
.van-field__label{
width: 60px;
font-weight: bold;
margin-right: 30px;
}
.line{
width: 100%;
height: 1px;
background: #f5f5f5;
margin: 10px 0 15px 0;
}
}
.addressBox .van-popup{
top: auto !important;
height: 100vh!important;
border-radius: initial!important;
overflow-y: scroll!important;
}
.clooseAddress{
.van-ellipsis{
}
}
.clooseAddress .van-popup{
top: auto !important;
height: 50vh!important;
border-radius: initial!important;
}
</style>
<style lang='scss'>
.clooseAddress{
.van-overlay{
z-index: 565456545!important;
}
}
</style>

View File

@ -0,0 +1,56 @@
<template>
<div class="backTop">
<img class='goToTopIcon' v-if='Placed' src='https://image.fulllinkai.com/202110/26/f0d10551dc5d3399cc7f15805cf04f4f.png' alt='' @click='goToTop'>
</div>
</template>
<script>
export default {
data() {
return {
Placed: false
}
},
watch: {},
methods: {
//
goToTop() {
const vm = this
let top = document.documentElement.scrollTop || document.body.scrollTop
const timeTop = setInterval(() => {
document.body.scrollTop = document.documentElement.scrollTop = top -= 100
if (top <= 0) {
clearInterval(timeTop)
}
}, 10)
},
//
handleScroll() {
const scrollTop = document.body.scrollTop || document.documentElement.scrollTop
if (scrollTop > 680) {
this.Placed = true
} else {
this.Placed = false
}
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
window.addEventListener('scroll', this.handleScroll, true)
}
}
</script>
<style lang="scss" scoped>
.backTop{
.goToTopIcon{
width: 80px;
height: 80px;
position: fixed;
right: 0;
bottom: 120px;
}
}
</style>

View File

@ -0,0 +1,646 @@
<template>
<div class="commentModule">
<!-- <van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
> -->
<van-list v-model="loading" :finished="finished" @load="getList">
<div style="">
<div>
<div class="m_com">
<div class="font16 color3 bold" id="commentTitle" v-if="type != 'videoDetails'">
评论·{{ commentNumModeule }}
</div>
<div class="m_cou_box" :class="type == 'videoDetails' ? 'sel' : ''" v-if="emptyData">
<div class="m_cou" :id="'comment_' + item.id" v-for="(item, index) in list" :key="index">
<div class="m_user">
<van-image fit="cover" round v-if="item.pic" class="u_lstImg" :src="item.pic" alt="" />
<div class="m_user_name">
<div class="u_user_name font13 color6 f-fcc">
<div class="bold">{{ item.nickname }}</div>
<!-- <div v-if="userData.id == item.commented_id" class="u_user_own font10">作者</div> -->
</div>
<div class="u_user_time font11 color9">{{ item.created_at }}</div>
</div>
</div>
<div class="m_txt font15 color3" @click="clickReply(item)">{{ item.comment }}</div>
<div class="m_reply_pa">
<div class="m_reply" v-if="item.reply && item.reply.length > 0">
<template v-for="(replyItem, replyIndex) in item.reply">
<div class="m_reply_lst font13" v-if="replyIndex < 3 || item.wholeShow" :key="replyIndex">
<span class="u_repLst_name colorTheme font13">
<div>{{ replyItem.nickname }}</div>
<!-- <div v-if="userData.id == item.commented_id" class="u_reply_lst_own font10">
作者
</div> -->
<div></div>
</span>
<span class="u_repLst_txt color3">{{ replyItem.comment }}</span>
</div>
</template>
<div
class="m_whole f-fc font13 colorTheme"
v-if="item.reply && item.reply.length > 3 && !item.wholeShow"
@click.stop="wholeComment(index)"
>
<div>{{ item.reply.length }}条回复</div>
<van-image
fit="cover"
class="u_you_icon"
src="https://image.fulllinkai.com/202111/04/8fb1bde2ef2bd5403ee3756ed1e5910a.png"
alt=""
/>
</div>
</div>
</div>
</div>
</div>
<div class="m_lack f-fcc f-fdc" v-else>
<van-image
class="u_lack_img"
fit="contain"
src="https://image.fulllinkai.com/202111/05/23cbdb149f1eb2bcb423aee104715448.png"
alt=""
/>
<div class="font16 color9">暂无评论</div>
</div>
<div class="m_com_bu">
<div class="u_com_bu f-fbc">
<div class="u_combu_inp font13 color9" @click="inpFocus">说点什么吧</div>
<div>
<a class="f-fcc f-fdc" href="#commentTitle">
<van-image
class="u_combu_icon"
fit="contain"
src="https://image.fulllinkai.com/202111/03/efdd9db7a71e1957f9178884701b15af.png"
alt=""
/>
<div class="fong10 color9">评论{{ commentNumModeule }}</div>
</a>
</div>
<div class="f-fcc f-fdc" @click="likeThrottle">
<van-image
class="u_combu_icon"
fit="contain"
v-if="likeShowModeule"
:show-loading="false"
src="https://image.fulllinkai.com/202111/04/0b74b1f0fce864a2b98b6be9499853a0.png"
alt=""
/>
<van-image
class="u_combu_icon"
fit="contain"
v-else
:show-loading="false"
src="https://image.fulllinkai.com/202111/03/f33908d11fb35037be590da6779c78f1.png"
alt=""
/>
<div class="fong10 color9">{{ likerNumModeule }}</div>
</div>
<div class="f-fcc f-fdc" @click="commentShare">
<van-image
class="u_combu_icon"
fit="contain"
src="https://image.fulllinkai.com/202111/03/1fe29f6a456ef4099a3f3c1eab962740.png"
alt=""
/>
<div class="fong10 color9">分享</div>
</div>
</div>
</div>
</div>
</div>
</div>
</van-list>
<!-- </van-pull-refresh> -->
<van-popup v-model="focusShow" position="bottom" :lock-scroll="true" :duration="0">
<div class="m_field">
<div class="f-ffs">
<div class="replyName font14" v-if="replyName != ''">
回复<span class="colorTheme">{{ replyName }}</span>
:
</div>
<van-field
class="u_combu_inp font13 color9"
type="textarea"
:border="false"
v-model="commentValue"
maxlength="300"
placeholder="说点什么吧"
ref="fieldPhone"
/>
</div>
<div class="m_sendOut">
<div
class="u_sendOut font14 bold f-fcc colorff bcTheme"
:class="commentValue != '' ? 'sel' : ''"
@click="sendOutComment"
>
发送
</div>
</div>
</div>
</van-popup>
</div>
</template>
<script>
import { formatDate } from '@/plugins/timeConversion'
import { $toastClear, $toastLoading, $toastText } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
commentUrl: {
type: String,
default: ''
},
publishCommentUrl: {
type: String,
default: ''
},
commentLikeUrl: {
type: String,
default: ''
},
type: {
type: String,
default: ''
},
commentNum: {
type: Number,
default: 0
},
likerNum: {
type: Number,
default: 0
},
likeShow: {
type: Boolean,
default: false
}
// list: {
// type: Array,
// default: () => {
// return []
// }
// }
},
data() {
return {
commentList: [],
focusShow: false,
commentValue: '',
reply_id: null,
replyName: '',
list: [],
commentNumModeule: 0,
likerNumModeule: 0,
likeShowModeule: false,
method: '',
userData: [],
page: 1,
showLoaded: false,
finished: false,
loading: false,
refreshing: false,
emptyData: true,
noMoreData: false
}
},
watch: {
list(e) {
this.commentList = e
},
commentNum(e) {
console.log(e, '1111111111111111111117987979')
this.commentNumModeule = e
},
likerNum(e) {
console.log(e, '4365436434321321')
this.likerNumModeule = e
},
likeShow(e) {
console.log(e, '4365436434321321')
this.likeShowModeule = e
},
commentUrl(e) {
this.page = 1
this.getList()
}
},
methods: {
// getBusinessUser() {
// const vm = this
// const url = `s/h5/BusinessUser`
// service
// .get(url)
// .then(data => {
// vm.userData = data
// })
// .catch(error => {
// console.log(error)
// })
// },
//
commentLike() {
const vm = this
service
.get(vm.commentLikeUrl)
.then(data => {
if (data.code == 1) {
if (vm.likeShowModeule) {
vm.$emit('update:likerNum', (vm.likerNumModeule -= 1))
} else {
vm.$emit('update:likerNum', (vm.likerNumModeule += 1))
}
vm.$emit('update:likeShow', !vm.likeShowModeule)
vm.$emit('likeShowCallback', vm.likeShowModeule)
}
})
.catch(error => {
console.log(error)
})
},
likeThrottle() {
const vm = this
clearTimeout(this.method)
this.method = setTimeout(function() {
if (vm.likeShowModeule) {
vm.$emit('update:likerNum', (vm.likerNumModeule -= 1))
} else {
vm.$emit('update:likerNum', (vm.likerNumModeule += 1))
}
vm.$emit('update:likeShow', !vm.likeShowModeule)
vm.$emit('likeShowCallback', vm.likeShowModeule)
vm.commentLike()
}, 200)
},
//
getList() {
const vm = this
// $toastLoading(vm.$i18n.t('loading_text'))
vm.$nextTick(() => {
service
.get(`${vm.commentUrl}?page=${vm.page}`)
.then(data => {
vm.commentNumModeule = vm.commentNum
vm.likerNumModeule = vm.likerNum
vm.likeShowModeule = vm.likeShow
if (data.data.length != 0) {
data.data.forEach(item => {
item.created_at = formatDate(item.created_at, 1)
item.wholeShow = false
})
}
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
vm.showLoaded = true
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
vm.loading = false
$toastClear()
}
vm.page++
setTimeout(() => {
// $toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToAboutUs() {
this.$router.push({
name: 'aboutUs'
})
},
goToUrlId(url, id) {
this.$router.push({
name: url,
params: { id: id }
})
},
commentShare() {
this.$emit('clickShare')
},
inpFocus() {
this.replyName = ''
this.reply_id = ''
if (!localStorage.getItem('authorize_at')) {
this.authorization()
return
}
this.focusShow = true
this.$nextTick(() => {
console.log('11111')
this.$refs.fieldPhone.focus()
})
},
inpBlur() {
this.focusShow = false
},
//
sendOutComment() {
const vm = this
if (this.commentValue == '') {
$toastText('说点什么吧')
return
}
vm.focusShow = false
var postData = {
content: vm.commentValue,
reply_id: vm.reply_id
}
service
.post(vm.publishCommentUrl, postData)
.then(data => {
if (data.code != 1) {
var commentData = data
if (vm.reply_id) {
vm.toComment(`comment_${vm.reply_id}`)
vm.forReply(vm.list, vm.reply_id, commentData)
} else {
vm.$nextTick(() => {
vm.emptyData = true
commentData.nickname = vm.userData.nickname
commentData.pic = vm.userData.avatar
commentData.created_at = formatDate(commentData.created_at, 1)
commentData.reply = []
console.log('commentData', commentData)
vm.list.unshift(commentData)
})
this.toComment('commentTitle')
}
vm.$emit('update:commentNum', (vm.commentNumModeule += 1))
vm.$emit('commentNumCallback', vm.commentNumModeule)
}
vm.commentValue = ''
})
.catch(error => {
console.log(error)
})
},
forReply(data, id, addData) {
const vm = this
data.forEach((item, index) => {
if (item.id == id) {
addData.nickname = vm.userData.nickname
item.reply.unshift(addData)
}
})
},
clickReply(item) {
this.replyName = item.nickname
this.reply_id = item.id
this.focusShow = true
this.$nextTick(() => {
this.$refs.fieldPhone.focus()
})
},
wholeComment(index) {
var listArr = this.list[index]
listArr.wholeShow = true
this.list.splice(index, 1, listArr)
},
toComment(id) {
document.querySelector(`#${id}`).scrollIntoView({
behavior: 'smooth', // "auto" "smooth" "auto"
block: 'start', // "start", "center", "end", "nearest" "start"
inline: 'nearest' // "start", "center", "end", "nearest" "nearest"
})
},
authorization() {
const vm = this
const urlPath = vm.$route.path.substr(1, vm.$route.path.length)
localStorage.removeItem('saas_token')
vm.$authorization(vm.$shareCallback, vm.$store.state.app.merchant_id, urlPath)
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
// this.getBusinessUser()
}
}
</script>
<style lang="scss" scoped>
.commentModule {
width: 100%;
// height: 100vh;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.m_com {
background: #ffffff;
.m_cou_box.sel {
padding-top: 0;
}
.m_cou_box {
padding-top: 22px;
.m_cou {
margin-bottom: 20px;
box-sizing: border-box;
.m_lstCt {
padding-right: 10px;
flex: 1;
height: auto;
display: flex;
flex-direction: column;
justify-content: space-between;
.m_lstCt_ta {
padding-top: 10px;
}
}
.m_user {
display: flex;
align-items: stretch;
.u_lstImg {
width: 30px;
height: 30px;
}
.m_user_name {
display: flex;
flex-direction: column;
justify-content: space-between;
padding-left: 6px;
.u_user_name {
line-height: 13px;
}
.u_user_time {
line-height: 11px;
}
}
}
.m_txt {
padding: 8px 0 0 36px;
box-sizing: border-box;
}
.m_reply_pa {
padding-left: 36px;
box-sizing: border-box;
margin-top: 10px;
.m_reply {
padding: 10px 10px 4px;
box-sizing: border-box;
background: #fbfbfb;
border-radius: 8px;
.m_reply_lst {
padding-bottom: 6px;
.u_repLst_txt,
.u_repLst_name {
line-height: 18px;
div {
display: inline-block;
vertical-align: bottom;
}
.u_reply_lst_own {
padding: 4px 6px 3px;
background: #f2f3ff;
border-radius: 9px;
color: #707ffa;
line-height: 10px;
margin-left: 2px;
}
}
}
}
}
}
}
.m_com_bu {
width: 100%;
position: fixed;
bottom: 0;
left: 0;
z-index: 999;
.u_com_bu {
padding: 9px 15px;
box-sizing: border-box;
width: 100%;
background: #ffffff;
border-top: #f5f5f5 solid 1px;
}
.u_com_bu.sel {
border-radius: 16px 16px 0px 0px;
}
.u_combu_inp {
width: 200px;
height: 36px;
background: #f5f5f5;
border-radius: 18px;
padding: 0 15px;
box-sizing: border-box;
line-height: 36px;
}
.u_combu_icon {
width: 20px;
height: 20px;
}
}
}
.u_user_own {
padding: 4px 6px 3px;
background: #f2f3ff;
border-radius: 9px;
color: #707ffa;
line-height: 10px;
margin-left: 2px;
}
.van-popup {
top: auto !important;
border-radius: 16px 16px 0px 0px !important;
overflow: hidden;
}
.m_whole {
line-height: 13px;
padding-bottom: 4px;
box-sizing: border-box;
.u_you_icon {
width: 6px;
height: 8px;
margin-left: 4px;
}
}
.m_field {
.replyName {
padding: 15px 0 15px 15px;
box-sizing: border-box;
word-break: keep-all;
white-space: nowrap;
}
.u_combu_inp {
width: 100%;
height: 60px;
border-radius: 6px;
margin-right: 10px;
line-height: 20px;
padding: 15px;
box-sizing: border-box;
background: #ffffff;
flex: 1;
}
.m_sendOut {
display: flex;
justify-content: flex-end;
padding: 0 15px 10px;
box-sizing: border-box;
.u_sendOut {
margin-top: 6px;
width: 60px;
height: 28px;
border-radius: 16px;
opacity: 0.6;
line-height: 13px;
}
.u_sendOut.sel {
opacity: 1;
}
}
}
.m_lack {
padding: 50px 0;
box-sizing: border-box;
.u_lack_img {
width: 196px;
height: 122px;
}
}
</style>
<style lang="scss">
.van-field--min-height .van-field__control {
min-height: 36px;
}
</style>

View File

@ -0,0 +1,329 @@
<template>
<div class="courseList">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div :style="quoteText == 'mySignUp' ? '' : 'padding-bottom: 110px'">
<div class="text-center" style="padding: 170px 0" v-if="!emptyData">
<img
class="emptyDataIcon"
src="https://image.fulllinkai.com/202108/23/939c529ca16a91e3ee3b22bef2fe92ca.png"
alt=""
/>
<div class="color9 font14" style="margin-top: 14px">{{ $t('Temporarily_no_data') }}</div>
</div>
<div v-else>
<div class="moreCourseBox">
<div
class="courseBox"
v-for="(item, index) in list"
:key="index"
@click="goToUrlId(`consultingDetail`, item.id)"
>
<div v-if="quoteText == 'mySignUp'" class="m_tips f-fcc">60{{ $t('minute') }}</div>
<div class="f-fs">
<van-image class="" width="100" height="100" round fit="cover" :src="item.pic" />
<div class="m_lst_ri">
<div>
<div class="f-fbc">
<div class="font14 color3 bold ellipsis_1 consult-title">
<div class="group-icon backCover" v-if="item.is_group"></div>
{{ item.title }}
</div>
</div>
<div class="font12 color9 ellipsis_1" style="max-width: 160px;margin-top: 4px;">
{{ $t('Voice_consultation') }} {{ item.name }}
</div>
</div>
<div>
<div class="ui-first-discount-box f-fc font10 color9 text-center" v-if="item.has_buy_discount === 1">
<div class="ui-first-discount">首单优惠</div>
<div class="ui-first-discount-price text-center">{{item.first_buy_discount === 0 ? $t('free') :item.first_buy_discount * 10 + '折'}}</div>
</div>
<div class="f-fbc">
<div class="coursePrice bold font14 f-fc" v-if="item.has_buy_discount === 1">
<div v-if="item.first_discount_price != 0"></div>
<div>{{ item.first_discount_price == 0? $t('free') : item.first_discount_price }}</div>
<div class="f-fc font11 color9 ui-ml-4" style="text-decoration: line-through;">
<div v-if="item.price != 0"></div>
<div>{{ item.price == 0? $t('free') : item.price }}</div>
</div>
</div>
<div class="coursePrice bold font14 f-fc" v-else>
<div v-if="item.price != 0"></div>
<div>{{ item.price == 0? $t('free') : item.price }}</div>
</div>
<div class="signUp sel f-fcc font13 colorff" v-if="quoteText == 'mySignUp' && index == 2">
{{ $t('evaluation') }}
</div>
<div class="signUp sel f-fcc font13 colorff" v-else-if="quoteText == 'mySignUp' && index == 3">
{{ $t('See_the_evaluation') }}
</div>
<div class="signUp f-fcc font13 colorff" v-else>{{ $t('Voice_consultation') }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
<div style="height: 50px;"></div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
url: {
type: String,
default: null
},
quoteText: {
type: String,
default: null
}
},
data() {
return {
list: [],
page: 1,
finished: false,
refreshing: false,
emptyData: true,
noMoreData: false,
loading: false
}
},
watch: {},
methods: {
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
service
.get(`${vm.url}?page=${vm.page}`)
.then(data => {
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
vm.$nextTick(() => {
vm.loading = false
vm.page++
})
$toastClear()
}
// vm.loading = false
// vm.page++
setTimeout(() => {
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToUrlId(url, id) {
this.$router.push({
name: url,
params: { id: id }
})
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
}
}
</script>
<style lang="scss" scoped>
.courseList {
height: calc(100vh - 44px) !important;
}
.van-tab__pane {
width: 100vw;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.moreCourseBox {
margin: 0 15px;
.courseBox {
padding: 17px 15px 17px 20px;
margin: 15px 0;
background: #ffffff;
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.1);
border-radius: 8px;
overflow: hidden;
position: relative;
.m_tips {
position: absolute;
left: 0;
top: 0;
background: #f2f3ff;
border-radius: 8px 0px 8px 0px;
font-size: 11px;
color: #707ffa;
line-height: 16px;
width: 50px;
height: 20px;
}
.m_lst_ri {
flex: 1;
height: auto;
display: flex;
flex-direction: column;
justify-content: space-between;
margin-left: 12px;
.consult-title{
max-width: 200px;
}
.group-icon{
float: left;
margin-top: 2px;
margin-right: 4px;
width: 32px;
height: 16px;
background-image: url("https://image.fulllinkai.com/202211/15/631d937276380af19ec646cf7563a64a.png");
}
.signUp {
background: linear-gradient(90deg, #8c9bff 0%, #707ffa 100%);
border-radius: 100px;
padding: 5px 10px;
line-height: 18px;
}
.signUp.sel {
background: linear-gradient(90deg, #ffc67a 0%, #ffb14a 100%);
}
}
.coursePic {
flex: none;
width: 142px;
height: 80px;
margin-right: 10px;
border-radius: 8px;
position: relative;
.preferential {
position: absolute;
top: 0;
left: 0;
background: #ff4a4c;
display: flex;
justify-content: center;
align-items: center;
padding: 0 5px;
height: 17px;
border-radius: 8px 0;
}
}
.ui-first-discount-box{
width: 86px;
//min-width: 86px;
height: 18px;
border-radius: 4px;
border: 1px solid #FFC5C0;
margin-bottom: 1px;
line-height: 18px;
box-sizing: border-box;
overflow: hidden;
}
.ui-first-discount{
width: 46px;
height: 100%;
background: linear-gradient(90deg, #FF4B5F 0%, #FF9159 100%);
border-radius: 3px;
font-size: 10px;
color: #FFFFFF;
box-sizing: border-box;
}
.ui-first-discount-price{
width: 45px;
border-radius: 4px;
background: #ffffff;
font-size: 10px;
color: #FC5142;
}
.coursePrice {
color: #fb9830;
max-width: 150px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.originalPrice {
text-decoration: line-through;
margin-left: 5px;
position: relative;
top: -1px;
}
}
.joinButton,
.joinCourseV2 {
position: absolute;
right: 15px;
bottom: 20px;
width: 78px;
height: 28px;
border-radius: 15px;
border: 1px solid #ffc67d;
}
.joinCourseV2 {
border: 1px solid #c2c2c2;
}
}
}
.bottomLine {
padding-top: 20px;
}
.ui-ml-4{
margin-left: 4px;
}
.ui-mt-8{
margin-top: 8px;
}
</style>
<style lang="scss">
.van-tab__pane {
width: 100%;
min-height: 100%;
background: #ffffff;
}
</style>

View File

@ -0,0 +1,288 @@
<template>
<div class="courseList">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div style="padding-bottom: 110px">
<div class="text-center" style="padding: 170px 0" v-if="!emptyData">
<img
class="emptyDataIcon"
src="https://image.fulllinkai.com/202108/23/939c529ca16a91e3ee3b22bef2fe92ca.png"
alt=""
/>
<div class="color9 font14" style="margin-top: 14px">{{ $t('Temporarily_no_data') }}</div>
</div>
<div v-else>
<div class="moreCourseBox f-fbc wrap">
<div
class="courseBox"
v-for="(item, index) in list"
:key="index"
@click="goToUrlId(`consultingDetail`, item.id)"
>
<div class='discount_icon font11' v-if='item.has_buy_discount == 1' alt=''>首单{{item.first_buy_discount === 0 ? $t('free') : item.first_buy_discount * 10 +'折'}}</div>
<img class='group_icon' v-else-if='item.is_group == 1' src='https://image.fulllinkai.com/202205/23/631d937276380af19ec646cf7563a64a.png' alt=''>
<div class="">
<div class="f-fcc consult-title">
<van-image class="f-fcc -title" width="108" height="108" round fit="cover" :src="item.pic" />
<!--<img class='discount_icon' v-if='item.has_buy_discount == 1' src='https://image.fulllinkai.com/202205/23/631d937276380af19ec646cf7563a64a.png' alt=''>-->
<!--<img class='group_icon' v-else-if='item.is_group == 1' src='https://image.fulllinkai.com/202205/23/631d937276380af19ec646cf7563a64a.png' alt=''>-->
</div>
<div class="m_lst_ri">
<div class="font14 color3 bold ellipsis_1">
{{ item.title }}
</div>
<div class="f-fc text-left">
<div class="font12 color9 ellipsis_1 " style="width: 110px;margin: 4px 0 8px;">
{{ $t('Consulting_teacher') }} {{ item.name }}
</div>
</div>
<div class="f-fbc">
<div class="coursePrice bold font14 f-fc" v-if="item.has_buy_discount === 1">
<div v-if="item.first_discount_price != 0"></div>
<div>{{ item.first_discount_price == 0? $t('free') : item.first_discount_price }}</div>
<div class="f-fc font11 color9 ui-ml-4" style="text-decoration: line-through;">
<div v-if="item.price != 0"></div>
<div>{{ item.price == 0? $t('free') : item.price }}</div>
</div>
</div>
<div class="coursePrice bold font14 f-fc" v-else>
<div v-if="item.price != 0"></div>
<div>{{ item.price == 0? $t('free') : item.price }}</div>
</div>
</div>
<div class=" text-center">
<div class="signUp font14 colorff">{{ $t('Voice_consultation') }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
<div style="height: 50px;"></div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
url: {
type: String,
default: null
}
},
data() {
return {
list: [],
page: 1,
loading: false,
finished: false,
refreshing: false,
emptyData: true,
noMoreData: false
}
},
watch: {},
methods: {
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
service
.get(`${vm.url}?page=${vm.page}`)
.then(data => {
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
vm.$nextTick(() => {
vm.loading = false
vm.page++
})
$toastClear()
}
// vm.loading = false
// vm.page++
setTimeout(() => {
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToUrlId(url, id) {
this.$router.push({
name: url,
params: { id: id }
})
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
}
}
</script>
<style lang="scss" scoped>
.courseList {
height: calc(100vh - 44px) !important;
}
.van-tab__pane {
width: 100vw;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.moreCourseBox {
padding: 0 15px;
box-sizing: border-box;
.courseBox {
position: relative;
width: calc(50% - 6px);
padding: 15px 10px;
margin: 15px 0;
background: #ffffff;
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.1);
border-radius: 8px;
overflow: hidden;
box-sizing: border-box;
.discount_icon{
position: absolute;
left: 0;
top: 0;
padding: 0 5px;
height: 20px;
color:#ffffff;
background: linear-gradient(90deg, #FF4B5F 0%, #FF9159 100%);
border-radius: 12px 0px 8px 0px;
line-height: 20px;
}
.group_icon{
width: 32px;
height: 16px;
position: absolute;
left: 0;
top: 0;
}
.consult-title{
position: relative;
}
.m_lst_ri {
padding-top: 10px;
flex: 1;
height: auto;
display: flex;
flex-direction: column;
justify-content: space-between;
.signUp {
margin: 8px auto 0;
width: 126px;
height: 30px;
background: linear-gradient(90deg, #8c9bff 0%, #707ffa 100%);
border-radius: 100px;
line-height: 30px;
}
}
.coursePic {
flex: none;
width: 142px;
height: 80px;
margin-right: 10px;
border-radius: 8px;
position: relative;
.preferential {
position: absolute;
top: 0;
left: 0;
background: #ff4a4c;
display: flex;
justify-content: center;
align-items: center;
padding: 0 5px;
height: 17px;
border-radius: 8px 0;
}
}
.coursePrice {
color: #fb9830;
max-width: 150px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.originalPrice {
text-decoration: line-through;
margin-left: 5px;
position: relative;
top: -1px;
}
}
.joinButton,
.joinCourseV2 {
position: absolute;
right: 15px;
bottom: 20px;
width: 78px;
height: 28px;
border-radius: 15px;
border: 1px solid #ffc67d;
}
.joinCourseV2 {
border: 1px solid #c2c2c2;
}
}
}
.bottomLine {
padding-top: 20px;
}
.ui-ml-4{
margin-left: 4px;
}
</style>
<style lang="scss">
.van-tab__pane {
width: 100%;
min-height: 100%;
background: #ffffff;
}
</style>

View File

@ -0,0 +1,307 @@
<template>
<div class="courseList">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div style="padding-bottom: 110px">
<div class="text-center" style="padding: 170px 0" v-if="!emptyData">
<img
class="emptyDataIcon"
src="https://image.fulllinkai.com/202108/23/939c529ca16a91e3ee3b22bef2fe92ca.png"
alt=""
/>
<div class="color9 font14" style="margin-top: 14px">{{ $t('Temporarily_no_data') }}</div>
</div>
<div v-else>
<div class="moreCourseBox">
<div
class="courseBox"
v-for="(item, index) in list"
:key="index"
@click="goToUrlId(`consultingDetail`, item.id)"
>
<div class="f-fs">
<van-image class="" width="108" height="108" radius="8" fit="cover" :src="item.pic" />
<div class="m_lst_ri">
<div>
<div class="font14 color3 bold ellipsis_1 consult-title">
<div class="group-icon backCover" v-if="item.is_group"></div>
{{ item.title }}
</div>
<div class="font12 color9 ellipsis_1" style="max-width: 190px;margin-top: 4px;">
{{ $t('Consulting_teacher') }} {{ item.name }}
</div>
</div>
<div>
<div class=" ui-first-discount-box f-fc font10 color9 text-center" v-if="item.has_buy_discount === 1">
<div class="ui-first-discount">首单优惠</div>
<div class="ui-first-discount-price text-center">{{item.first_buy_discount === 0 ? $t('free') :item.first_buy_discount * 10 + '折'}}</div>
</div>
<div class="f-fbc">
<div class="coursePrice bold font14 f-fc" v-if="item.has_buy_discount === 1">
<div v-if="item.first_discount_price != 0"></div>
<div>{{ item.first_discount_price == 0? $t('free') : item.first_discount_price }}</div>
<div class="f-fc font11 color9 ui-ml-4" style="text-decoration: line-through;">
<div v-if="item.price != 0"></div>
<div>{{ item.price == 0? $t('free') : item.price }}</div>
</div>
</div>
<div class="coursePrice bold font14 f-fc" v-else>
<div v-if="item.price != 0"></div>
<div>{{ item.price == 0? $t('free') : item.price }}</div>
</div>
<div class="signUp sel f-fcc font13 colorff" v-if="quoteText == 'mySignUp' && index == 2">
{{ $t('evaluation') }}
</div>
<div class="signUp sel f-fcc font13 colorff" v-else-if="quoteText == 'mySignUp' && index == 3">
{{ $t('See_the_evaluation') }}
</div>
<div class="signUp f-fcc font13 colorff" v-else>{{ $t('Voice_consultation') }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
<div style="height: 50px;"></div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
url: {
type: String,
default: null
},
quoteText: {
type: String,
default: null
}
},
data() {
return {
list: [],
page: 1,
finished: false,
loading: false,
refreshing: false,
emptyData: true,
noMoreData: false
}
},
watch: {},
methods: {
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
service
.get(`${vm.url}?page=${vm.page}`)
.then(data => {
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
vm.$nextTick(() => {
vm.loading = false
vm.page++
})
$toastClear()
}
// vm.page++
// vm.loading = false
setTimeout(() => {
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToUrlId(url, id) {
this.$router.push({
name: url,
params: { id: id }
})
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
}
}
</script>
<style lang="scss" scoped>
.courseList {
height: calc(100vh - 44px) !important;
}
.van-tab__pane {
width: 100vw;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.moreCourseBox {
margin: 0 15px;
.courseBox {
padding: 17px 15px 17px 20px;
margin: 15px 0;
background: #ffffff;
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.1);
border-radius: 8px;
overflow: hidden;
.m_lst_ri {
flex: 1;
height: auto;
display: flex;
flex-direction: column;
justify-content: space-between;
margin-left: 12px;
.consult-title{
max-width: 190px;
}
.group-icon{
float: left;
margin-top: 2px;
margin-right: 4px;
width: 32px;
height: 16px;
background-image: url("https://image.fulllinkai.com/202211/15/631d937276380af19ec646cf7563a64a.png");
}
.signUp {
width: 80px;
height: 28px;
background: linear-gradient(90deg, #8c9bff 0%, #707ffa 100%);
border-radius: 100px;
}
}
.coursePic {
flex: none;
width: 142px;
height: 80px;
margin-right: 10px;
border-radius: 8px;
position: relative;
.preferential {
position: absolute;
top: 0;
left: 0;
background: #ff4a4c;
display: flex;
justify-content: center;
align-items: center;
padding: 0 5px;
height: 17px;
border-radius: 8px 0;
}
}
.ui-first-discount-box{
width: 86px;
//min-width: 86px;
height: 18px;
border-radius: 4px;
border: 1px solid #FFC5C0;
margin-bottom: 1px;
line-height: 18px;
box-sizing: border-box;
overflow: hidden;
}
.ui-first-discount{
width: 46px;
height: 100%;
background: linear-gradient(90deg, #FF4B5F 0%, #FF9159 100%);
border-radius: 3px;
font-size: 10px;
color: #FFFFFF;
box-sizing: border-box;
}
.ui-first-discount-price{
width: 45px;
border-radius: 4px;
background: #ffffff;
font-size: 10px;
color: #FC5142;
}
.coursePrice {
color: #fb9830;
max-width: 150px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.originalPrice {
text-decoration: line-through;
margin-left: 5px;
position: relative;
top: -1px;
}
}
.joinButton,
.joinCourseV2 {
position: absolute;
right: 15px;
bottom: 20px;
width: 78px;
height: 28px;
border-radius: 15px;
border: 1px solid #ffc67d;
}
.joinCourseV2 {
border: 1px solid #c2c2c2;
}
}
}
.bottomLine {
padding-top: 20px;
}
.ui-ml-4{
margin-left: 4px;
}
</style>
<style lang="scss">
.van-tab__pane {
width: 100%;
min-height: 100%;
background: #ffffff;
}
</style>

View File

@ -0,0 +1,339 @@
<template>
<div class="courseList">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div style="padding-bottom: 110px">
<div class='course_class_box' v-if='classList && classList.length != 0'>
<div class='course_class_item font12' :class='classIndex == index ? "activeClass" : "inactiveClass"' v-for='(item,index) in classList' :key='index' @click='chooseClass(item,index)'>
{{item.name}}
</div>
</div>
<div class="text-center" style="padding: 170px 0" v-if="!emptyData">
<img
class="emptyDataIcon"
src="https://image.fulllinkai.com/202108/23/939c529ca16a91e3ee3b22bef2fe92ca.png"
alt=""
/>
<div class="color9 font14" style="margin-top: 14px">{{ $t('Temporarily_no_data') }}</div>
</div>
<div v-else>
<div class="moreCourseBox">
<div
class="courseBox"
v-for="(item, index) in list"
:key="index"
@click="goToUrlId(`courseDetail`, item.id)"
>
<div class="f-fs">
<div class="coursePic backCover">
<van-image class="" width="100%" height="100%" radius="8" fit="cover" :src="item.thumb" />
<div v-if="item.discount_status == 1" class="preferential colorff font10">
{{ $t('preferential') }}
</div>
</div>
<div class="m_lst_ri">
<div class="font14 color3 bold ellipsis_2 course_title">
<div class="group-icon backCover" v-if="item.is_group"></div>
<div>{{ item.title }}</div>
</div>
<div class="coursePrice bold font18">
<span v-if="item.charge != 0"></span>
<span>{{ item.charge == 0? $t('free') : item.charge }}</span>
<span class="color9 font12 originalPrice" v-if="item.discount_status == 1">{{item.price}}</span>
</div>
</div>
</div>
<div class="signUpBox f-fbc" style="margin-top: 5px">
<div class="font12 color9 ellipsis_1" style="width: 200px;">
{{ item.short_description || '' }}
</div>
<div class="signUp f-fcc font13 colorff">{{userAuth.is_vip === 1 && item.vip_free === 1? 'VIP免费' : $t('join_learning') }}</div>
<!--<div class="signUp f-fcc font13 colorff">VIP免费</div>-->
</div>
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
<div style="height: 50px;"></div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
url: {
type: String,
default: null
}
},
data() {
return {
list: [],
classState: 0,
classIndex: 0,
class_id: '',
classList: [],
page: 1,
finished: false,
loading: false,
refreshing: false,
emptyData: true,
noMoreData: false,
userAuth: {}
}
},
watch: {},
methods: {
chooseClass(e, index) {
this.classIndex = index
if (e.id) {
this.class_id = e.id
} else {
this.class_id = ''
}
this.onRefresh()
},
getAllClass() {
const vm = this
const url = `s/h5/course/class`
service.get(url).then(data => {
if (data) {
vm.classList = data
if (vm.classList.length !== 0) {
vm.classList.unshift({ id: 0, name: '全部', sort: 0 })
}
console.log(vm.classList, '/*-/-*-*/-')
}
}).catch(error => {
console.log(error)
})
},
ToText(HTML) {
var input = HTML
return input.replace(/<(style|script|iframe)[^>]*?>[\s\S]+?<\/\1\s*>/gi, '').replace(/<[^>]+?>/g, '').replace(/\s+/g, ' ').replace(/ /g, ' ').replace(/>/g, ' ')
},
getVipValue() {
const vm = this
vm.showQrcode = false
service.get(`s/h5/user/auth/info`)
.then(data => {
console.log(data, 'data----')
vm.userAuth = data
})
},
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
if (!vm.classState) {
vm.class_id = ''
vm.getAllClass()
vm.classState++
}
vm.getVipValue()
service.get(`${vm.url}?page=${vm.page}&class_id=${vm.class_id}`).then(data => {
const dataV = vm.page === 1 ? [] : vm.list
if (data.data && data.data.length !== 0) {
data.data.forEach((item) => {
if (item.short_description) {
item.short_description = vm.ToText(item.short_description).slice(0, 32)
}
})
}
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
if (vm.list && vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
vm.$nextTick(() => {
vm.loading = false
vm.page++
})
$toastClear()
}
// vm.page++
// vm.loading = false
setTimeout(() => {
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToUrlId(url, id) {
this.$router.push({
name: url,
params: { id: id }
})
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
}
}
</script>
<style lang="scss" scoped>
.courseList {
height: calc(100vh - 72px) !important;
}
.van-tab__pane {
width: 100vw;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.course_class_box{
padding: 3px 0 3px 15px;
overflow-x: scroll;
white-space: nowrap;
.course_class_item{
display: inline-block;
width: fit-content;
padding: 3px 12px;
border-radius: 20px;
margin-right: 15px;
}
.activeClass{
color: #707FFA;
background: #F2F3FF;
}
.inactiveClass{
color: #999999;
background: #f8f8f8;
}
}
.moreCourseBox {
margin: 0 15px;
.courseBox {
padding: 15px 15px 10px;
margin: 15px 0;
background: #ffffff;
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.1);
border-radius: 8px;
overflow: hidden;
.m_lst_ri {
flex: 1;
height: auto;
display: flex;
flex-direction: column;
justify-content: space-between;
.group-icon{
float: left;
margin-top: 2px;
margin-right: 4px;
width: 32px;
height: 16px;
background-image: url("https://image.fulllinkai.com/202211/15/631d937276380af19ec646cf7563a64a.png");
}
.course_title {
/*display: flex;*/
/*align-items: center;*/
max-width: 160px;
}
}
.coursePic {
flex: none;
width: 142px;
height: 80px;
margin-right: 10px;
border-radius: 8px;
position: relative;
.preferential {
position: absolute;
top: 0;
left: 0;
background: #ff4a4c;
display: flex;
justify-content: center;
align-items: center;
padding: 0 5px;
height: 17px;
border-radius: 8px 0;
}
}
.coursePrice {
color: #fb9830;
max-width: 80px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.originalPrice {
text-decoration: line-through;
margin-left: 5px;
position: relative;
top: -1px;
}
}
.joinButton,
.joinCourseV2 {
position: absolute;
right: 15px;
bottom: 20px;
width: 78px;
height: 28px;
border-radius: 15px;
border: 1px solid #ffc67d;
}
.joinCourseV2 {
border: 1px solid #c2c2c2;
}
.signUpBox {
.signUp {
width: 80px;
height: 28px;
background: linear-gradient(90deg, #8c9bff 0%, #707ffa 100%);
border-radius: 100px;
}
}
}
}
.bottomLine {
padding-top: 20px;
}
</style>
<style lang="scss">
.van-tab__pane {
width: 100%;
min-height: 100%;
background: #ffffff;
}
</style>

View File

@ -0,0 +1,356 @@
<template>
<div class="courseList">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div style="padding-bottom: 110px">
<div class='course_class_box' v-if='classList && classList.length != 0'>
<div class='course_class_item font12' :class='classIndex == index ? "activeClass" : "inactiveClass"' v-for='(item,index) in classList' :key='index' @click='chooseClass(item,index)'>
{{item.name}}
</div>
</div>
<div class="text-center" style="padding: 170px 0" v-if="!emptyData">
<img
class="emptyDataIcon"
src="https://image.fulllinkai.com/202108/23/939c529ca16a91e3ee3b22bef2fe92ca.png"
alt=""
/>
<div class="color9 font14" style="margin-top: 14px">{{ $t('Temporarily_no_data') }}</div>
</div>
<div v-else>
<div class="moreCourseBox">
<div
class="courseBox"
v-for="(item, index) in list"
:key="index"
@click="goToUrlId(`courseDetail`, item.id)"
>
<div class="coursePic backCover">
<van-image class="" width="100%" height="100%" fit="cover" :src="item.thumb" />
<div v-if="item.discount_status == 1" class="preferential colorff font10">
{{ $t('preferential') }}
</div>
</div>
<div class="m_cou_ct">
<div class="m_lst_ri">
<div class="font16 color3 bold ellipsis_1 course_title">
<div class="group-icon backCover" v-if="item.is_group"></div>
<div class="ellipsis_1">{{ item.title }}</div>
</div>
<div class="font12 color9 ellipsis_1">{{ item.videos_count || 0 }}{{ $t('Class_time') }}</div>
</div>
<div class="signUpBox f-fbc">
<div class="coursePrice bold font18">
<span v-if="item.charge != 0"></span>
<span>{{ item.charge == 0? $t('free') : item.charge }}</span>
<span class="color9 font12 originalPrice" v-if="item.discount_status == 1">{{
item.price
}}</span>
</div>
<div class="signUp f-fcc bold font14 colorff bold">
{{userAuth.is_vip === 1 && item.vip_free === 1? 'VIP免费' : $t('join_learning') }}
<van-image
class="sign_icon"
width="6"
height="8"
fit="contain"
src="https://image.fulllinkai.com/202109/13/6c39c0a86db31f1817d59aa569b23e62.png"
/>
</div>
</div>
</div>
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
<div style="height: 50px;"></div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
url: {
type: String,
default: null
}
},
data() {
return {
list: [],
classState: 0,
classIndex: 0,
class_id: '',
classList: [],
page: 1,
finished: false,
loading: false,
refreshing: false,
emptyData: true,
noMoreData: false,
userAuth: {}
}
},
watch: {},
methods: {
chooseClass(e, index) {
this.classIndex = index
if (e.id) {
this.class_id = e.id
} else {
this.class_id = ''
}
this.onRefresh()
},
getAllClass() {
const vm = this
const url = `s/h5/course/class`
service.get(url).then(data => {
if (data) {
vm.classList = data
if (vm.classList.length !== 0) {
vm.classList.unshift({ id: 0, name: '全部', sort: 0 })
}
console.log(vm.classList, '/*-/-*-*/-')
}
}).catch(error => {
console.log(error)
})
},
ToText(HTML) {
var input = HTML
return input.replace(/<(style|script|iframe)[^>]*?>[\s\S]+?<\/\1\s*>/gi, '').replace(/<[^>]+?>/g, '').replace(/\s+/g, ' ').replace(/ /g, ' ').replace(/>/g, ' ')
},
getVipValue() {
const vm = this
vm.showQrcode = false
service.get(`s/h5/user/auth/info`)
.then(data => {
console.log(data, 'data----')
vm.userAuth = data
})
},
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
console.log('three')
if (!vm.classState) {
vm.class_id = ''
vm.getAllClass()
vm.classState++
}
vm.getVipValue()
service.get(`${vm.url}?page=${vm.page}&class_id=${vm.class_id}`).then(data => {
const dataV = vm.page === 1 ? [] : vm.list
if (data.data && data.data.length !== 0) {
data.data.forEach((item) => {
if (item.short_description) {
item.short_description = vm.ToText(item.short_description).slice(0, 32)
}
})
}
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
vm.$nextTick(() => {
vm.loading = false
vm.page++
})
$toastClear()
}
// vm.page++
// vm.loading = false
setTimeout(() => {
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToUrlId(url, id) {
this.$router.push({
name: url,
params: { id: id }
})
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
}
}
</script>
<style lang="scss" scoped>
.courseList {
height: calc(100vh - 72px) !important;
}
.van-tab__pane {
width: 100vw;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.course_class_box{
padding: 3px 0 3px 15px;
overflow-x: scroll;
white-space: nowrap;
.course_class_item{
display: inline-block;
width: fit-content;
padding: 3px 12px;
border-radius: 20px;
margin-right: 15px;
}
.activeClass{
color: #707FFA;
background: #F2F3FF;
}
.inactiveClass{
color: #999999;
background: #f8f8f8;
}
}
.moreCourseBox {
margin: 0 15px;
.courseBox {
margin: 15px 0;
background: #ffffff;
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.1);
border-radius: 12px;
overflow: hidden;
.coursePic {
width: 100%;
height: 194px;
position: relative;
.group_icon{
width: 32px;
height: 16px;
position: absolute;
left: 0;
top: 0;
}
.preferential {
position: absolute;
top: 0;
left: 0;
background: #ff4a4c;
display: flex;
justify-content: center;
align-items: center;
padding: 0 5px;
height: 17px;
border-radius: 8px 0;
}
}
.m_cou_ct {
padding: 10px 12px 15px;
box-sizing: border-box;
.m_lst_ri {
width: 100%;
.course_title {
/*width: 100%;*/
/*display: flex;*/
/*align-items: center;*/
.group-icon {
float: left;
margin-top: 2px;
margin-right: 4px;
width: 32px;
height: 16px;
background-image: url("https://image.fulllinkai.com/202211/15/631d937276380af19ec646cf7563a64a.png");
}
}
div {
/*width: 100%;*/
margin-bottom: 5px;
}
}
.signUpBox {
width: 100%;
.coursePrice {
color: #fb9830;
max-width: 80px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.originalPrice {
text-decoration: line-through;
margin-left: 5px;
position: relative;
top: -1px;
}
}
.signUp {
color: #707ffa;
.sign_icon {
margin-left: 10px;
}
}
}
}
.joinButton,
.joinCourseV2 {
position: absolute;
right: 15px;
bottom: 20px;
width: 78px;
height: 28px;
border-radius: 15px;
border: 1px solid #ffc67d;
}
.joinCourseV2 {
border: 1px solid #c2c2c2;
}
}
}
.bottomLine {
padding-top: 20px;
}
</style>
<style lang="scss">
.van-tab__pane {
width: 100%;
min-height: 100%;
background: #ffffff;
}
</style>

View File

@ -0,0 +1,346 @@
<template>
<div class="courseList">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div style="padding-bottom: 110px">
<div class='course_class_box' v-if='classList && classList.length != 0'>
<div class='course_class_item font12' :class='classIndex == index ? "activeClass" : "inactiveClass"' v-for='(item,index) in classList' :key='index' @click='chooseClass(item,index)'>
{{item.name}}
</div>
</div>
<div class="text-center" style="padding: 170px 0" v-if="!emptyData">
<img
class="emptyDataIcon"
src="https://image.fulllinkai.com/202108/23/939c529ca16a91e3ee3b22bef2fe92ca.png"
alt=""
/>
<div class="color9 font14" style="margin-top: 14px">{{ $t('Temporarily_no_data') }}</div>
</div>
<div v-else>
<div class="moreCourseBox">
<div
class="courseBox"
v-for="(item, index) in list"
:key="index"
@click="goToUrlId(`courseDetail`, item.id)"
>
<div class="coursePic backCover">
<van-image class="" width="100%" height="100%" fit="cover" :src="item.thumb" />
<div v-if="item.discount_status == 1" class="preferential colorff font10">
{{ $t('preferential') }}
</div>
</div>
<div class="m_cou_ct">
<div class="m_lst_ri">
<div class="font16 color3 bold course_title">
<div class="group-icon backCover" v-if="item.is_group"></div>
<div class="ellipsis_1">{{ item.title }}</div>
</div>
<div class="font12 color9 ellipsis_1">{{ item.videos_count || 0 }}{{ $t('Class_time') }}</div>
</div>
<div class="signUpBox f-fbc">
<div class="coursePrice bold font18">
<span v-if="item.charge != 0"></span>
<span >{{ item.charge == 0? $t('free') : item.charge }}</span>
<span class="color9 font12 originalPrice" v-if="item.discount_status == 1">{{
item.price
}}</span>
</div>
<div class="signUp font14 colorff">{{userAuth.is_vip === 1 && item.vip_free === 1? 'VIP免费' : $t('join_learning') }}</div>
</div>
</div>
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
<div style="height: 50px;"></div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
url: {
type: String,
default: null
}
},
data() {
return {
list: [],
classState: 0,
classIndex: 0,
class_id: '',
classList: [],
page: 1,
finished: false,
loading: false,
refreshing: false,
emptyData: true,
noMoreData: false,
userAuth: {}
}
},
watch: {},
methods: {
chooseClass(e, index) {
this.classIndex = index
if (e.id) {
this.class_id = e.id
} else {
this.class_id = ''
}
this.onRefresh()
},
getAllClass() {
const vm = this
const url = `s/h5/course/class`
service.get(url).then(data => {
if (data) {
vm.classList = data
if (vm.classList.length !== 0) {
vm.classList.unshift({ id: 0, name: '全部', sort: 0 })
}
console.log(vm.classList, '/*-/-*-*/-')
}
}).catch(error => {
console.log(error)
})
},
ToText(HTML) {
var input = HTML
return input.replace(/<(style|script|iframe)[^>]*?>[\s\S]+?<\/\1\s*>/gi, '').replace(/<[^>]+?>/g, '').replace(/\s+/g, ' ').replace(/ /g, ' ').replace(/>/g, ' ')
},
getVipValue() {
const vm = this
vm.showQrcode = false
service.get(`s/h5/user/auth/info`)
.then(data => {
console.log(data, 'data----')
vm.userAuth = data
})
},
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
console.log('two')
if (!vm.classState) {
vm.class_id = ''
vm.getAllClass()
vm.classState++
}
vm.getVipValue()
service.get(`${vm.url}?page=${vm.page}&class_id=${vm.class_id}`).then(data => {
const dataV = vm.page === 1 ? [] : vm.list
if (data.data && data.data.length !== 0) {
data.data.forEach((item) => {
if (item.short_description) {
item.short_description = vm.ToText(item.short_description).slice(0, 32)
}
})
}
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
vm.$nextTick(() => {
vm.loading = false
vm.page++
})
$toastClear()
}
// vm.page++
// vm.loading = false
setTimeout(() => {
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToUrlId(url, id) {
this.$router.push({
name: url,
params: { id: id }
})
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
}
}
</script>
<style lang="scss" scoped>
.courseList {
height: calc(100vh - 44px) !important;
}
.van-tab__pane {
width: 100vw;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.course_class_box{
padding: 3px 0 3px 15px;
overflow-x: scroll;
white-space: nowrap;
.course_class_item{
display: inline-block;
width: fit-content;
padding: 3px 12px;
border-radius: 20px;
margin-right: 15px;
}
.activeClass{
color: #707FFA;
background: #F2F3FF;
}
.inactiveClass{
color: #999999;
background: #f8f8f8;
}
}
.moreCourseBox {
margin: 0 15px;
.courseBox {
margin: 15px 0;
background: #ffffff;
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.1);
border-radius: 12px;
overflow: hidden;
.coursePic {
width: 100%;
height: 194px;
position: relative;
.group_icon{
width: 32px;
height: 16px;
position: absolute;
left: 0;
top: 0;
}
.preferential {
position: absolute;
top: 0;
left: 0;
background: #ff4a4c;
display: flex;
justify-content: center;
align-items: center;
padding: 0 5px;
height: 17px;
border-radius: 8px 0;
}
}
.m_cou_ct {
padding: 10px 12px 15px;
box-sizing: border-box;
.m_lst_ri {
width: 100%;
.course_title{
width: 100%;
/*display: flex;*/
/*align-items: center;*/
.group-icon{
float: left;
margin-top: 2px;
margin-right: 4px;
width: 32px;
height: 16px;
background-image: url("https://image.fulllinkai.com/202211/15/631d937276380af19ec646cf7563a64a.png");
}
}
div {
/*width: 100%;*/
margin-bottom: 5px;
}
}
.signUpBox {
width: 100%;
.coursePrice {
color: #fb9830;
max-width: 80px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.originalPrice {
text-decoration: line-through;
margin-left: 5px;
position: relative;
top: -1px;
}
}
.signUp {
padding: 8px 25px;
background: linear-gradient(90deg, #8c9bff 0%, #707ffa 100%);
border-radius: 100px;
}
}
}
.joinButton,
.joinCourseV2 {
position: absolute;
right: 15px;
bottom: 20px;
width: 78px;
height: 28px;
border-radius: 15px;
border: 1px solid #ffc67d;
}
.joinCourseV2 {
border: 1px solid #c2c2c2;
}
}
}
.bottomLine {
padding-top: 20px;
}
</style>
<style lang="scss">
.van-tab__pane {
width: 100%;
min-height: 100%;
background: #ffffff;
}
</style>

View File

@ -0,0 +1,283 @@
<template>
<div>
<div class="exceptional-box" v-if="detailData.id">
<div class="line"></div>
<div class="color9 font13">{{ $t('Like_the_author_praise_and_support_it') }}</div>
<div class="appreciates-btn font14 colorff alignment_center bcTheme" @click="exceptionalBt">
{{ $t('appreciates') }}
</div>
<div class="font12" style="color: #c2c2c2">
{{ detailData.reward_count || '0' }}{{ $t('people_appreciates') }}
</div>
</div>
<div class="exceptionalPopup">
<van-popup v-model="showExceptional" :click-overlay="false" :lock-scroll="true" :duration="0.5">
<div class="exceptional-popup-box text-center">
<div class="font16 bold title color3">{{ $t('appreciates') }}</div>
<div class="amount-box alignment">
<div
class="amount-item alignment_center font15 color6"
:class="chooseIndex == index ? 'chooseState' : ''"
v-for="(item, index) in exceptionalAmount"
:key="index"
@click="chooseAmount(item, index)"
>
<span>¥</span>{{ item }}
</div>
<div class="amount-item alignment_center font15 color6" :class="chooseIndex == 99 ? 'chooseState' : ''">
<div v-show="!showCustom" @click="customInput">{{ $t('custom') }}</div>
<van-field
v-model="amount"
ref="customAmount"
v-show="showCustom"
@blur="changeBlur"
type="number"
@input="change"
oninput="if(value>10000)value=9999"
/>
</div>
<div class="message-box">
<van-field
v-model="message"
rows="5"
type="textarea"
maxlength="260"
show-word-limit
:placeholder="$t('Leave_a_message_to_the_author_and_encourage_the_author')"
/>
</div>
<div style="width: 100%">
<div class="determine bold font15 alignment_center" @click="paySubmit">{{ $t('determine') }}</div>
</div>
</div>
</div>
<img
class="cancelIcon"
@click="showExceptional = false"
src="https://images.ufutx.com/202107/29/1033c7b52cacddcebe999cefc6ad2c9b.png"
alt=""
/>
</van-popup>
</div>
</div>
</template>
<script>
import { $toastText } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: ['detailData', 'headSize', 'type'],
data() {
return {
exceptionalAmount: [1, 2, 5, 10, 50],
amount: 1,
message: '',
trade_no: '',
chooseIndex: 0,
payThrottle: true,
showExceptional: false,
showCustom: false
}
},
methods: {
authorization() {
const vm = this
const urlPath = vm.$route.path.substr(1, vm.$route.path.length)
localStorage.removeItem('saas_token')
vm.$authorization(vm.$shareCallback, vm.$store.state.app.merchant_id, urlPath)
},
exceptionalBt() {
if (!localStorage.getItem('authorize_at')) {
this.authorization()
return
}
this.showExceptional = true
},
paySubmit() {
const vm = this
const data = {
amount: vm.amount,
comment: vm.message,
type: vm.type
}
if (parseFloat(vm.amount) <= 0) {
return $toastText('赞赏金额不能为0')
}
if (vm.payThrottle) {
vm.payThrottle = false
service
.post(`/s/h5/pay/reward/info/${vm.detailData.id}`, data)
.then(data => {
const wx_pay = data.wx_pay.attributes
const wxconfig = data.wx_pay.config
vm.trade_no = wx_pay.notify_url
if (data.mweb_url) {
vm.payThrottle = true
window.location.href = data.mweb_url
} else {
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
{
appId: wxconfig.appId,
timeStamp: wxconfig.timestamp,
nonceStr: wxconfig.nonceStr,
package: wxconfig.package,
signType: wxconfig.signType,
paySign: wxconfig.paySign
},
function (res) {
if (res.err_msg === 'get_brand_wcpay_request:ok') {
vm.payThrottle = true
// $toastText(vm.$i18n.t('appreciates_successful'))
vm.showCustom = false
vm.showExceptional = false
vm.chooseIndex = 0
vm.message = ''
vm.amount = 1
setTimeout(() => {
vm.$emit('changeData')
vm.callback()
})
} else if (res.err_msg === 'get_brand_wcpay_request:cancel') {
$toastText(vm.$i18n.t('Cancel_payment'))
vm.payThrottle = true
} else if (res.err_msg === 'get_brand_wcpay_request:fail') {
$toastText(vm.$i18n.t('Network_anomalies'))
vm.payThrottle = true
}
}
)
}
})
.catch(error => {
vm.payThrottle = true
console.log(error)
})
}
},
change(e) {
this.amount = e.match(/^\d*(\.?\d{0,2})/g)[0]
},
changeBlur() {
if (!this.amount) {
this.showCustom = false
this.amount = 1
this.chooseIndex = 0
}
},
callback() {
const vm = this
service
.post(vm.trade_no)
.then(data => {
$toastText(vm.$i18n.t('appreciates_successful'))
})
.catch(error => {
console.log(error)
})
},
customInput() {
this.chooseIndex = 99
this.amount = ''
this.showCustom = true
this.$nextTick(() => {
this.$refs.customAmount.focus()
})
},
chooseAmount(item, e) {
this.showCustom = false
this.$refs.customAmount.blur()
this.chooseIndex = e
this.amount = item
}
},
created() {},
mounted() {}
}
</script>
<style lang="scss" scoped>
.exceptional-box {
text-align: center;
.line {
width: 100%;
margin: 20px 0 40px 0;
height: 1px;
background: #f5f5f5;
}
.appreciates-btn {
width: 80px;
height: 28px;
border-radius: 4px;
margin: 10px auto 5px auto;
}
}
.exceptionalPopup {
.exceptional-popup-box {
width: 300px;
.title {
padding: 20px 0 15px 0;
}
.amount-box {
flex-wrap: wrap;
padding: 0 20px;
width: 100%;
box-sizing: border-box;
.amount-item {
width: 80px;
height: 38px;
border-radius: 4px;
border: 1px solid #d8d8d8;
margin-bottom: 10px;
.van-cell {
padding: 0 10px;
font-size: 16px;
}
}
.chooseState {
font-weight: bold;
border: 1px solid #96a2ff;
color: #707ffa;
}
.message-box {
width: 100%;
margin: 5px 0 15px 0;
.van-cell {
border-radius: 4px;
background: #f5f5f5;
font-size: 14px;
padding: 7px 12px;
}
}
.determine {
width: 90px;
height: 38px;
border-radius: 20px;
border: 1px solid #96a2ff;
color: #707ffa;
margin: 0 auto 20px auto;
}
}
.amount-box::after {
content: '';
width: 80px;
}
}
.cancelIcon {
width: 24px;
height: 24px;
position: fixed;
margin-top: 25px;
left: 50%;
transform: translate(-50%);
}
}
</style>
<style lang="scss">
.amount-item {
.van-field__control {
text-align: center !important;
color: #707ffa;
}
}
</style>

View File

@ -0,0 +1,166 @@
<template>
<canvas id="praiseCvs" style="width: 175px; height: 250px" width="375" height="500"></canvas>
</template>
<script>
import LikeHeart from './LikeHeart'
export default {
data() {
return {
ctx: null, // canvas
rafId: '', // id
ratio: 0,
heartInterval: null, //
praiseNum: 0, //
cachePraiseNum: 0, //
aletMsg: '', //
displayStsates: 'none', //
toShake: false,
// praiseTime: null,
width: 175, //
height: 250, //
heartList: [], //
heartCount: 0, //
iconPic: [
'https://images.ufutx.com/202008/12/1.png',
'https://images.ufutx.com/202008/12/2.png',
'https://images.ufutx.com/202008/12/3.png',
'https://images.ufutx.com/202008/12/4.png',
'https://images.ufutx.com/202008/12/5.png'
]
}
},
created() {},
mounted() {
this.$nextTick(() => {
this.initCtx()
})
},
methods: {
removeCtx(state) {
this.ctx.clearRect(0, 0, 500, 500)
clearInterval(this.heartInterval)
cancelAnimationFrame(this.rafId)
this.ctx = null
this.rafId = 0
this.ratio = 0
this.heartInterval = null
this.heartList = []
this.heartCount = 0
if (state === '1') {
this.$nextTick(() => {
this.initCtx()
})
}
},
//
initCtx() {
//
const _this = this
_this.ctx = document.getElementById('praiseCvs').getContext('2d')
_this.ratio = window.devicePixelRatio
_this.ctx.canvas.width = _this.width * _this.ratio
_this.ctx.canvas.height = _this.height * _this.ratio
_this.ctx.scale(_this.ratio, _this.ratio)
// (_this.ctx.translate(0.5, 0.5));
// (function loop() {
// _this.ctx.clearRect(0, 0, _this.width, _this.height)
// _this.heartList.forEach(function (item) {
// item && item.move(_this.ctx)
// })
// _this.rafId = requestAnimationFrame(loop)
// })()
function requestAnimation() {
_this.ctx.clearRect(0, 0, _this.width, _this.height)
_this.heartList.forEach(item => {
item && item.move(_this.ctx)
})
_this.rafId = requestAnimationFrame(requestAnimation)
}
_this.rafId = requestAnimationFrame(requestAnimation)
// _this.heartInterval = setInterval(function() {
// _this.heartList.push(_this.createHeart())
// }, 1000)
},
zanFn() {
const vm = this
vm.cachePraiseNum += 1
if (parseInt(vm.praiseNum) <= 9998) {
vm.praiseNum += 1
}
// let setIntervalFn = setInterval(function () {
vm.heartList.push(vm.createHeart())
this.toShake = true
// demo for next animation.
setTimeout(() => {
this.toShake = false
}, 1000)
// }, 120)
// setTimeout(() => {
// clearInterval(setIntervalFn)
// }, 1200)
},
getRandomDis() {
if (Math.random() > 0.5) {
return -(Math.random() * 12)
} else {
return +(Math.random() * 12)
}
},
createHeart() {
// console.log(this.heartCount, '6666')
// let vm = this
this.heartCount++
const positionArray = [
{
x: 60,
y: 200,
endX: 130,
endY: -100
}
]
const img = new Image()
img.src = `https://images.ufutx.com/202008/22/${Math.ceil(Math.random() * 6)}.png`
const p1 = {
x: 60 + this.getRandomDis(),
y: 80 + this.getRandomDis()
}
const p2 = {
x: 10 + this.getRandomDis(),
y: 50 + this.getRandomDis()
}
return new LikeHeart({
id: this.heartCount,
x: positionArray[0].x,
y: positionArray[0].y,
endX: positionArray[0].endX,
endY: positionArray[0].endY,
onFadeOut: this.removeItem,
// noAngel: true, //
noScale: true, //
angleLeft: true,
width: 20, //
height: 20,
speed: 0.0017,
image: img,
bezierPoint: {
p0: {
x: positionArray[0].x,
y: positionArray[0].y
},
p1: p1,
p2: p2,
p3: {
x: positionArray[0].endX,
y: positionArray[0].endY
}
}
})
}
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,119 @@
<template>
<div>
<van-popup v-model="onShow" :close-on-click-overlay="false" :lock-scroll="true" :duration="0.5">
<div class="material-box">
<div class="font18 material-title">素材库图片</div>
<div class="material-pics">
<img :class="selectIndex === index? 'select-box': ''" :src="item" class="pic" v-for="(item,index) in materialList" :key="index" @click="selectPic(index)">
</div>
<div class='edit_poster alignment_center colorff font15' @click="toSelectPic">确认</div>
<img class="cancelIcon" @click.stop="clickShare" src="https://image.fulllinkai.com/202110/23/78698e898cd570e5e7751c323e4a5cb7.png" alt="" />
</div>
</van-popup>
</div>
</template>
<script>
import service from '@/utils/request'
export default {
name: 'FolderPic',
props: ['onShow'],
data() {
return {
selectIndex: 0,
materialList: [
'https://image.fulllinkai.com/202110/23/78698e898cd570e5e7751c323e4a5cb7.png',
'https://image.fulllinkai.com/202211/04/dabb753754f3c5034eff22df8d5a7021.jpeg',
'https://image.fulllinkai.com/202110/23/78698e898cd570e5e7751c323e4a5cb7.png',
'https://image.fulllinkai.com/202110/23/78698e898cd570e5e7751c323e4a5cb7.png',
'https://image.fulllinkai.com/202110/23/78698e898cd570e5e7751c323e4a5cb7.png',
'https://image.fulllinkai.com/202110/23/78698e898cd570e5e7751c323e4a5cb7.png',
'https://image.fulllinkai.com/202110/23/78698e898cd570e5e7751c323e4a5cb7.png',
'https://image.fulllinkai.com/202110/23/78698e898cd570e5e7751c323e4a5cb7.png',
'https://image.fulllinkai.com/202110/23/78698e898cd570e5e7751c323e4a5cb7.png',
'https://image.fulllinkai.com/202110/23/78698e898cd570e5e7751c323e4a5cb7.png'
] //
}
},
methods: {
clickShare() {
this.$emit('update:onShow', !this.onShow)
},
getMaterialList() {
const vm = this
service.get(``)
.then(data => {
vm.materialList = data
})
},
selectPic(index) {
this.selectIndex = index
},
toSelectPic() {
console.log('11321----&**')
this.$emit('onChange', this.materialList[this.selectIndex])
}
},
mounted() {
// this.getMaterialList()
}
}
</script>
<style lang="scss" scoped>
.material-box{
position: relative;
/*height: 300px;*/
width: 300px;
padding: 10px 20px;
.material-title{
margin: 10px 0 20px;
text-align: center;
}
.material-pics{
display: flex;
flex-wrap: wrap;
align-items: center;
max-height: 300px;
overflow-y: scroll;
/*overflow: hidden;*/
.pic{
margin-right: 20px;
margin-bottom: 20px;
height: 80px;
width: 80px;
border-radius: 5px;
object-fit: cover;
}
.pic:nth-child(3n){
margin-right: 0px;
}
.select-box{
padding: -2px;
box-shadow: 0px 0px 20px 0px rgba(112,127,250,0.43);
border: 1px solid #707FFA;
}
}
.edit_poster{
width: 200px;
height: 40px;
background: linear-gradient(90deg, #8C9BFF 0%, #707FFA 100%);
border-radius: 20px;
margin: 20px auto 10px auto;
}
.cancelIcon {
width: 15px;
height: 15px;
position: absolute;
z-index: 222;
top: 10px;
right: 15px;
}
}
.van-popup {
top: 48% !important;
/*border-radius: 12px !important;*/
/*overflow-y: initial !important;*/
/*z-index: 100000001 !important;*/
}
</style>

View File

@ -0,0 +1,152 @@
<template>
<div class="groupJoinData">
<div v-show='showList'>
<div class='segmentation' :style="{marginTop: type == 'course'? '15px':''}"></div>
<div style='margin: 15px'>
<div class='font16 color3 bold' style='padding-bottom: 2px'>{{list.length}}人发起拼团可直接参与</div>
<div>
<div class="marqueeWrap" :class='list && list.length > 1 ? "" : "marqueeWrapActive"'>
<div class="animateBox">
<div class="animate" :class="{ 'animate-up': animateUp }">
<div class='alignment' style='padding-top: 15px' v-for="(item, index) in list" :key="index">
<div class='alignment_left'>
<div class="head_pic backCover" :style="{ backgroundImage: 'url(' + item.avatar + ')' }"></div>
<div class='font14 color3 ellipsis_1' style='max-width: 100px'>{{item.nickname}}</div>
</div>
<div class='alignment_right'>
<div>
<div class='font12 color6'>还差<span style='color: #FFAC4A'>{{item.need_count}}</span>拼团</div>
<div class='font10 color9 text-right'>剩余{{item.deadline}}</div>
</div>
<div class='goToJoin alignment_center colorff font13' @click.stop='chooseSwiper(item)'>去参团</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class='segmentation'></div>
</div>
</div>
</template>
<script>
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: ['type'],
data() {
return {
id: '',
showList: false,
animateUp: false,
timer: null,
list: [],
bg: 'https://image.fulllinkai.com/202208/02/ccd8c3e29b9bdfc89907d92584497154.jpeg'
}
},
methods: {
scrollAnimate() {
const vm = this
this.animateUp = true
setTimeout(() => {
vm.list.push(vm.list[0])
vm.list.shift()
vm.animateUp = false
}, 3300)
},
getGroupList() {
const vm = this
service.get(`s/h5/business/unfinished/groups?type_id=${vm.id}&type=${vm.type}`).then(data => {
vm.list = data
if (vm.list && vm.list.length !== 0) {
vm.$nextTick(() => {
vm.showList = true
})
}
console.log(vm.showList, '--------------showList')
if (vm.list && vm.list.length > 2) {
this.timer = setInterval(this.scrollAnimate, 3500)
}
}).catch(error => {
console.log(error)
})
},
chooseSwiper(e) {
const vm = this
vm.$router.push({
name: 'groupData',
query: { order_id: e.m_order_id, type: vm.type, history_id: e.id, id: vm.id }
})
// window.location.replace(`${vm.$shareCallback}/pu/#/groupData?order_id=${e.m_order_id}&merchant_id=${vm.$store.state.app.merchant_id}&history_id=${e.id}`)
// window.location.replace(`http://sh5.ufutx.net/pu/#/groupData?order_id=${e.m_order_id}&merchant_id=${vm.$store.state.app.merchant_id}&history_id=${e.id}`)
console.log(e, '7987')
}
},
destroyed() {
clearInterval(this.timer)
this.timer = null
},
created() {
},
mounted() {
this.id = this.$route.params.id
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
this.getGroupList()
}
}
</script>
<style lang="scss" scoped>
.groupJoinData {
margin-bottom: 1px;
.segmentation{
//margin-bottom: -15px;
height: 8px;
background: #f8f8f8;
}
.marqueeWrap {
height: 94px;
overflow: hidden;
display: flex;
.animate-up {
transition: all 1s;
margin-top: -47px;
flex: none;
width: 100%;
}
.animateBox {
flex: none;
width: 100%;
height: 100%;
}
.animate {
width: 100%;
height: 100%;
}
}
.marqueeWrapActive{
height: 47px;
}
.head_pic{
width: 30px;
height: 30px;
border-radius: 50%;
margin-right: 5px;
border: 1px solid #FFFFFF;
}
.goToJoin{
position: relative;
z-index: 9;
width: 52px;
height: 22px;
background: linear-gradient(90deg, #FFC485 0%, #FFA653 100%);
border-radius: 11px;
margin-left: 10px;
}
}
</style>

View File

@ -0,0 +1,116 @@
<template>
<div class="groupTopData" :class="(type==='community'||type==='shop')? 'padding-more' : (type==='consult')? 'padding-more-v2' :''">
<div v-show='spellGroupState'>
<div class="groupTopBg alignment" :class="(type === 'course')? 'groupTopBgV2':''" :style="{ backgroundImage: 'url(' + bg + ')' }">
<div class='alignment_left' style='margin-left: 15px'>
<div class='font22 bold colorff'><span class='font14'>¥</span>{{group.price || 0}}</div>
<div class='groupTopNum alignment_center font13'>{{group.require_num || 0}}人成团</div>
</div>
<div style='margin-right: 15px'>
<div class='font12 colorff text-right'>距结束仅剩</div>
<div class='alignment_right colorff font11' style='margin-top: 2px'>
<div>{{countdown.d}}</div>
<div class='countdownSmallBox'>{{countdown.h}}</div>
<div>:</div>
<div class='countdownSmallBox'>{{countdown.m}}</div>
<div>:</div>
<div class='countdownSmallBox'>{{countdown.s}}</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { formatRemainTimeData } from '@/plugins/timeConversion'
export default {
computed: {},
components: {},
props: ['group', 'type'],
data() {
return {
timer: null,
loading: false,
spellGroupState: false,
countdown: {},
bg: 'https://image.fulllinkai.com/202208/02/7fb24bf1377799eafe9fc07337bd106c.png'
}
},
watch: {
group() {
const vm = this
console.log(vm.group.end_time, 'vm.group.end_time---')
if (vm.group && vm.group.end_time) {
const time = vm.group.end_time
const timeOut = formatRemainTimeData(time)
if (timeOut.d == 0 && timeOut.h == '00' && timeOut.m == '00' && timeOut.s == '00') {
vm.spellGroupState = false
} else {
vm.spellGroupState = true
}
vm.timer = setInterval(() => {
vm.countdown = formatRemainTimeData(time)
if (vm.countdown.d == 0 && vm.countdown.h == '00' && vm.countdown.m == '00' && vm.countdown.s == '00') {
clearInterval(vm.timer)
vm.timer = null
vm.spellGroupState = false
} else {
vm.spellGroupState = true
}
}, 1000)
}
console.log(this.group, '-----')
}
},
methods: {
},
created() {
},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
}
}
</script>
<style lang="scss" scoped>
.groupTopData {
.groupTopBg{
/*width: 100vw;*/
height: 60px;
border-radius: 12px 12px 0 0;
.groupTopNum{
color: #FFAC4A;
padding: 2px 10px 3px 10px;
border-radius: 20px;
background: #ffffff;
margin-left: 8px;
}
.countdownSmallBox{
width: 16px;
height: 16px;
background: #FFFFFF;
color: #ffac4a;
border-radius: 4px;
margin: 0 2px;
display: flex;
justify-content: center;
align-items: center;
}
}
.groupTopBgV2{
border-radius: 0;
}
}
.padding-more{
position: relative;
margin-top: -14px;
z-index: 222;
}
.padding-more-v2{
position: relative;
margin-top: -110px;
z-index: 222;
}
</style>

View File

@ -0,0 +1,225 @@
<template>
<div class="health_collect_one">
<div class="merchants_data_box">
<div class="card-title">基础资料</div>
<div class='input_box' v-for='(item,index) in basicData' :key='index'>
<div class="font14 color9" v-if="index === 6 && fromDataOne.sex !=='女' ? false : true">{{item.name}}</div>
<van-field v-if="index === 6 && fromDataOne.sex !=='' ? false : true" class="name_input alignment_center font14 color3" type="text" readonly v-model="fromDataOne[item.parameter]" :placeholder="item.prompt" @click='showChoose(item,index)'/>
</div>
</div>
<div class='colorff font16 bold next_button alignment_center' @click='nextStep'>下一步</div>
<van-popup v-model="showSex" round position="bottom" :lock-scroll="true">
<van-picker show-toolbar :columns="sexList" @cancel="showSex = false" @confirm="onConfirm" title="选择你的性别" ref='pickerSex' />
</van-popup>
<van-popup v-model="showBirthday" round position="bottom" :lock-scroll="true">
<van-datetime-picker @cancel="showBirthday = false" @confirm="onConfirm" v-model="currentDate" type="date" title="选择你的生日日期" :min-date="minDate" :max-date="maxDate"/>
</van-popup>
<!--<van-popup v-model="showAge" round position="bottom" :lock-scroll="true">-->
<!-- <van-picker show-toolbar :columns="ageList" @cancel="showAge = false" @confirm="onConfirm" title="选择你的年龄" ref='pickerAge' />-->
<!--</van-popup>-->
<van-popup v-model="showHeight" round position="bottom" :lock-scroll="true">
<van-picker show-toolbar :columns="heightList" @cancel="showHeight = false" @confirm="onConfirm" title="选择你的身高" ref='pickerHeight' />
</van-popup>
<van-popup v-model="showWeight" round position="bottom" :lock-scroll="true">
<van-picker show-toolbar :columns="weightList" @cancel="showWeight = false" @confirm="onConfirm" title="选择你的体重" ref='pickerWeight' />
</van-popup>
<van-popup v-model="showVegetarian" round position="bottom" :lock-scroll="true">
<van-picker show-toolbar :columns="vegetarianList" @cancel="showVegetarian = false" @confirm="onConfirm" title="选择是否素食" ref='pickerVegetarian' />
</van-popup>
<van-popup v-model="showEgg" round position="bottom" :lock-scroll="true">
<van-picker show-toolbar :columns="eggList" @cancel="showEgg = false" @confirm="onConfirm" title="选择是否可以吃鸡蛋" ref='pickerEgg' />
</van-popup>
<van-popup v-model="showPeriod" round position="bottom" :lock-scroll="true">
<van-picker show-toolbar :columns="periodList" @cancel="showPeriod = false" @confirm="onConfirm" title="选择是否吃鸡蛋" ref='pickerPeriod' />
</van-popup>
</div>
</template>
<script>
import service from '@/utils/request'
import { formatDate } from '@/plugins/timeTransition'
import { $toastClear, $toastLoading, $toastText } from '@/config/toast'
export default {
name: 'HealthCollectOne',
props: {
healthOne: {
type: Object,
default: null
}
},
data() {
return {
basicData: [
{ name: '性别', prompt: '添加性别', parameter: 'sex', show: 'showSex' },
{ name: '年龄', prompt: '选择出生日期', parameter: 'birthday', show: 'showBirthday' },
{ name: '身高', prompt: '选择身高', parameter: 'height', show: 'showHeight' },
{ name: '体重', prompt: '选择体重', parameter: 'weight', show: 'showWeight' },
{ name: '素食', prompt: '是否素食', parameter: 'vegetarian', show: 'showVegetarian' },
{ name: '吃鸡蛋', prompt: '是否可以吃鸡蛋', parameter: 'egg', show: 'showEgg' },
{ name: '经期', prompt: '是否绝经', parameter: 'period', show: 'showPeriod' }
],
fromDataOne: {
sex: '', //
birthday: '', //
height: '', //
weight: '', //
vegetarian: '', //
egg: '', //
period: '' //
},
keyVal: [], //
minDate: new Date(1940, 0, 1),
maxDate: new Date(),
currentDate: new Date(1990, 0, 1),
sexList: ['男', '女'],
showSex: false, //
showBirthday: false,
ageList: [],
showAge: false,
heightList: [],
showHeight: false,
weightList: [],
showWeight: false,
vegetarianList: ['是', '否'],
showVegetarian: false,
eggList: ['是', '否'],
showEgg: false,
periodList: ['未绝经', '已绝经'],
showPeriod: false
}
},
watch: {
'healthOne'() {
console.log(this.healthOne, 'this.healthOne---')
this.fromDataOne = this.healthOne
}
},
methods: {
showChoose(item, index) {
const vm = this
vm[item.show] = true
vm.$nextTick(() => { //
if (index === 0) {
vm.$refs.pickerSex.setColumnValue(0, vm.fromDataOne.sex || '男')
} else if (index === 1) {
// vm.$refs.pickerAge.setColumnValue(0, vm.fromDataOne.age || '24')
} else if (index === 2) {
vm.$refs.pickerHeight.setColumnValue(0, vm.fromDataOne.height || '140cm')
} else if (index === 3) {
vm.$refs.pickerWeight.setColumnValue(0, vm.fromDataOne.weight || '40kg')
} else if (index === 4) {
vm.$refs.pickerVegetarian.setColumnValue(0, vm.fromDataOne.vegetarian || '否')
} else if (index === 5) {
vm.$refs.pickerEgg.setColumnValue(0, vm.fromDataOne.egg || '是')
} else if (index === 6) {
vm.$refs.pickerPeriod.setColumnValue(0, vm.fromDataOne.period || '未绝经')
}
})
this.chooseState = item.show
this.chooseSIndex = index
},
onConfirm(val, index) {
if (this.chooseSIndex === 0) {
this.fromDataOne.sex = val
} else if (this.chooseSIndex === 1) {
this.fromDataOne.birthday = formatDate(val, 'yyyy-MM-dd')
// this.fromDataOne.age = val
} else if (this.chooseSIndex === 2) {
this.fromDataOne.height = val
} else if (this.chooseSIndex === 3) {
this.fromDataOne.weight = val
} else if (this.chooseSIndex === 4) {
this.fromDataOne.vegetarian = val
} else if (this.chooseSIndex === 5) {
this.fromDataOne.egg = val
} else if (this.chooseSIndex === 6) {
this.fromDataOne.period = val
}
this[this.chooseState] = false
},
nextStep() {
const vm = this
vm.keyVal = Object.keys(vm.fromDataOne)
console.log(vm.keyVal, 'this.keyVal')
for (const i in vm.keyVal) {
if (!vm.fromDataOne[vm.keyVal[i]]) {
if (vm.fromDataOne.sex !== '男' || vm.keyVal[i] !== 'period') {
return $toastText('请完善基础资料')
}
}
}
console.log('bbb---')
const data = {
sex: vm.fromDataOne.sex === '男' ? '1' : '0',
birthday: vm.fromDataOne.birthday,
period: vm.fromDataOne.sex === '女' ? vm.fromDataOne.period : '',
height: vm.fromDataOne.height,
weight: vm.fromDataOne.weight,
vegtarian: vm.fromDataOne.vegtarian === '是' ? '1' : '0',
egg: vm.fromDataOne.egg === '是' ? '1' : '0'
}
service.put(`s/h5/health/base?order_id=530`, data)
.then(data => {
console.log(data, 'data-----')
if (data.code !== 1) {
this.$emit('oneChange', this.fromDataOne.sex)
}
})
}
},
mounted() {
// //
// for (let num = 12; num < 99; num++) {
// this.ageList.push(`${num}`)
// }
//
for (let num = 140; num < 220; num++) {
this.heightList.push(`${num}cm`)
}
//
for (let num = 40; num < 130; num++) {
this.weightList.push(`${num}kg`)
}
}
}
</script>
<style lang="scss" scoped>
.health_collect_one{
margin: 10px 15px 0;
background: #ffffff;
border-radius: 12px;
padding-bottom: 15px;
.merchants_data_box {
padding: 15px 20px 25px 20px;
.card-title{
margin-bottom: 10px;
font-size: 16px;
font-weight: bold;
}
.input_box{
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10px;
}
.name_input {
width: 160px;
height: 35px;
background: #f8f8f8;
border-radius: 8px;
/*margin-top: 10px;*/
}
}
.next_button{
width: 260px;
height: 44px;
border-radius: 30px;
margin: 30px auto 0 auto;
/*padding-bottom: 10px;*/
background: linear-gradient(90deg, #8c9bff 0%, #707ffa 100%);
}
}
</style>

View File

@ -0,0 +1,192 @@
<template>
<div class="health_collect_three">
<div class="health-card">
<div class="card-big-title">体检信息</div>
<div v-for="(item,index) in pExaminationData" :key="index">
<div class="merchants_data_box">
<div class="card-title">{{item.label}}</div>
<div class='input_box' v-for="(itemV2,indexV2) in item.children" :key="indexV2">
<div class="font14 color9">{{itemV2.label}}</div>
<van-field class="name_input alignment_center font14 color3" type="number" input-align="right" v-model="fromeDataThre[itemV2.val]" placeholder="请填写" step="0.0000000001" @blur="changeValue($event,itemV2.min,itemV2.max)">
<van-button class="btn_class" slot="button">{{itemV2.unit}}</van-button>
</van-field>
</div>
</div>
</div>
<div class='colorff font16 bold next_button alignment_center'>提交</div>
</div>
</div>
</template>
<script>
export default {
name: 'HealthCollectThree',
data() {
return {
pExaminationData: [
{
label: '血压',
children: [
{ label: '收缩压', val: 'sbp', min: 90, max: 140, unit: 'mmHg' },
{ label: '舒张压', val: 'dbp', min: 60, max: 90, unit: 'mmHg' }
]
},
{
label: '糖检测',
children: [
{ label: '空腹血糖', val: 'fbg', min: 3.9, max: 6.1, unit: 'mmol/L' }]
},
{
label: '肾功能检测',
children: [
{ label: '尿素', val: 'urea', min: 2.9, max: 8.2, type: 'number', unit: 'mmol/L' },
{ label: '肌酐', val: 'cre', min: 53, max: 97, type: 'number', unit: 'umol/L' },
{ label: '尿素', val: 'ua', min: 208, max: 428, type: 'number', unit: 'umol/L' },
{ label: '胱抑素C', val: 'cvsc', min: 0.63, max: 1.25, type: 'number', unit: 'mg/L' }
]
},
{
label: '血脂四项检查',
children: [
{ label: '总胆固醇', val: 'tc', min: 3.1, max: 5.23, unit: 'mmol/L' },
{ label: '甘油三脂', val: 'tg', min: 0.56, max: 1.47, unit: 'mmol/L' },
{ label: '高密度脂蛋白', val: 'hdl', min: 0.91, max: 2.06, unit: 'mmol/L' },
{ label: '低密度脂蛋白', val: 'ldl', min: 0, max: 3.36, unit: 'mmol/L' }
]
},
{
label: '五分类血常规',
children: [
{ label: '白细胞计数', val: 'wbc', min: 3.5, max: 9.5, type: 'number', unit: '10^9/L' },
{ label: '红细胞计数', val: 'rbc', min: 4.3, max: 5.8, type: 'number', unit: '10^12/L' },
{ label: '血红蛋白', val: 'hgb', min: 130, max: 175, type: 'number', unit: 'g/L' },
{ label: '红细胞比积', val: 'hct', min: 0.4, max: 0.5, type: 'number', unit: '' },
{ label: '平均RBC体积', val: 'mcv', min: 82, max: 100, type: 'number', unit: 'fl' },
{ label: '平均RBC血红蛋白量', val: 'mch', min: 27, max: 34, type: 'number', unit: 'pg' },
{ label: '平均RBC血红蛋白浓度', val: 'mchc', min: 316, max: 354, type: 'number', unit: 'g/L' },
{ label: 'RBC分布宽度标准差', val: 'rdw', min: 37, max: 54, type: 'number', unit: 'fL' },
{ label: 'RBC分布宽度变异系数', val: 'rdwcv', min: 0.11, max: 0.16, type: 'number', unit: '' },
{ label: '血小板计数', val: 'plt', min: 125, max: 350, type: 'number', unit: '10^9/L' },
{ label: '平均血小板体积', val: 'mpv', min: 9.4, max: 12.5, type: 'number', unit: 'fL' },
{ label: '血小板体积分布宽带', val: 'pdw', min: 10, max: 18, type: 'number', unit: 'fL' },
{ label: '大血小板比率', val: 'plcr', min: 0.13, max: 0.43, type: 'number', unit: '' },
{ label: '血小板比积', val: 'pct', min: 0.11, max: 0.28, type: 'number', unit: '%' },
{ label: '中性粒细胞计数', val: 'gr', min: 1.8, max: 6.3, type: 'number', unit: '10^9/L' },
{ label: '中性粒细胞比值', val: 'gr_p', min: 40, max: 75, type: 'number', unit: '%' },
{ label: '淋巴细胞计数', val: 'ly', min: 1.1, max: 3.2, type: 'number', unit: '10^9/L' },
{ label: '淋巴细胞比值', val: 'ly_p', min: 20, max: 50, type: 'number', unit: '%' },
{ label: '单核细胞计数', val: 'mono', min: 3, max: 10, type: 'number', unit: '10^9/L' },
{ label: '单核细胞比值', val: 'mono_p', min: 3, max: 10, type: 'number', unit: '%' },
{ label: '嗜酸粒细胞计数', val: 'eos', min: 0.02, max: 0.52, type: 'number', unit: '10^9/L' },
{ label: '嗜酸睡粒细胞比值', val: 'eos_p', min: 0.4, max: 8, type: 'number', unit: '%' },
{ label: '嗜碱性粒细胞计数', val: 'baso', min: 0, max: 0.06, type: 'number', unit: '10^9/L' },
{ label: '嗜碱性粒细胞比值', val: 'baso_p', min: 0, max: 1, type: 'number', unit: '%' }
]
},
{
label: '肝功三项',
children: [
{ label: '谷丙转氨酶', val: 'alt', min: 0, max: 100, type: 'number', unit: 'U/L' },
{ label: '谷草转氨酶', val: 'ast', min: 15, max: 40, type: 'number', unit: 'U/L' },
{ label: '总胆红素', val: 'tbil', min: 0, max: 100, type: 'number', unit: 'umol/L' },
{ label: '直接胆红素', val: 'dbil', min: 0, max: 100, type: 'number', unit: 'umol/L' }
]
}
], //
fromeDataThre: {
// sbp:'',
// dbp:'',
// fbg:'',
// urea:'',
// cre:'',
// ua:'',
// cvsc:'',
// tc:'',
// tg:'',
// hdl:'',
// ldl:'',
// wbc:'',
// rbc:'',
// hgb:'',
}
}
},
methods: {
changeValue(e, min, max) {
console.log(typeof e.target.value, 'ee----')
if (Number(e.target.value) < min) {
e.target.value = min
} else if (Number(e.target.value) > max) {
e.target.value = max
}
console.log(this.fromData, 'fromData----')
}
}
}
</script>
<style lang="scss" scoped>
.health_collect_three {
padding-bottom: 10px;
.health-card{
margin: 10px 15px 10px;
padding-bottom: 40px;
background: #ffffff;
border-radius: 12px;
.card-big-title{
padding: 10px 0 10px 0;
font-size: 16px;
font-weight: bold;
text-align: center;
}
.merchants_data_box {
padding: 15px 20px 0 20px;
.card-title {
margin-bottom: 10px;
font-size: 16px;
font-weight: bold;
}
.input_box {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10px;
.btn_class{
border: none;
min-width: 50px;
text-align: left;
background: #ffffff;
/*background: #f8f8f8;*/
}
::v-deep.van-button--normal{
padding: 0;
}
::v-deep.van-button__content{
justify-content: start;
}
}
.name_input {
margin-left: 30px;
width: 180px;
height: 35px;
background: #ffffff;
/*background: #f8f8f8;*/
border-radius: 8px;
}
}
.next_button{
width: 260px;
height: 44px;
border-radius: 30px;
margin: 30px auto 0 auto;
/*padding-bottom: 10px;*/
background: linear-gradient(90deg, #8c9bff 0%, #707ffa 100%);
}
}
/*height: 2100px;*/
}
</style>

View File

@ -0,0 +1,205 @@
<template>
<div class="health_collect_two">
<div class="card-box">
<div class="card-big-title">症状资料</div>
<div v-for="(item,index) in healthDetails" :key="index">
<div class="merchants_data_box" v-if="sex === '女' || item.label !== '妇科问题' ? true : false">
<div class="card-title">{{item.label}}</div>
<div class='input_box' v-for="(itemV2,indexV2) in item.children" :key="indexV2">
<div class="font14 color9">{{itemV2.label}}</div>
<van-radio-group v-model="formDataTwo[item.valKey][indexV2]" direction="horizontal">
<van-radio name="0"></van-radio>
<van-radio name="1"></van-radio>
</van-radio-group>
</div>
</div>
</div>
<div class='colorff font16 bold next_button alignment_center' @click="toSave()">提交</div>
</div>
</div>
</template>
<script>
import service from '@/utils/request'
export default {
name: 'HealthCollectTwo',
props: {
sex: {
type: String,
default: ''
},
healthTwo: {
type: Object,
default: null
}
},
data() {
return {
healthDetails: [
{
label: '妇科问题',
valKey: 'problem_women',
children: [
{ label: '月经不调', val: 0 },
{ label: '白带异常', val: 0 },
{ label: '尿频尿急', val: 0 },
{ label: '不孕', val: 0 },
{ label: '小腹胀痛', val: 0 },
{ label: '子宫肌瘤', val: 0 }
]
},
{
label: '肠胃问题',
valKey: 'problem_stamach',
children: [
{ label: '恶心', val: 0 },
{ label: '胃部反酸', val: 0 },
{ label: '胃部疼痛', val: 0 },
{ label: '便秘', val: 0 },
{ label: '腹胀', val: 0 },
{ label: '大便带血', val: 0 },
{ label: '腹泻', val: 0 }
]
},
{
label: '心脏问题',
valKey: 'problem_heart',
children: [
{ label: '心慌', val: 0 },
{ label: '心悸', val: 0 },
{ label: '水肿', val: 0 },
{ label: '胸闷', val: 0 },
{ label: '呼吸急促', val: 0 },
{ label: '头昏', val: 0 },
{ label: '咳嗽', val: 0 },
{ label: '耳鸣', val: 0 },
{ label: '打鼾', val: 0 }
]
},
{
label: '睡眠问题',
valKey: 'problem_sleep',
children: [
{ label: '入睡困难', val: 0 },
{ label: '容易醒', val: 0 },
{ label: '视觉疲劳', val: 0 },
{ label: '反应迟钝', val: 0 },
{ label: '记忆力减退', val: 0 },
{ label: '焦虑', val: 0 },
{ label: '困倦', val: 0 }
]
},
{
label: '免疫力问题',
valKey: 'problem_immune',
children: [
{ label: '呼吸系统不好', val: 0 },
{ label: '鼻炎', val: 0 },
{ label: '腰酸背痛', val: 0 },
{ label: '容易感冒', val: 0 },
{ label: '虚弱无力', val: 0 },
{ label: '没食欲', val: 0 },
{ label: '容易感染', val: 0 },
{ label: '皮肤问题', val: 0 },
{ label: '哮喘', val: 0 }
]
}
],
formDataTwo: {
problem_women: ['0', '0', '0', '0', '0', '0'],
problem_stamach: ['0', '0', '0', '0', '0', '0', '0'],
problem_heart: ['0', '0', '0', '0', '0', '0', '0', '0', '0'],
problem_sleep: ['0', '0', '0', '0', '0', '0', '0', '0'],
problem_immune: ['0', '0', '0', '0', '0', '0', '0', '0', '0']
}
}
},
watch: {
'healthTwo'() {
console.log(this.healthOne, 'this.healthOne---')
this.formDataTwo = this.healthOne
}
},
methods: {
toSave() {
const vm = this
const data = {
problem_women: vm.sex === '女' ? vm.formDataTwo.problem_women : [],
problem_stamach: vm.formDataTwo.problem_stamach,
problem_heart: vm.formDataTwo.problem_heart,
problem_sleep: vm.formDataTwo.problem_sleep,
problem_immune: vm.formDataTwo.problem_immune
}
service.put(`s/h5/health/symptom?order_id=530`, data)
.then(data => {
})
}
}
}
</script>
<style lang="scss" scoped>
.health_collect_two {
padding-bottom: 10px;
.card-box{
margin: 10px 15px 10px;
padding-bottom: 40px;
background: #ffffff;
border-radius: 12px;
.card-big-title{
padding: 10px 0 10px 0;
font-size: 16px;
font-weight: bold;
text-align: center;
}
.merchants_data_box {
padding: 15px 20px 0 20px;
.card-title {
margin-bottom: 10px;
font-size: 16px;
font-weight: bold;
}
.input_box {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10px;
.btn_class{
border: none;
min-width: 50px;
text-align: left;
background: #ffffff;
/*background: #f8f8f8;*/
}
::v-deep.van-button--normal{
padding: 0;
}
::v-deep.van-button__content{
justify-content: start;
}
}
.name_input {
margin-left: 30px;
width: 180px;
height: 35px;
background: #ffffff;
/*background: #f8f8f8;*/
border-radius: 8px;
}
}
.next_button{
width: 260px;
height: 44px;
border-radius: 30px;
margin: 30px auto 0 auto;
/*padding-bottom: 10px;*/
background: linear-gradient(90deg, #8c9bff 0%, #707ffa 100%);
}
}
/*height: 2100px;*/
}
</style>

View File

@ -0,0 +1,502 @@
<template>
<div class="dynamic">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div v-if="photosList.length > 0 && make_friends == 1 && !isLabel">
<div style="height: 10px"></div>
<div class="Single_square_box alignment_left" @click="goToUrl('makingFriendsList')">
<div class="Single_square alignment_left">
<div class="Single_user_box alignment_left" v-for="(item, index) in photosList" :key="index">
<div
class="Single_user_photo backCover"
v-bind:style="{ backgroundImage: 'url(' + item.pic + ')' }"
></div>
</div>
<div style="margin-left: 20px">又有人进入单身广场戳此看看>></div>
</div>
</div>
</div>
<div style="padding-bottom: 110px">
<div>
<div class="moreCourseBox">
<div id="elementLeft">
<div
class="courseBox"
v-for="(item, index) in listLeft"
:key="index"
@click="goToUrlId(item.type, item)"
>
<van-image
fit="cover"
v-if="item.pic"
class="u_lstImg"
:class="item.type == 'video' ? 'sel' : ''"
:src="item.pic"
alt=""
/>
<div class="labelBox" @click.stop="goToLabel(item)" v-if="item.tag">
<div class="labelBoxImg"></div>
<div class="labelBoxText ellipsis_1">{{item.tag.name}}</div>
</div>
<div class="m_lstCt">
<div class="font16 color2a" :class="item.type == 'information' ? 'ellipsis_2' : 'ellipsis_1'">
{{ item.title }}
</div>
<div class="m_lstCt_ta f-fbc">
<div class="f-fc">
<van-image
fit="cover"
class="u_pv_icon"
src="https://image.fulllinkai.com/202111/10/b82efdd72a34150688ead6f1f2a32d79.png"
alt=""
/>
<div class="font13 color9">{{ item.pv }}</div>
</div>
<div class="font12" style="color: #c8c8c8">{{ item.created_at }}</div>
</div>
</div>
<van-image
v-if="item.type == 'video'"
fit="contain"
width="20"
height="20"
class="list_item_icon"
src="https://image.fulllinkai.com/202111/12/50abd53df312139611640b39f35686d7.png"
alt=""
/>
</div>
<div v-if="showLoaded && leftShow && !isLabel" class="courseBox" @click="goToAboutUs">
<van-image
fit="cover"
v-if="$store.state.app.info.avatar"
class="u_lstImg"
:src="$store.state.app.info.avatar"
alt=""
/>
<div class="m_lstCt">
<div class="font16 color2a ellipsis_2">
{{ $store.state.app.info.name }}
</div>
<div class="m_lstCt_ta f-fbc ellipsis_2">
{{ $store.state.app.info.designation }}
</div>
</div>
</div>
</div>
<div id="elementRight">
<div
class="courseBox"
v-for="(item, index) in listRight"
:key="index"
@click="goToUrlId(item.type, item)"
>
<van-image
fit="cover"
v-if="item.pic"
class="u_lstImg"
:class="item.type == 'video' ? 'sel' : ''"
:src="item.pic"
alt=""
/>
<div class="labelBox" @click.stop="goToLabel(item)" v-if="item.tag">
<div class="labelBoxImg"></div>
<div class="labelBoxText ellipsis_1">{{item.tag.name}}</div>
</div>
<div class="m_lstCt">
<div class="font16 color2a" :class="item.type == 'information' ? 'ellipsis_2' : 'ellipsis_1'">
{{ item.title }}
</div>
<div class="m_lstCt_ta f-fbc">
<div class="f-fc">
<van-image
fit="cover"
class="u_pv_icon"
src="https://image.fulllinkai.com/202111/10/b82efdd72a34150688ead6f1f2a32d79.png"
alt=""
/>
<div class="font13 color9">{{ item.pv }}</div>
</div>
<div class="font12" style="color: #c8c8c8">{{ item.created_at }}</div>
</div>
</div>
<van-image
v-if="item.type == 'video'"
fit="contain"
width="20"
height="20"
class="list_item_icon"
src="https://image.fulllinkai.com/202111/12/50abd53df312139611640b39f35686d7.png"
alt=""
/>
</div>
<div v-if="showLoaded && !leftShow && !isLabel" class="courseBox" @click="goToAboutUs">
<van-image
fit="cover"
v-if="$store.state.app.info.avatar"
class="u_lstImg"
:src="$store.state.app.info.avatar"
alt=""
/>
<div class="m_lstCt">
<div class="font16 color2a ellipsis_2">
{{ $store.state.app.info.name }}
</div>
<div class="m_lstCt_ta f-fbc ellipsis_2">
{{ $store.state.app.info.designation }}
</div>
</div>
</div>
</div>
<!-- <div v-if="showLoaded" class="courseBox" @click="goToAboutUs">
<div class="m_lstCt">
<div class="font16 color2a ellipsis_2">{{ $store.state.app.info.name }}</div>
<div class="m_lstCt_ta f-fc">
<div class="font14 color9 ellipsis_2">{{ $store.state.app.info.designation }}</div>
</div>
</div>
<van-image fit="cover" radius="4" class="u_lstImg" :src="$store.state.app.info.avatar" alt="" />
</div> -->
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { formatDate } from '@/plugins/timeConversion'
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
isLabel: {
type: Boolean,
default: false
},
labelId: {
type: String,
default: ''
}
},
data() {
return {
make_friends: '',
merchant_id: false,
list: [],
photosList: [],
listLeft: [],
listRight: [],
page: 1,
pv_time: true,
showLoaded: false,
finished: false,
loading: false,
refreshing: false,
emptyData: true,
noMoreData: false,
leftShow: true,
heightLeft: 0,
heightRight: 0
}
},
watch: {
$route(to, from) {
if (from.name == 'welcome') {
this.page = 1
this.list = []
this.onRefresh()
}
},
list(e) {
if (this.page === 1) {
this.listLeft = []
this.listRight = []
}
if (e.length > 0) {
e.forEach((item, index) => {
this.getOffsetWidth(item)
})
}
}
},
methods: {
goToLabel(item) {
console.log(item, 'item-----')
// return
this.$router.push({
name: 'dynamicClassification',
params: {
id: item.tag.id
}
})
},
goToUrl(url) {
this.$router.push({
name: url
})
},
getOffsetWidth(item) {
const vm = this
setTimeout(() => {
vm.$nextTick(() => {
var listLeft = document.getElementById('elementLeft')
var listRight = document.getElementById('elementRight')
var h_l = listLeft.offsetHeight
var h_r = listRight.offsetHeight
if (h_l < h_r) {
vm.leftShow = false
vm.listLeft.push(item)
} else {
vm.leftShow = true
vm.listRight.push(item)
}
})
vm.showLoaded = true
}, 200)
},
getPhotos() {
const url = `s/h5/friend/photos`
service
.get(url)
.then(data => {
this.photosList = data
})
.catch(error => {
console.log(error)
})
},
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
let url = ''
if (!vm.isLabel) {
url = `/s/h5/video/infor/list?page=${vm.page}`
} else {
url = `/s/h5/tag/informations?page=${vm.page}&tag_id=${vm.labelId}`
}
service
.get(url)
.then(data => {
this.$nextTick(() => {
setTimeout(() => {
this.make_friends = this.$store.state.app.info.make_friends
console.log(this.make_friends)
}, 300)
})
if (data.data.length != 0) {
data.data.forEach(item => {
item.created_at = item.created_at.replace(/-/g, '/')
item.created_at = formatDate(item.created_at, 1)
})
}
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = data.data
// vm.list = dataV
vm.refreshing = false
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
vm.loading = false
$toastClear()
}
vm.page++
setTimeout(() => {
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToAboutUs() {
this.$router.push({
name: 'aboutUs'
})
},
goToUrlId(type, item) {
this.showLoaded = false
if (type == 'information') {
this.$router.push({
name: 'dynamicParticulars',
params: { id: item.id }
})
if (this.pv_time) {
this.pv_time = false
item.pv += 1
}
} else {
if (localStorage.getItem('merchant_id') == '40') {
this.$router.push({
name: 'videoDetailsV2',
params: { id: item.id }
})
return
}
this.$router.push({
name: 'videoDetails',
params: { id: item.id }
})
}
}
},
deactivated() {
this.pv_time = true
},
created() {
},
mounted() {
// document.title = localStorage.getItem('merchant_name') ? localStorage.getItem('merchant_name') + ` · ${this.$i18n.t(localStorage.getItem('informationTitle'))}` : this.$i18n.t(localStorage.getItem('informationTitle'))
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
this.getPhotos()
if (
parseInt(localStorage.getItem('merchant_id')) === 5 ||
parseInt(localStorage.getItem('merchant_id')) === 40 ||
parseInt(localStorage.getItem('merchant_id')) === 596 ||
parseInt(localStorage.getItem('merchant_id')) === 16
) {
this.merchant_id = true
}
}
}
</script>
<style lang="scss" scoped>
.dynamic {
width: 100vw;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.Single_square_box {
margin: 0 15px;
height: 48px;
border-radius: 24px;
background: #f2f3ff;
.Single_square {
margin-left: 15px;
.Single_user_box {
border: 2px solid #ffffff;
margin-right: -10px;
border-radius: 50%;
.Single_user_photo {
width: 24px;
height: 24px;
border-radius: 50%;
}
}
}
}
.moreCourseBox,
.m_abo {
padding: 15px;
display: flex;
justify-content: space-between;
align-items: flex-start;
.courseBox {
width: 168px;
margin-bottom: 12px;
background: #ffffff;
box-shadow: 0px 2px 12px 0px rgba(0, 0, 0, 0.08);
box-sizing: border-box;
border-radius: 8px;
overflow: hidden;
position: relative;
.labelBox{
position: absolute;
top: 101px;
left: 5px;
display: flex;
align-items: center;
padding: 0 0 0 5px;
width: fit-content;
max-width: 90px;
height: 20px;
background: rgba(0, 0, 0, 0.4);
border-radius: 10px;
.labelBoxImg{
/*margin-top: 2px;*/
height:16px;
width: 16px;
background-image: url("https://image.fulllinkai.com/202201/11/5804938d3f57ff3dd581b1a780d80808.png");
background-size: 100% 100%;
background-repeat: no-repeat;
}
.labelBoxText{
flex: 1;
//margin-top: -1px;
margin-left: 4px;
padding-right: 10px;
font-size: 12px;
color: #FFFFFF;
}
}
.list_item_icon {
position: absolute;
right: 10px;
top: 10px;
}
.m_lstCt {
padding: 10px;
box-sizing: border-box;
.m_lstCt_ta {
padding-top: 10px;
.u_pv_icon {
width: 12px;
height: 14px;
margin-right: 3px;
}
}
}
.u_lstImg {
width: 100%;
height: 126px;
}
.u_lstImg.sel {
width: 100%;
height: 224px;
}
}
}
.bottomLine {
padding-top: 20px;
}
</style>
<style>
.van-list {
background-color: white;
}
</style>

View File

@ -0,0 +1,396 @@
<template>
<div class="dynamic">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div v-if="photosList.length > 0 && make_friends == 1 && !isLabel">
<div style="height: 10px"></div>
<div class="Single_square_box alignment_left" @click="goToUrl('makingFriendsList')">
<div class="Single_square alignment_left">
<div class="Single_user_box alignment_left" v-for="(item, index) in photosList" :key="index">
<div
class="Single_user_photo backCover"
v-bind:style="{ backgroundImage: 'url(' + item.pic + ')' }"
></div>
</div>
<div style="margin-left: 20px">又有人进入单身广场戳此看看>></div>
</div>
</div>
</div>
<div style="padding-bottom: 110px">
<div>
<div class="moreCourseBox">
<div class="courseBox" v-for="(item, index) in list" :key="index" @click="goToUrlId(item.type, item)">
<template v-if="item.type == 'video'">
<div class="m_lstCt" :class="item.type == 'video' ? 'sel' : ''">
<van-image fit="cover" radius="8" v-if="item.pic" class="u_lstImg" :src="item.pic" alt="">
<van-image
v-if="item.type == 'video'"
fit="contain"
width="37"
height="37"
class="list_item_icon"
src="https://image.fulllinkai.com/202111/18/e6f98af4037bd884db2ea26111b16fb5.png"
alt=""
/>
</van-image>
<div class="font16 color2a ellipsis_2">{{ item.title }}</div>
<div class="m_lstCt_ta f-fc">
<div class="font12 color9" style="margin-right: 15px">{{ item.created_at }}</div>
<div class="f-fc">
<van-image
fit="cover"
class="u_pv_icon"
src="https://image.fulllinkai.com/202111/10/b82efdd72a34150688ead6f1f2a32d79.png"
alt=""
/>
<div class="font12 color9" style="line-height: 12px; margin-top: 1px">{{ item.pv }}</div>
</div>
</div>
</div>
</template>
<template v-else>
<div class="m_lstCt">
<div class="font16 color2a ellipsis_2 m_1stCt_text">{{ item.title }}</div>
<div class="m_lstCt_ta f-fc">
<div class="labelBox" @click.stop="goToLabel(item)" v-if="item.tag">
<div class="labelBoxImg"></div>
<div class="labelBoxText ellipsis_1">{{item.tag.name}}</div>
</div>
<div class="font12 color9" style="margin-right: 15px">{{ item.created_at }}</div>
<div class="f-fc">
<van-image
fit="cover"
class="u_pv_icon"
src="https://image.fulllinkai.com/202111/10/b82efdd72a34150688ead6f1f2a32d79.png"
alt=""
/>
<div class="font12 color9" style="line-height: 12px; margin-top: 2px">{{ item.pv }}</div>
</div>
</div>
</div>
<van-image fit="cover" radius="8" v-if="item.pic" class="u_lstImg" :src="item.pic" alt="" />
</template>
</div>
<div v-if="showLoaded && !isLabel" class="courseBox" @click="goToAboutUs">
<div class="m_lstCt">
<div class="font16 color2a ellipsis_2">{{ $store.state.app.info.name }}</div>
<div class="m_lstCt_ta f-fc">
<div class="font14 color9 ellipsis_2">{{ $store.state.app.info.designation }}</div>
</div>
</div>
<van-image fit="cover" radius="4" class="u_lstImg" :src="$store.state.app.info.avatar" alt="" />
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { formatDate } from '@/plugins/timeConversion'
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
isLabel: {
type: Boolean,
default: false
},
labelId: {
type: String,
default: ''
}
},
data() {
return {
make_friends: '',
merchant_id: false,
list: [],
photosList: [],
page: 1,
pv_time: true,
showLoaded: false,
finished: false,
loading: false,
refreshing: false,
emptyData: true,
noMoreData: false
}
},
watch: {
$route(to, from) {
if (from.name == 'welcome') {
this.onRefresh()
}
}
},
methods: {
goToLabel(item) {
console.log(item, 'item-----')
// return
this.$router.push({
name: 'dynamicClassification',
params: {
id: item.tag.id
}
})
},
goToUrl(url) {
this.$router.push({
name: url
})
},
getPhotos() {
const url = `s/h5/friend/photos`
service
.get(url)
.then(data => {
this.photosList = data
})
.catch(error => {
console.log(error)
})
},
getList() {
const vm = this
console.log(vm.labelId, 'id')
$toastLoading(vm.$i18n.t('loading_text'))
let url = ''
console.log(vm.isLabel, '798798789789')
if (!vm.isLabel) {
url = `/s/h5/video/infor/list?page=${vm.page}`
} else {
url = `/s/h5/tag/informations?page=${vm.page}&tag_id=${vm.labelId}`
}
service
.get(url)
.then(data => {
if (data.data.length != 0) {
data.data.forEach(item => {
item.created_at = item.created_at.replace(/-/g, '/')
item.created_at = formatDate(item.created_at, 1)
})
}
this.$nextTick(() => {
setTimeout(() => {
this.make_friends = this.$store.state.app.info.make_friends
console.log(this.make_friends)
}, 300)
})
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
vm.showLoaded = true
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
vm.loading = false
$toastClear()
}
vm.page++
setTimeout(() => {
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToAboutUs() {
this.$router.push({
name: 'aboutUs'
})
},
goToUrlId(type, item) {
if (type == 'information') {
this.$router.push({
name: 'dynamicParticulars',
params: { id: item.id }
})
if (this.pv_time) {
this.pv_time = false
item.pv += 1
}
} else {
if (localStorage.getItem('merchant_id') == '40') {
this.$router.push({
name: 'videoDetailsV2',
params: { id: item.id }
})
return
}
this.$router.push({
name: 'videoDetails',
params: { id: item.id }
})
}
}
},
deactivated() {
this.pv_time = true
},
created() {
},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
this.getPhotos()
if (
parseInt(localStorage.getItem('merchant_id')) === 5 ||
parseInt(localStorage.getItem('merchant_id')) === 40 ||
parseInt(localStorage.getItem('merchant_id')) === 596 ||
parseInt(localStorage.getItem('merchant_id')) === 17
) {
this.merchant_id = true
}
}
}
</script>
<style lang="scss" scoped>
.dynamic {
width: 100vw;
background: #ffffff;
position: relative;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.Single_square_box {
margin: 0 15px;
height: 48px;
border-radius: 24px;
background: #f2f3ff;
.Single_square {
margin-left: 15px;
.Single_user_box {
border: 2px solid #ffffff;
margin-right: -10px;
border-radius: 50%;
.Single_user_photo {
width: 24px;
height: 24px;
border-radius: 50%;
}
}
}
}
.moreCourseBox,
.m_abo {
margin: 0 15px;
.courseBox {
padding: 18px 0 15px;
background: #ffffff;
box-sizing: border-box;
display: flex;
align-items: stretch;
border-bottom: 1px solid #f5f5f5;
}
.m_lstCt {
flex: 1;
height: auto;
display: flex;
flex-direction: column;
justify-content: space-between;
.m_1stCt_text{
padding-right: 10px;
}
.m_lstCt_ta {
padding-top: 10px;
.labelBox{
margin-right: 15px;
display: flex;
align-items: center;
padding: 0 0 0 2px;
width: fit-content;
max-width: 90px;
height: 20px;
background: #F2F3FF;
border-radius: 10px;
.labelBoxImg{
height:16px;
width: 16px;
background-image: url("https://image.fulllinkai.com/202201/10/7157a900bbc62721dc89f49d092f83e6.png");
background-size: 100% 100%;
background-repeat: no-repeat;
}
.labelBoxText{
flex: 1;
margin-left: 4px;
padding-right: 10px;
font-size: 12px;
color:#707FFA;
}
}
}
}
.m_lstCt.sel {
display: block;
.u_lstImg {
width: 100%;
height: 194px;
margin-bottom: 10px;
position: relative;
.list_item_icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
}
.u_lstImg {
/*padding-left: 4px;*/
/*margin-left: 10px;*/
width: 104px;
height: 78px;
}
}
.bottomLine {
padding-top: 20px;
}
.u_pv_icon {
width: 12px;
height: 14px;
margin-right: 3px;
}
</style>
<style>
.van-list {
background-color: white;
}
</style>

View File

@ -0,0 +1,307 @@
<template>
<div class="dynamic">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div v-if='photosList.length > 0 && make_friends == 1 && !isLabel'>
<div style='height: 10px'></div>
<div class='Single_square_box alignment_left' @click='goToUrl("makingFriendsList")'>
<div class='Single_square alignment_left'>
<div class='Single_user_box alignment_left' v-for='(item,index) in photosList' :key='index'>
<div class='Single_user_photo backCover' v-bind:style="{ backgroundImage: 'url(' + item.pic + ')' }"></div>
</div>
<div style='margin-left: 20px'>又有人进入单身广场戳此看看>></div>
</div>
</div>
</div>
<div style="padding-bottom: 110px">
<div>
<div class="moreCourseBox">
<div
class="courseBox"
v-for="(item, index) in list"
:key="index"
@click="goToUrlId(`dynamicParticulars`, item.id)"
>
<van-image fit="cover" radius="4" v-if="item.pic" class="u_lstImg" :src="item.pic" alt="" />
<div class="m_lstCt">
<div class="font16 color2a ellipsis_2">{{ item.title }}</div>
<div class="m_lstCt_ta f-fc">
<div class="labelBox" @click.stop="goToLabel(item)" v-if="item.tag">
<div class="labelBoxImg"></div>
<div class="labelBoxText ellipsis_1">{{item.tag.name}}</div>
</div>
<div class="font12 color9" style="margin-right: 15px;">{{ item.created_at }}</div>
<div class="font12 color9">{{ $t('pv') }}{{ item.pv }}</div>
</div>
</div>
</div>
<div class="m_abo">
<!-- <img
class="emptyDataIcon"
src="https://image.fulllinkai.com/202108/23/939c529ca16a91e3ee3b22bef2fe92ca.png"
alt=""
/>
<div class="color9 font14" style="margin-top: 14px">{{ $t('Temporarily_no_data') }}</div> -->
<div v-if="showLoaded && !isLabel" class="courseBox" @click="goToAboutUs">
<van-image fit="cover" radius="4" class="u_lstImg" :src="$store.state.app.info.avatar" alt="" />
<div class="m_lstCt">
<div class="font16 color2a ellipsis_2">{{ $store.state.app.info.name }}</div>
<div class="font14 color9 ellipsis_2">{{ $store.state.app.info.designation }}</div>
</div>
</div>
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { formatDate } from '@/plugins/timeConversion'
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
isLabel: {
type: Boolean,
default: false
},
labelId: {
type: String,
default: ''
}
},
data() {
return {
make_friends: '',
merchant_id: false,
list: [],
photosList: [],
page: 1,
showLoaded: false,
finished: false,
loading: false,
refreshing: false,
emptyData: true,
noMoreData: false
}
},
watch: {
$route(to, from) {
if (from.name == 'dynamicParticulars' || from.name == 'welcome') {
this.onRefresh()
}
}
},
methods: {
goToLabel(item) {
console.log(item, 'item-----')
// return
this.$router.push({
name: 'dynamicClassification',
params: {
id: item.tag.id
}
})
},
goToUrl(url) {
this.$router.push({
name: url
})
},
getPhotos() {
const url = `s/h5/friend/photos`
service.get(url).then(data => {
this.photosList = data
}).catch(error => {
console.log(error)
})
},
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
let url = ''
if (!vm.isLabel) {
url = `/s/h5/video/infor/list?page=${vm.page}`
} else {
url = `/s/h5/tag/informations?page=${vm.page}&tag_id=${vm.labelId}`
}
service
.get(url)
.then(data => {
if (data.data.length != 0) {
data.data.forEach(item => {
item.created_at = item.created_at.replace(/-/g, '/')
item.created_at = formatDate(item.created_at, 1)
})
}
this.$nextTick(() => {
setTimeout(() => {
this.make_friends = this.$store.state.app.info.make_friends
console.log(this.make_friends)
}, 300)
})
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
vm.showLoaded = true
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
vm.loading = false
$toastClear()
}
vm.page++
setTimeout(() => {
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToAboutUs() {
this.$router.push({
name: 'aboutUs'
})
},
goToUrlId(url, id) {
this.$router.push({
name: url,
params: { id: id }
})
}
},
created() {
},
mounted() {
// document.title = localStorage.getItem('merchant_name') ? localStorage.getItem('merchant_name') + ` · ${this.$i18n.t(localStorage.getItem('informationTitle'))}` : this.$i18n.t(localStorage.getItem('informationTitle'))
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
this.getPhotos()
if (parseInt(localStorage.getItem('merchant_id')) === 5 || parseInt(localStorage.getItem('merchant_id')) === 40 || parseInt(localStorage.getItem('merchant_id')) === 596 || parseInt(localStorage.getItem('merchant_id')) === 16) {
this.merchant_id = true
}
}
}
</script>
<style lang="scss" scoped>
.dynamic {
width: 100vw;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.Single_square_box{
margin: 0 15px;
height: 48px;
border-radius: 24px;
background: #f2f3ff;
.Single_square{
margin-left: 15px;
.Single_user_box{
border: 2px solid #ffffff;
margin-right: -10px;
border-radius: 50%;
.Single_user_photo{
width: 24px;
height: 24px;
border-radius: 50%;
}
}
}
}
.moreCourseBox,
.m_abo {
.courseBox {
padding: 15px 10px;
background: #ffffff;
border-radius: 8px;
box-sizing: border-box;
display: flex;
align-items: stretch;
border-bottom: 1px solid #f5f5f5;
.m_lstCt {
padding-left: 10px;
flex: 1;
height: auto;
display: flex;
flex-direction: column;
justify-content: space-between;
.m_lstCt_ta {
padding-top: 10px;
.labelBox{
margin-right: 15px;
display: flex;
align-items: center;
padding: 0 10px 0 2px;
width: fit-content;
max-width: 90px;
height: 20px;
background: #F2F3FF;
border-radius: 10px;
line-height: 20px;
.labelBoxImg{
height:16px;
width: 16px;
background-image: url("https://image.fulllinkai.com/202201/10/7157a900bbc62721dc89f49d092f83e6.png");
background-size: 100% 100%;
background-repeat: no-repeat;
}
.labelBoxText{
flex: 1;
margin-left: 4px;
}
}
}
}
.u_lstImg {
width: 112px;
height: 84px;
}
}
}
.bottomLine {
padding-top: 20px;
}
</style>
<style>
.van-list {
background-color: white;
}
</style>

View File

@ -0,0 +1,393 @@
<template>
<div class="dynamic">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div v-if="photosList.length > 0 && make_friends == 1 && !isLabel">
<div style="height: 10px"></div>
<div class="Single_square_box alignment_left" @click="goToUrl('makingFriendsList')">
<div class="Single_square alignment_left">
<div class="Single_user_box alignment_left" v-for="(item, index) in photosList" :key="index">
<div
class="Single_user_photo backCover"
v-bind:style="{ backgroundImage: 'url(' + item.pic + ')' }"
></div>
</div>
<div style="margin-left: 20px">又有人进入单身广场戳此看看>></div>
</div>
</div>
</div>
<div style="padding-bottom: 110px">
<div>
<div class="moreCourseBox">
<div class="courseBox" v-for="(item, index) in list" :key="index" @click="goToUrlId(item.type, item)">
<template v-if="item.type == 'video'">
<div class="m_lstCt" :class="item.type == 'video' ? 'sel' : ''">
<van-image fit="cover" radius="8" v-if="item.pic" class="u_lstImg" :src="item.pic" alt="">
<van-image
v-if="item.type == 'video'"
fit="contain"
width="37"
height="37"
class="list_item_icon"
src="https://image.fulllinkai.com/202111/18/e6f98af4037bd884db2ea26111b16fb5.png"
alt=""
/>
</van-image>
<div class="font16 color2a ellipsis_2">{{ item.title }}</div>
<div class="m_lstCt_ta f-fc">
<div class="font12 color9" style="margin-right: 15px">{{ item.created_at }}</div>
<div class="f-fc">
<van-image
fit="cover"
class="u_pv_icon"
src="https://image.fulllinkai.com/202111/10/b82efdd72a34150688ead6f1f2a32d79.png"
alt=""
/>
<div class="font12 color9" style="line-height: 12px; margin-top: 2px">{{ item.pv }}</div>
</div>
</div>
</div>
</template>
<template v-else>
<div class="m_lstCt">
<div class="font16 color2a ellipsis_2 m_1stCt_text">{{ item.title }}</div>
<div class="m_lstCt_ta f-fc">
<div class="labelBox" @click.stop="goToLabel(item)" v-if="item.tag">
<div class="labelBoxImg"></div>
<div class="labelBoxText ellipsis_1">{{item.tag.name}}</div>
</div>
<div class="font12 color9" style="margin-right: 15px">{{ item.created_at }}</div>
<div class="f-fc">
<van-image
fit="cover"
class="u_pv_icon"
src="https://image.fulllinkai.com/202111/10/b82efdd72a34150688ead6f1f2a32d79.png"
alt=""
/>
<div class="font12 color9" style="line-height: 12px; margin-top: 2px">{{ item.pv }}</div>
</div>
</div>
</div>
<van-image fit="cover" radius="8" v-if="item.pic" class="u_lstImg" :src="item.pic" alt="" />
</template>
</div>
<div v-if="showLoaded && !isLabel" class="courseBox" @click="goToAboutUs">
<div class="m_lstCt">
<div class="font16 color2a ellipsis_2">{{ $store.state.app.info.name }}</div>
<div class="m_lstCt_ta f-fc">
<div class="font14 color9 ellipsis_2">{{ $store.state.app.info.designation }}</div>
</div>
</div>
<van-image fit="cover" radius="4" class="u_lstImg" :src="$store.state.app.info.avatar" alt="" />
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { formatDate } from '@/plugins/timeConversion'
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
isLabel: {
type: Boolean,
default: false
},
labelId: {
type: String,
default: ''
}
},
data() {
return {
make_friends: '',
merchant_id: false,
list: [],
photosList: [],
page: 1,
pv_time: true,
showLoaded: false,
finished: false,
loading: false,
refreshing: false,
emptyData: true,
noMoreData: false
}
},
watch: {
$route(to, from) {
if (from.name == 'welcome') {
this.onRefresh()
}
}
},
methods: {
goToLabel(item) {
console.log(item, 'item-----')
// return
this.$router.push({
name: 'dynamicClassification',
params: {
id: item.tag.id
}
})
},
getPhotos() {
const url = `s/h5/friend/photos`
service
.get(url)
.then(data => {
this.photosList = data
})
.catch(error => {
console.log(error)
})
},
goToUrl(url) {
this.$router.push({
name: url
})
},
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
let url = ''
if (!vm.isLabel) {
url = `/s/h5/video/infor/list?page=${vm.page}`
} else {
url = `/s/h5/tag/informations?page=${vm.page}&tag_id=${vm.labelId}`
}
service
.get(url)
.then(data => {
this.$nextTick(() => {
setTimeout(() => {
this.make_friends = this.$store.state.app.info.make_friends
console.log(this.make_friends)
}, 300)
})
if (data.data.length != 0) {
data.data.forEach(item => {
item.created_at = item.created_at.replace(/-/g, '/')
item.created_at = formatDate(item.created_at, 1)
})
}
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
vm.showLoaded = true
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
vm.loading = false
$toastClear()
}
vm.page++
setTimeout(() => {
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToAboutUs() {
this.$router.push({
name: 'aboutUs'
})
},
goToUrlId(type, item) {
if (type == 'information') {
this.$router.push({
name: 'dynamicParticulars',
params: { id: item.id }
})
if (this.pv_time) {
this.pv_time = false
item.pv += 1
}
} else {
if (localStorage.getItem('merchant_id') == '40') {
this.$router.push({
name: 'videoDetailsV2',
params: { id: item.id }
})
return
}
this.$router.push({
name: 'videoDetails',
params: { id: item.id }
})
}
}
},
deactivated() {
this.pv_time = true
},
created() {
},
mounted() {
// document.title = localStorage.getItem('merchant_name') ? localStorage.getItem('merchant_name') + ` · ${this.$i18n.t(localStorage.getItem('informationTitle'))}` : this.$i18n.t(localStorage.getItem('informationTitle'))
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
this.getPhotos()
if (
parseInt(localStorage.getItem('merchant_id')) === 5 ||
parseInt(localStorage.getItem('merchant_id')) === 40 ||
parseInt(localStorage.getItem('merchant_id')) === 596 ||
parseInt(localStorage.getItem('merchant_id')) === 16
) {
this.merchant_id = true
}
}
}
</script>
<style lang="scss" scoped>
.dynamic {
width: 100vw;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.Single_square_box {
margin: 0 15px;
height: 48px;
border-radius: 24px;
background: #f2f3ff;
.Single_square {
margin-left: 15px;
.Single_user_box {
border: 2px solid #ffffff;
margin-right: -10px;
border-radius: 50%;
.Single_user_photo {
width: 24px;
height: 24px;
border-radius: 50%;
}
}
}
}
.moreCourseBox,
.m_abo {
padding: 15px 15px 0;
.courseBox {
padding: 12px 10px;
background: #ffffff;
border-radius: 8px;
box-sizing: border-box;
display: flex;
align-items: stretch;
box-shadow: 0px 2px 12px 0px rgba(0, 0, 0, 0.08);
margin-bottom: 15px;
}
.m_lstCt {
flex: 1;
height: auto;
display: flex;
flex-direction: column;
justify-content: space-between;
.m_1stCt_text{
padding-right: 10px;
}
.m_lstCt_ta {
padding-top: 10px;
.labelBox{
margin-right: 15px;
display: flex;
align-items: center;
padding: 0 0 0 2px;
width: fit-content;
max-width: 90px;
height: 20px;
background: #F2F3FF;
border-radius: 10px;
.labelBoxImg{
height:16px;
width: 16px;
background-image: url("https://image.fulllinkai.com/202201/10/7157a900bbc62721dc89f49d092f83e6.png");
background-size: 100% 100%;
background-repeat: no-repeat;
}
.labelBoxText{
flex: 1;
margin-left: 4px;
padding-right: 10px;
font-size: 12px;
color:#707FFA;
}
}
}
}
.u_lstImg {
width: 104px;
height: 78px;
}
}
.m_lstCt.sel {
display: block;
.u_lstImg {
width: 100%;
height: 194px;
margin-bottom: 10px;
position: relative;
.list_item_icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
}
.bottomLine {
padding-top: 20px;
}
.u_pv_icon {
width: 12px;
height: 14px;
margin-right: 3px;
}
</style>
<style>
.van-list {
background-color: white;
}
</style>

View File

@ -0,0 +1,264 @@
<template>
<div class="mallList">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div style="padding-bottom: 110px">
<div class="text-center" style="padding: 170px 0" v-if="!emptyData">
<img
class="emptyDataIcon"
src="https://image.fulllinkai.com/202108/23/939c529ca16a91e3ee3b22bef2fe92ca.png"
alt=""
/>
<div class="color9 font14" style="margin-top: 14px">{{ $t('Temporarily_no_data') }}</div>
</div>
<div v-else>
<div class="moreCourseBox f-fbc wrap">
<div
class="courseBox"
v-for="(item, index) in list"
:key="index"
@click="goToUrlId(`mallDetail`, item.id)"
>
<div class="">
<div class="f-fcc">
<div class="mallPic backCover" v-bind:style="{ backgroundImage: 'url(' + item.icon + ')' }"></div>
</div>
<div class="m_lst_ri">
<div class="font14 color3 bold ellipsis_1 mall-title">
<div class="group-icon backCover" v-if="item.is_group"></div>
<div class="font14 color3 bold ellipsis_1 mall-text">{{ item.title }}</div>
</div>
<div style="padding: 4px 0 11px 0">
<div class="font12 color9 ellipsis_1">
{{ item.sub_title }}
</div>
</div>
<div class="f-fbc">
<div class="coursePrice bold font16 ellipsis_1">
<span v-if="item.price != 0"></span>
<span>{{ item.price == 0? $t('free') : item.price }}</span>
</div>
<div class="signUp f-fcc font12 colorff">购买</div>
</div>
</div>
</div>
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
<div style="height: 50px;"></div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
url: {
type: String,
default: null
}
},
data() {
return {
list: [],
page: 1,
loading: false,
finished: false,
refreshing: false,
emptyData: true,
noMoreData: false
}
},
watch: {},
methods: {
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
service
.get(`${vm.url}?page=${vm.page}`)
.then(data => {
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
$toastClear()
}
vm.loading = false
vm.page++
setTimeout(() => {
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.loading = true
this.finished = false
this.getList()
},
goToUrlId(url, id) {
this.$router.push({
name: url,
params: { id: id }
})
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
}
}
</script>
<style lang="scss" scoped>
.mallList {
height: calc(100vh - 44px) !important;
}
.van-tab__pane {
width: 100vw;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.moreCourseBox {
margin: 0 15px;
box-sizing: border-box;
.courseBox {
width: calc(50% - 6px);
margin: 15px 0;
background: #ffffff;
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.1);
border-radius: 12px;
overflow: hidden;
box-sizing: border-box;
.mallPic {
width: 166px;
height: 166px;
border-radius: 12px 12px 0 0;
}
.m_lst_ri {
padding: 8px 10px 15px 10px;
flex: 1;
height: auto;
display: flex;
flex-direction: column;
justify-content: space-between;
.mall-title{
display: flex;
align-items: center;
margin-bottom: 5px;
.mall-text{
width: 120px;
}
.group-icon{
margin-right: 4px;
width: 32px;
height: 16px;
background-image: url("https://image.fulllinkai.com/202211/15/631d937276380af19ec646cf7563a64a.png");
}
}
.signUp {
width: 50px;
height: 24px;
background: linear-gradient(90deg, #8c9bff 0%, #707ffa 100%);
border-radius: 100px;
display: flex;
justify-content: center;
align-items: center;
}
}
.coursePic {
flex: none;
width: 142px;
height: 80px;
margin-right: 10px;
border-radius: 8px;
position: relative;
.preferential {
position: absolute;
top: 0;
left: 0;
background: #ffac4a;
display: flex;
justify-content: center;
align-items: center;
padding: 0 5px;
height: 17px;
border-radius: 8px 0;
}
}
.coursePrice {
color: #ffac4a;
//max-width: 76px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.originalPrice {
text-decoration: line-through;
margin-left: 5px;
position: relative;
top: -1px;
}
}
.joinButton,
.joinCourseV2 {
position: absolute;
right: 15px;
bottom: 20px;
width: 78px;
height: 28px;
border-radius: 15px;
border: 1px solid #ffac4a;
}
.joinCourseV2 {
border: 1px solid #c2c2c2;
}
}
}
.bottomLine {
padding-top: 20px;
}
</style>
<style lang="scss">
.van-tab__pane {
width: 100%;
min-height: 100%;
background: #ffffff;
}
</style>

View File

@ -0,0 +1,258 @@
<template>
<div class="mallList">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div style="padding-bottom: 110px">
<div class="text-center" style="padding: 170px 0" v-if="!emptyData">
<img
class="emptyDataIcon"
src="https://image.fulllinkai.com/202108/23/939c529ca16a91e3ee3b22bef2fe92ca.png"
alt=""
/>
<div class="color9 font14" style="margin-top: 14px">{{ $t('Temporarily_no_data') }}</div>
</div>
<div v-else>
<div class="moreCourseBox">
<div
class="courseBox"
v-for="(item, index) in list"
:key="index"
@click="goToUrlId(`mallDetail`, item.id)"
>
<div class="f-fs">
<van-image class="" width="108" height="108" radius="8" fit="cover" :src="item.icon" />
<div class="m_lst_ri">
<div>
<div
class="font14 color3 bold ellipsis_2 mall-title"
>
<div class="group-icon backCover" v-if="item.is_group"></div>
{{ item.title }}
</div>
<div
class="font12 color9 ellipsis_1"
style="max-width: 220px;margin-top: 4px;word-wrap: break-word;word-break: break-all"
>
{{ item.sub_title }}
</div>
</div>
<div class="f-fbc">
<div class="coursePrice bold font18">
<span v-if="item.price != 0"></span>
<span>{{ item.price == 0? $t('free') : item.price }}</span>
</div>
<div class="signUp f-fcc font13 colorff">{{ $t('Buy_now') }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
<div style="height: 50px;"></div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
url: {
type: String,
default: null
}
},
data() {
return {
list: [],
page: 1,
loading: false,
finished: false,
refreshing: false,
emptyData: true,
noMoreData: false
}
},
watch: {},
methods: {
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
service
.get(`${vm.url}?page=${vm.page}`)
.then(data => {
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
$toastClear()
}
vm.loading = false
vm.page++
setTimeout(() => {
vm.loading = true
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.loading = true
this.finished = false
this.getList()
},
goToUrlId(url, id) {
this.$router.push({
name: url,
params: { id: id }
})
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
}
}
</script>
<style lang="scss" scoped>
.mallList {
height: calc(100vh - 44px) !important;
}
.van-tab__pane {
width: 100vw;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.moreCourseBox {
padding: 0 15px;
.courseBox {
padding: 15px 0;
border-bottom: 1px solid #f5f5f5;
background: #ffffff;
overflow: hidden;
.m_lst_ri {
flex: 1;
height: auto;
display: flex;
flex-direction: column;
justify-content: space-between;
margin-left: 12px;
.mall-title{
word-wrap: break-word;
word-break: break-all;
}
.group-icon{
float: left;
margin-top: 2px;
margin-right: 4px;
width: 32px;
height: 16px;
background-image: url("https://image.fulllinkai.com/202211/15/631d937276380af19ec646cf7563a64a.png");
}
.signUp {
width: 80px;
height: 28px;
background: linear-gradient(90deg, #8c9bff 0%, #707ffa 100%);
border-radius: 100px;
display: flex;
justify-content: center;
align-items: center;
}
}
.coursePic {
flex: none;
width: 142px;
height: 80px;
margin-right: 10px;
border-radius: 8px;
position: relative;
.preferential {
position: absolute;
top: 0;
left: 0;
background: #ffac4a;
display: flex;
justify-content: center;
align-items: center;
padding: 0 5px;
height: 17px;
border-radius: 8px 0;
}
}
.coursePrice {
color: #ffac4a;
max-width: 80px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.originalPrice {
text-decoration: line-through;
margin-left: 5px;
position: relative;
top: -1px;
}
}
.joinButton,
.joinCourseV2 {
position: absolute;
right: 15px;
bottom: 20px;
width: 78px;
height: 28px;
border-radius: 15px;
border: 1px solid #ffac4a;
}
.joinCourseV2 {
border: 1px solid #c2c2c2;
}
}
}
.bottomLine {
padding-top: 20px;
}
</style>
<style lang="scss">
.van-tab__pane {
width: 100%;
min-height: 100%;
background: #ffffff;
}
</style>

View File

@ -0,0 +1,282 @@
<template>
<div class="mallList">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div :style="quoteText == 'mySignUp' ? '' : 'padding-bottom: 110px'">
<div class="text-center" style="padding: 170px 0" v-if="!emptyData">
<img
class="emptyDataIcon"
src="https://image.fulllinkai.com/202108/23/939c529ca16a91e3ee3b22bef2fe92ca.png"
alt=""
/>
<div class="color9 font14" style="margin-top: 14px">{{ $t('Temporarily_no_data') }}</div>
</div>
<div v-else>
<div class="moreCourseBox">
<div
class="courseBox"
v-for="(item, index) in list"
:key="index"
@click="goToUrlId(`mallDetail`, item.id)"
>
<div v-if="quoteText == 'mySignUp'" class="m_tips f-fcc">60{{ $t('minute') }}</div>
<div class="f-fs">
<van-image radius="8" width="108" height="108" fit="cover" :src="item.icon" />
<div class="m_lst_ri">
<div>
<div class="f-fbc">
<div
class="font14 color3 bold ellipsis_2 mall-title"
>
<div class="group-icon backCover" v-if="item.is_group"></div>
{{ item.title }}
</div>
</div>
<div
class="font12 color9 ellipsis_1"
style="max-width: 190px;margin-top: 4px;word-wrap: break-word;word-break: break-all"
>
{{ item.sub_title }}
</div>
</div>
<div class="f-fbc">
<div class="coursePrice bold font18">
<span v-if="item.price != 0"></span>
<span>{{ item.price == 0? $t('free') : item.price }}</span>
</div>
<div class="signUp f-fcc font13 colorff">{{ $t('Buy_now') }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
<div style="height: 50px;"></div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
url: {
type: String,
default: null
},
quoteText: {
type: String,
default: null
}
},
data() {
return {
list: [],
page: 1,
loading: false,
finished: false,
refreshing: false,
emptyData: true,
noMoreData: false
}
},
watch: {},
methods: {
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
service
.get(`${vm.url}?page=${vm.page}`)
.then(data => {
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
$toastClear()
}
vm.loading = false
vm.page++
setTimeout(() => {
vm.loading = true
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.loading = true
this.finished = false
this.getList()
},
goToUrlId(url, id) {
this.$router.push({
name: url,
params: { id: id }
})
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
}
}
</script>
<style lang="scss" scoped>
.mallList {
height: calc(100vh - 44px) !important;
}
.van-tab__pane {
width: 100vw;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.moreCourseBox {
margin: 0 15px;
.courseBox {
padding: 17px 15px 17px 20px;
margin: 15px 0;
background: #ffffff;
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.1);
border-radius: 8px;
overflow: hidden;
position: relative;
.m_tips {
position: absolute;
left: 0;
top: 0;
background: #f2f3ff;
border-radius: 8px 0px 8px 0px;
font-size: 11px;
color: #707ffa;
line-height: 16px;
width: 50px;
height: 20px;
}
.m_lst_ri {
flex: 1;
height: auto;
display: flex;
flex-direction: column;
justify-content: space-between;
margin-left: 12px;
.mall-title{
max-width: 190px;
word-wrap: break-word;
word-break: break-all;
}
.group-icon{
float: left;
margin-top: 2px;
margin-right: 4px;
width: 32px;
height: 16px;
background-image: url("https://image.fulllinkai.com/202211/15/631d937276380af19ec646cf7563a64a.png");
}
.signUp {
background: linear-gradient(90deg, #8c9bff 0%, #707ffa 100%);
border-radius: 100px;
padding: 5px 14px;
display: flex;
justify-content: center;
align-items: center;
}
.signUp.sel {
background: linear-gradient(90deg, #ffc67a 0%, #ffb14a 100%);
}
}
.coursePic {
flex: none;
width: 142px;
height: 80px;
margin-right: 10px;
border-radius: 8px;
position: relative;
.preferential {
position: absolute;
top: 0;
left: 0;
background: #ffac4a;
display: flex;
justify-content: center;
align-items: center;
padding: 0 5px;
height: 17px;
border-radius: 8px 0;
}
}
.coursePrice {
color: #ffac4a;
max-width: 80px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.originalPrice {
text-decoration: line-through;
margin-left: 5px;
position: relative;
top: -1px;
}
}
.joinButton,
.joinCourseV2 {
position: absolute;
right: 15px;
bottom: 20px;
width: 78px;
height: 28px;
border-radius: 15px;
border: 1px solid #ffac4a;
}
.joinCourseV2 {
border: 1px solid #c2c2c2;
}
}
}
.bottomLine {
padding-top: 20px;
}
</style>
<style lang="scss">
.van-tab__pane {
width: 100%;
min-height: 100%;
background: #ffffff;
}
</style>

View File

@ -0,0 +1,265 @@
<template>
<div class="courseList">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList" style="overflow: auto;">
<div :style="quoteText == 'mySignUp' ? '' : 'padding-bottom: 110px'">
<div class="text-center" style="padding: 170px 0" v-if="!emptyData">
<img
class="emptyDataIcon"
src="https://image.fulllinkai.com/202108/23/939c529ca16a91e3ee3b22bef2fe92ca.png"
alt=""
/>
<div class="color9 font14" style="margin-top: 14px">{{ $t('Temporarily_no_data') }}</div>
</div>
<div v-else>
<div class="moreCourseBox">
<div
class="courseBox"
v-for="(item, index) in list"
:key="index"
@click="goToUrlId(`consultingDetail`, item.id)"
>
<div v-if="quoteText == 'mySignUp'" class="m_tips f-fcc">60{{ $t('minute') }}</div>
<div class="f-fs">
<van-image class="" width="100" height="100" round fit="cover" :src="item.pic" />
<div class="m_lst_ri">
<div>
<div class="f-fbc">
<div class="font14 color3 bold ellipsis_2" style="max-width: 200px">
{{ item.title }}
</div>
</div>
<div class="font12 color9 ellipsis_1" style="max-width: 160px;margin-top: 4px;">
{{ $t('Voice_consultation') }} {{ item.name }}
</div>
</div>
<div class="f-fbc">
<div class="coursePrice bold font18">
<span style="margin-left: -2px">{{ item.price || 0 }}</span>
</div>
<div class="signUp sel f-fcc font13 colorff" v-if="quoteText == 'mySignUp' && index == 2">
{{ $t('evaluation') }}
</div>
<div class="signUp sel f-fcc font13 colorff" v-else-if="quoteText == 'mySignUp' && index == 3">
{{ $t('See_the_evaluation') }}
</div>
<div class="signUp f-fcc font13 colorff" v-else>{{ $t('Voice_consultation') }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
<div style="height: 50px;"></div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
url: {
type: String,
default: null
},
quoteText: {
type: String,
default: null
}
},
data() {
return {
list: [],
page: 1,
finished: false,
loading: false,
refreshing: false,
emptyData: true,
noMoreData: false
}
},
watch: {},
methods: {
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
service
.get(`${vm.url}?page=${vm.page}`)
.then(data => {
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
$toastClear()
}
vm.page++
vm.loading = false
setTimeout(() => {
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToUrlId(url, id) {
this.$router.push({
name: url,
params: { id: id }
})
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
}
}
</script>
<style lang="scss" scoped>
.courseList {
height: 100vh;
}
.van-tab__pane {
width: 100vw;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.moreCourseBox {
margin: 0 15px;
.courseBox {
padding: 17px 15px 17px 20px;
margin: 15px 0;
background: #ffffff;
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.1);
border-radius: 8px;
overflow: hidden;
position: relative;
.m_tips {
position: absolute;
left: 0;
top: 0;
background: #f2f3ff;
border-radius: 8px 0px 8px 0px;
font-size: 11px;
color: #707ffa;
line-height: 16px;
width: 50px;
height: 20px;
}
.m_lst_ri {
flex: 1;
height: auto;
display: flex;
flex-direction: column;
justify-content: space-between;
margin-left: 12px;
.signUp {
background: linear-gradient(90deg, #8c9bff 0%, #707ffa 100%);
border-radius: 100px;
padding: 5px 14px;
line-height: 18px;
}
.signUp.sel {
background: linear-gradient(90deg, #ffc67a 0%, #ffb14a 100%);
}
}
.coursePic {
flex: none;
width: 142px;
height: 80px;
margin-right: 10px;
border-radius: 8px;
position: relative;
.preferential {
position: absolute;
top: 0;
left: 0;
background: #ff4a4c;
display: flex;
justify-content: center;
align-items: center;
padding: 0 5px;
height: 17px;
border-radius: 8px 0;
}
}
.coursePrice {
color: #fb9830;
max-width: 80px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.originalPrice {
text-decoration: line-through;
margin-left: 5px;
position: relative;
top: -1px;
}
}
.joinButton,
.joinCourseV2 {
position: absolute;
right: 15px;
bottom: 20px;
width: 78px;
height: 28px;
border-radius: 15px;
border: 1px solid #ffc67d;
}
.joinCourseV2 {
border: 1px solid #c2c2c2;
}
}
}
.bottomLine {
padding-top: 20px;
}
</style>
<style lang="scss">
.van-tab__pane {
width: 100%;
min-height: 100%;
background: #ffffff;
}
</style>

View File

@ -0,0 +1,402 @@
<template>
<div>
<div v-for="(item, index) in listData" :key="index" @click="goToUrl(item.urlName)">
<div class='alignment' :class='index + 1 != listData.length ? "item_margin" : ""'>
<div class="alignment_left">
<img class="item_icon" :src="item.icon" alt="" />
<div class="font16 color3">{{ $t(item.text) }}</div>
</div>
<img class="AngleIcon" src="https://images.ufutx.com/202108/18/794ae58096304f177454c93daba14179.png" alt="" />
</div>
</div>
<div class="my_list">
<van-popup v-model="showQrcode" :close-on-click-overlay="false" :lock-scroll="true" :duration="0.5">
<div class="m_com">
<div class="u_com_tt font17 text-center color3 bold" style="padding-bottom: 10px">{{ $t('Contact_us') }}</div>
<div v-if='qrcode && qrcode.length > 16'>
<div class="f-fcc">
<img class="u_com_QR" :src="qrcode" alt="" />
</div>
<div class="font14 color6 bold text-center" style="padding-top: 15px">{{ $t('identify_Qr_code') }}</div>
</div>
<div class='font14 color3 text-center' style='padding: 0 20px;line-height: 22px' v-else>
<img class='contact_icon' src='https://image.fulllinkai.com/202112/08/2828a5a3e4bb32db8987c436b09b9cf5.png' alt=''>
<span class='font15 color6'>联系我们请拨打</span>
<span class='font15 colorTheme bold' @click.stop='callPhone'>{{qrcode}}</span>
</div>
</div>
<img class="handleDelete" @click="showQrcode = false" src="https://images.ufutx.com/202105/25/5f7678d9f8fc84f3694893a71169263a.png" alt="" />
</van-popup>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters(['userArr'])
},
props: {
isDetail: {
type: Object,
default: () => {
return {}
}
},
isShop: {
type: Boolean,
default: false
},
isTemplate: {
type: Number,
default: 0
}
},
data() {
return {
qrcode: localStorage.getItem('qrCode'),
listData: [
// {
// urlName: 'myCustomer',
// icon: 'https://image.fulllinkai.com/202206/25/597e7089b74d04ac201c0759743a8e4d.png',
// text: 'my_Customer'
// },
// {
// urlName: 'realName',
// icon: 'https://image.fulllinkai.com/202206/25/70aaa72b63950deacebb6f61d3bb4481.png',
// text: ''
// },
// {
// urlName: 'myTest',
// icon: 'https://image.fulllinkai.com/202206/25/50f95dc3dbd6ce6096791f009028cfa7.png',
// text: 'my_test'
// },
{
urlName: 'myCoupons',
icon: 'https://image.fulllinkai.com/202209/22/afa93b7503b6af60d1e321cc8f171bf0.png',
text: '我的优惠券'
},
{
urlName: 'myMaterial',
icon: 'https://image.fulllinkai.com/202211/08/3282acb1a6cd55ff9a37897a1e7e39d3.png',
text: '我的图库'
},
{
urlName: 'aboutUs',
icon: 'https://image.fulllinkai.com/202206/25/5d6846203bd2cdb6e37238bda0e98ead.png',
text: 'About_us'
},
{
urlName: 'contactUs',
icon: 'https://image.fulllinkai.com/202206/25/3d05b50eb110b2b19908dd9bbea08c7d.png',
text: 'Contact_us'
},
{
urlName: 'myEvaluate',
icon: 'https://image.fulllinkai.com/202206/25/66098c9a843bad97724716335915e352.png',
text: 'my_evaluate'
},
{
urlName: 'language',
icon: 'https://image.fulllinkai.com/202206/25/718832e6edf0995b3295e45d3d106f61.png',
text: 'Language_Settings'
}
],
showQrcode: false,
showCreatedModal: false,
dataInfo: this.$store.state.app.userArr
}
},
watch: {
isDetail(e) {
//
if (this.isDetail.merchant_appointment === 1 || this.isDetail.merchant_appointment === 2) {
if (this.listData[1] && this.listData[1].text === '商家预约') {
return
}
this.listData.splice(1, 0, {
urlName: 'appointmentDetail',
icon: 'https://image.fulllinkai.com/202207/07/4718dbfb7d701236439c94566b4b8522.png',
text: '商家预约'
})
}
},
userArr(e) {
this.dataInfo = e
}
},
methods: {
callPhone() {
const vm = this
window.location.href = `tel://${vm.qrcode}`
},
goToUrl(url) {
if (url == 'realName') {
this.$router.push({
name: 'certificationTransit'
})
return
}
if (url == 'myVIP') {
this.$router.push({
name: 'VIPIndex'
})
return
}
if (url == 'contactUs') {
this.showQrcode = true
return
}
if (url == 'myPlatform') {
if (this.isShop) {
location.href = 'https://love.ufutx.com/api/official/merchat/auth/login'
} else {
this.showCreatedModal = true
}
return
}
if (this.isDetail.merchant_appointment === 2 && url === 'appointmentDetail') {
this.$router.push({
name: 'merchantsMembers'
})
return
}
if (this.isDetail.merchant_appointment === 1 && url === 'appointmentDetail') {
this.$router.push({
name: 'appointmentDetail',
query: { m_id: this.$route.query.merchant_id }
})
return
}
this.$router.push({
name: url
})
}
},
deactivated() {
this.showQrcode = false
},
created() {
},
mounted() {
console.log(this.isTemplate, '-----------')
//
if (this.isTemplate === 2) {
this.listData.splice(1, 0, {
urlName: 'recruitingTeacher',
icon: 'https://image.fulllinkai.com/202206/25/1a4b4c27031eafbf1c909c72920c1b7f.png',
text: 'recruiting_teacher'
})
} else if (this.isTemplate === 3) {
this.listData.splice(1, 0, {
urlName: 'mySignUp',
icon: 'https://image.fulllinkai.com/202206/25/5e234b51191b13381bced0a15be40898.png',
text: 'My_order'
})
this.listData.splice(2, 0, {
urlName: 'recruitingTeacher',
icon: 'https://image.fulllinkai.com/202206/25/1a4b4c27031eafbf1c909c72920c1b7f.png',
text: 'recruiting_teacher'
})
}
}
}
</script>
<style lang="scss" scoped>
.item_margin{
margin-bottom: 20px;
}
.item_icon{
width: 26px;
height: 26px;
display: block;
}
.AngleIcon {
width: 5px;
height: 10px;
display: block;
}
.line {
width: 100%;
height: 1px;
background: #f5f5f5;
margin: 20px 0;
}
.m_com {
width: 300px;
padding-bottom: 30px;
.u_com_tt {
padding-top: 20px;
}
.u_com_QR {
width: 164px;
height: 164px;
display: block;
margin: 0 auto;
}
.contact_icon{
width: 176px;
height: 110px;
display: block;
margin: 10px auto 20px auto;
}
}
.handleDelete {
width: 24px;
height: 24px;
position: fixed;
margin-top: 25px;
left: 50%;
transform: translate(-50%);
}
.mobile-big-box{
margin: 15px 0 20px;
height: 40px;
background: #FFFFFF;
box-shadow: 0px 2px 14px 0px rgba(0, 0, 0, 0.1);
border-radius: 8px;
.mobile-box{
display: flex;
align-items: center;
height: 40px;
.close-box{
margin-top:2px;
margin-left: 8px;
margin-right:6px;
height: 12px;
width:12px;
background-image: url("https://image.fulllinkai.com/202203/08/0fb3ec31f29628d09d18135a826154fe.png");
background-size: cover;
}
.mobile-text{
height: 18px;
font-size: 12px;
color: #666666;
line-height: 18px;
}
.mobile-bind-box{
margin-left: 9px;
padding: 0px 8px 0;
height: 22px;
border-radius: 13px;
border: 1px solid rgba(112, 127, 250, 0.3);
font-size: 12px;
color: #707FFA;
line-height: 22px;
}
}
}
.my_list{
::v-deep .wrapperMy {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
.createdBox{
margin-top: -80px;
position: relative;
width: 300px;
height: 184px;
background: #FFFFFF;
border-radius: 12px;
.createdBoxV2{
display: flex;
flex-direction: column;
align-items: center;
/*justify-content: center;*/
width: 300px;
height: 184px;
.createdText1{
margin-top: 25px;
height: 25px;
font-size: 18px;
font-weight: 500;
color: #333333;
line-height: 25px;
}
.createdText2{
height: 20px;
font-size: 14px;
font-weight: 400;
color: #999999;
line-height: 20px;
}
.enterBox{
margin-top: 25px;
display: flex;
.cancelBox{
margin-right: 20px;
width: 100px;
height: 36px;
border-radius: 20px;
font-size: 16px;
color: #E5AC59;
line-height: 36px;
border: 1px solid #E5AC59;
text-align: center;
}
.confirmBox{
width: 100px;
height: 36px;
background: linear-gradient(90deg, #E9BA8B 0%, #E5AC59 100%);
border-radius: 20px;
font-size: 16px;
color: #ffffff;
line-height: 36px;
border: 1px solid #E5AC59;
text-align: center;
}
}
.shopCreatedBox{
margin-top: 25px;
width: 158px;
height: 104px;
background-image: url("https://image.fulllinkai.com/202112/24/fac5a4e8635d934c9e3a3da363900276.png");
background-size: cover;
}
.createdShopText{
/*height: 42px;*/
font-size: 15px;
color: #666666;
line-height: 21px;
}
.createdSHopBtn{
margin-top: 25px;
width: 200px;
height: 40px;
background: linear-gradient(90deg, #E9BA8B 0%, #E5AC59 100%);
border-radius: 20px;
font-size: 16px;
font-weight: 500;
color: #FFFFFF;
line-height: 40px;
text-align: center;
}
}
.createdClose{
position: absolute;
top: 300px;
right: 50%;
transform: translateX(50%);
width: 24px;
height: 24px;
background-image: url("https://image.fulllinkai.com/202112/24/612dbd14460583a936fbe1650935df0a.png");
background-size: cover;
z-index: 333;
}
}
}
}
.close-btn{
position: absolute;
bottom: -50px;
left: 50%;
transform: translateX(-50%);
height: 20px;
width: 20px;
background-image: url("https://image.fulllinkai.com/202203/08/0119b47bbda33be02d0a4f6c60558602.png");
background-size: cover;
}
</style>

View File

@ -0,0 +1,714 @@
<template>
<div class="my">
<div class="userBgBox alignment" :class='detail.member == 1?"":"activeBg"'>
<div class='alignment_left'>
<div class="user_photo backCover" v-bind:style="{ backgroundImage: 'url(' + detail.avatar + ')' }"></div>
<div>
<div class='font18 color3 bold'>{{ detail.nickname || '未填写' }}</div>
<van-image class="WeChatAuthorization" fit="contain" @click="authorization" src="https://image.fulllinkai.com/202206/25/ca11dae806a1ce4a7f71cd26fd1cfc10.png" alt="" />
</div>
</div>
<div class='alignment_right' @click="goToUrl('editorUserData')">
<div class='font14 color6'>编辑</div>
<img class='editor_icom' src='https://image.fulllinkai.com/202206/25/32e488269070923ca4b7e363a1afeffb.png' alt=''>
</div>
</div>
<div class="m_live_box" v-if="liveShow" :class='detail.member == 1?"":"activeBg"'>
<div class="m_live alignment_left" @click="goToUrlId('liveList', liveData.id)">
<div class="m_live_to">
<van-image class="u_live_to" round fit="contain" :src="liveData.poster" alt="" />
<van-image class="u_live_to_icon" fit="contain" src="https://image.fulllinkai.com/202111/23/69812a694932506893e0e4572bd57cf2.gif" alt="" />
</div>
<div class="font13 color6">有人正在直播快来强势围观点击进入>></div>
</div>
</div>
<div class="vip_pic backCover alignment" v-bind:style="{ backgroundImage: 'url(' + 'https://image.fulllinkai.com/202206/30/4c83d3da9e0e2018f548755036c86a30.png' + ')' }" v-if='detail.member == 1' @click='goToUrl("VIPIndex")'>
<div style='margin-left: 63px;margin-top: 4px'>
<div class='font14 colorff bold' v-if='!detail.member_expire_time'>开通VIP超级会员</div>
<div class='font14 colorff bold' v-else>VIP超级会员</div>
</div>
<div class='font13 bold colorff' style='opacity: 0.8;margin-right: 30px;margin-top: 4px' v-if='!detail.member_expire_time'>专享超值权益 >></div>
<div class='font13 bold colorff alignment_right' style='opacity: 0.8;margin-right: 30px;margin-top: 5px' v-else>{{detail.member_expire_time}}
<img style='width: 5px;height: 10px;display: block;margin-left: 10px;margin-top: -1px' src='https://image.fulllinkai.com/202206/30/794ae58096304f177454c93daba14179.png' alt=''>
</div>
</div>
<div style='margin: 15px' v-if='mobileShow'>
<div class='mobile-big-box alignment'>
<div class='mobile-box alignment_left'>
<img class='close-box' @click='mobileShow = false' src='https://image.fulllinkai.com/202203/08/0fb3ec31f29628d09d18135a826154fe.png' alt=''>
<div class='font13 color6'>你还没绑定手机号,绑定后将更好地服务您</div>
</div>
<div class='mobile-bind-box alignment_center font12 colorTheme' @click='goToBind'>去绑定</div>
</div>
</div>
<div class='tabs_box'>
<div class='alignment'>
<div class='tabs_item_box' v-for='(item,index) in tabsList' :key='index' @click="goToUrl(item.urlName)">
<img class='tabs_item_icon' :src='item.icon' alt=''>
<div class='font12 color3'>{{ $t(item.text) }}</div>
</div>
</div>
<div class='marqueeWrap_box' v-if='showGroup'>
<div class="marqueeWrap">
<div class="animateBox">
<div class="animate" :class="{ 'animate-up': animateUp }">
<div class='alignment' v-for="(item, index) in groupList" :key="index" @click='goToGroup(item)'>
<div class='alignment_left'>
<div class="head_pic backCover" :class="item.type === 'shop'? 'shop_pic':''" :style="{ backgroundImage: 'url(' + item.pic + ')' }"></div>
<div>
<div class='font12 color3 bold'>拼团中</div>
<div class='font10 color6'>还差<span style='color: #FFAC4A'>{{item.need_count}}</span>拼团</div>
</div>
</div>
<div class='alignment_right'>
<div class='goToJoin alignment_center color3 font11'>邀请好友</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class='operationBox'>
<myListComponent :isShop="detail.is_merchant == 0 ? false : true" :isDetail='detail' :isTemplate='1' :border="true" @updateData='updateData'></myListComponent>
</div>
<div class="logoBox" @click="clearLocalStorage">
<img class="logoImg" src="https://image.fulllinkai.com/202108/26/d9bb2c2d9f958a3d02ba96dff07a11a5.png" alt="" />
<div class="font11 text-center" style="color: #c2c2c2">
{{ $t('Full_Link_intelligent_to_provide_technical_service_support') }}
</div>
</div>
<div style="height: 55px"></div>
<van-popup v-model="showAccount" :close-on-click-overlay="false" :lock-scroll="true" :duration="0.5">
<div class="m_acc">
<div class="font18 text-center color3 bold" style="padding: 20px 0 5px">绑定手机号</div>
<div class="font12 text-center color9" style="padding: 0 0 10px">为了更好的服务您请绑定手机号</div>
<div class='mobile_box'>
<div class="alignment" style='padding-bottom: 10px'>
<van-field class="inputBox" type="text" v-model="mobile" placeholder="请输入手机号" />
</div>
<div class="alignment from_item_input">
<div class='font14 code_box' style='color: #707FFA' v-if='time == 60' @click.stop='getCode'>{{codeText}}</div>
<div class='font14 code_box color9' v-else>{{time}}</div>
<van-field class="inputBox" oninput="if(value.length>6)value=value.slice(0,6)" type="number" v-model="code" placeholder="请输入验证码" />
</div>
</div>
<div class="m_acc_bu f-fcc font16 colorff" @click="changeMobile">{{ $t('determine') }}</div>
<div class='close-btn' @click='showAccount=false'></div>
</div>
</van-popup>
<div class='my_list'>
<van-overlay :show="showCreatedModal" :lock-scroll="true">
<div class="wrapperMy">
<div class="createdBox" :style="{height: '286px'}">
<div class="createdBoxV2" :style="{height: '286px'}">
<div class="shopCreatedBox"></div>
<div class="font15 color6" style="margin-top: 15px;">您还不是服务商成为服务商即可</div>
<div class="font15 color6">搭建您的专属平台</div>
<div class="createdSHopBtn" @click="goToUrl('recruitingTeacher')">成为服务商</div>
</div>
<div class="createdClose" @click="showCreatedModal = false"></div>
</div>
</div>
</van-overlay>
</div>
</div>
</template>
<script>
import service from '@/utils/request'
import myListComponent from '@/components/myModule/my_list_component'
import { $toastClear, $toastLoading, $toastText } from '@/config/toast'
export default {
computed: {},
components: {
myListComponent
},
data() {
return {
detail: {},
qrcode: '',
bg: 'https://images.ufutx.com/202108/18/3bf93cea648f588a5623ceb4f8fa7f3c.png',
showCreatedModal: false,
liveShow: false,
mobileShow: false, //
code: '',
tabsList: [
{
urlName: 'myPlatform',
icon: 'https://image.fulllinkai.com/202206/25/cf617d89bc47858bd06d139d822fc5d4.png',
text: 'my_Platform'
},
{
urlName: 'mySignUp',
icon: 'https://image.fulllinkai.com/202206/25/8071738a8f44a17b43ddab96a9217058.png',
text: 'My_order'
},
{
urlName: 'myRecommend',
icon: 'https://image.fulllinkai.com/202206/25/a603a96afaca054386eb41e8a909d010.png',
text: 'my_recommend'
},
{
urlName: 'recruitingTeacher',
icon: 'https://image.fulllinkai.com/202206/25/75058e5a2f3c69dc00b779e69e319960.png',
text: 'recruiting_teacher'
}
],
groupList: [],
showGroup: false,
timer: null,
animateUp: false,
mobile: '',
showAccount: false,
codeThrottle: true,
time: 60,
codeTime: null,
codeText: '获取验证码',
liveData: {}
}
},
watch: {
'$route'(to, from) {
if (from.name === 'editorUserData') { this.getData() }
},
time() {
if (this.time === 0) {
clearInterval(this.codeTime)
this.time = 60
this.codeThrottle = true
this.codeText = '重新获取'
}
}
},
methods: {
clearLocalStorage() {
localStorage.clear()
},
authorization() {
const vm = this
localStorage.removeItem('saas_token')
vm.$authorization(vm.$shareCallback, vm.$store.state.app.merchant_id, 'my')
},
//
updateData() {
this.getData()
this.getGroupData()
},
scrollAnimate() {
const vm = this
this.animateUp = true
setTimeout(() => {
vm.groupList.push(vm.groupList[0])
vm.groupList.shift()
vm.animateUp = false
}, 3300)
},
goToGroup(e) {
const vm = this
if (e.is_initiator === 1) {
vm.$router.push({
name: 'groupOrder',
query: { order_id: e.m_order_id, type: e.type }
})
} else {
vm.$router.push({
name: 'groupData',
query: { order_id: e.m_order_id, type: e.type, history_id: e.id, id: e.type_id }
})
}
},
getGroupData() {
const vm = this
service.get(`s/h5/group/myGroups`).then(data => {
vm.groupList = data
if (vm.groupList && vm.groupList.length !== 0) {
vm.showGroup = true
console.log(vm.groupList, '-------------')
}
if (vm.groupList && vm.groupList.length > 1) {
this.timer = setInterval(this.scrollAnimate, 3500)
}
console.log(vm.showGroup, '-------------showGroup')
}).catch(error => {
console.log(error)
})
},
getData() {
const vm = this
const url = `s/h5/BusinessUser`
service.get(url).then(data => {
data.avatar = data.avatar.replace(/\/\d*$/, '/0')
vm.detail = data
if (data.mobile) {
vm.mobileShow = false
} else {
vm.mobileShow = true
}
}).catch(error => {
console.log(error)
})
},
getLiveData() {
const vm = this
const url = `/s/h5/live/list`
service.get(url).then(data => {
if (data.data.length > 0) {
data.data.forEach(item => {
if (item.status == 1) {
this.liveShow = true
}
if (item.poster && item.poster.indexOf('?') != -1) {
var urlArr = item.poster.split('?')
if (urlArr.length > 0) {
console.log(item.poster)
item.poster = urlArr[0]
}
}
})
this.liveData = data.data[0]
}
}).catch(error => {
console.log(error)
})
},
goToUrl(url) {
if (url === 'myPlatform') {
if (this.detail.is_merchant) {
location.href = 'https://love.ufutx.com/api/official/merchat/auth/login'
} else {
this.showCreatedModal = true
}
return
}
this.$router.push({
name: url
})
},
goToUrlId(url, id) {
this.$router.push({
name: url,
params: { id: id }
})
},
goToBind() {
this.showAccount = true
},
getCode() {
const vm = this
const data = {
mobile: vm.mobile
}
if (!vm.mobile) {
$toastText('手机号不能为空')
return
}
if (!(/^1(3|4|5|6|7|8|9)\d{9}$/.test(vm.mobile))) {
$toastText('手机号无效,请重新输入')
return
}
if (vm.codeThrottle) {
vm.codeThrottle = false
service.post('s/m/admin/plat/sendCode', data).then(data => {
setTimeout(() => {
vm.codeThrottle = true
}, 700)
if (data.status === 0) {
vm.time = 59
vm.codeTime = setInterval(() => {
vm.time--
}, 1000)
setTimeout(() => {
$toastText('验证码已发送')
}, 300)
} else if (data.status === 6) {
$toastText('请求频率过快,请稍后再试')
vm.codeThrottle = true
}
})
.catch(error => {
vm.codeThrottle = true
console.log(error)
})
}
},
changeMobile() {
const vm = this
const data = {
mobile: vm.mobile,
code: vm.code
}
if (!vm.mobile) {
$toastText('手机号不能为空')
return
}
if (!(/^1(3|4|5|6|7|8|9)\d{9}$/.test(vm.mobile))) {
$toastText('手机号无效,请重新输入')
return
}
if (!vm.code) {
$toastText('验证码不能为空')
return
}
service.post(`s/h5/merchant/merchantUserBindMobile`, data)
.then(data => {
if (data.status === 8) {
return $toastText('验证码有误')
}
if (data.status === 9) {
return $toastText('验证码过期')
}
if (data.status === 10) {
return $toastText('验证码已使用')
}
$toastText('绑定成功')
vm.showAccount = false
vm.getData()
})
}
},
destroyed() {
clearInterval(this.timer)
this.timer = null
},
activated() {
if (this.$route.query.jumpState) {
this.getData()
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
this.getData()
this.getGroupData()
this.getLiveData()
console.log(this.$i18n.t('Language_Settings'), '798798798')
}
}
</script>
<style lang="scss" scoped>
.my {
width: 100vw;
min-height: 100vh;
background: #f8f8f8;
}
.userBgBox {
padding: 20px 15px 15px 15px;
background: #ffffff;
.user_photo{
width: 56px;
height: 56px;
border: 1px solid #e2e2e2;
border-radius: 50%;
display: block;
margin-right: 11px;
}
.WeChatAuthorization{
width: 120px;
height: 34px;
display: block;
margin-left: -4px;
margin-top: 2px;
}
.editor_icom{
width: 6px;
height: 12px;
display: block;
margin-left: 10px;
}
}
.m_live_box {
padding: 0 15px 20px 15px;
background: #ffffff;
.m_live {
width: 100%;
height: 56px;
background: #F2F3FF;
border-radius: 28px;
.m_live_to {
width: 32px;
height: 32px;
border-radius: 50%;
border: 2px solid #96a2ff;
box-sizing: border-box;
position: relative;
margin-right: 10px;
margin-left: 15px;
.u_live_to {
width: 100%;
height: 100%;
border-radius: 50%;
}
.u_live_to_icon {
width: 14px;
height: 10px;
position: absolute;
background-color: #96a2ff;
border-radius: 10px;
bottom: -2px;
right: -2px;
z-index: 11;
}
}
}
.icon {
width: 26px;
height: 26px;
display: block;
margin-bottom: 1px;
}
.AngleIcon {
width: 5px;
height: 10px;
display: block;
margin-right: 15px;
}
.line {
width: 100%;
height: 1px;
background: #f5f5f5;
margin: 20px 0;
}
}
.activeBg{
background: #f8f8f8;
}
.vip_pic{
width: 100%;
height: 58px;
}
.mobile-big-box{
padding: 11px 15px 11px 13px;
background: #ffffff;
border-radius: 8px;
.close-box{
width:12px;
height: 12px;
display: block;
margin-right: 4px;
}
.mobile-bind-box{
width: 52px;
height: 22px;
border-radius: 13px;
border: 1px solid rgba(112, 127, 250, 0.3);
}
}
.tabs_box{
margin: 15px;
border-radius: 12px;
padding: 12px 15px 13px 15px;
background: #ffffff;
.tabs_item_box{
text-align: center;
.tabs_item_icon{
width: 28px;
height: 28px;
display: block;
margin: 0 auto 10px auto;
}
}
.marqueeWrap_box{
padding: 8px 10px;
margin-top: 15px;
background: #f8f8f8;
border-radius: 8px;
.marqueeWrap {
height: 35px;
overflow: hidden;
display: flex;
.animateBox {
flex: none;
width: 100%;
height: 100%;
.animate {
width: 100%;
height: 100%;
.head_pic{
width: 62px;
height: 35px;
border-radius: 6px;
margin-right: 8px;
}
.shop_pic{
width: 35px;
}
.goToJoin{
width: 72px;
height: 22px;
border-radius: 13px;
border: 1px solid #D8D8D8;
}
}
.animate-up {
transition: all 1s;
margin-top: -35px;
flex: none;
width: 100%;
}
}
}
}
}
.operationBox{
margin: 15px;
padding: 15px 15px 15px 10px;
background: #ffffff;
border-radius: 12px;
}
.logoBox {
width: 100vw;
padding: 15px 0 70px 0;
.logoImg {
width: 51px;
height: 18px;
display: block;
margin: 0 auto 1px auto;
}
}
.m_acc {
width: 300px;
padding-bottom: 35px;
.alignment{
padding: 0;
}
.mobile_box{
padding: 0 20px;
.inputBox{
font-size: 16px;
color: #333333;
outline: none;
appearance: none;
border-bottom: 1px solid #f5f5f5;
padding-top: 11px;
padding-left: initial;
padding-bottom: 8px;
}
.from_item_input{
position: relative;
.code_box{
position: absolute;
right: 0;
z-index: 1;
}
.van-cell{
padding-right: 90px;
}
}
}
.m_acc_bu {
width: 200px;
height: 36px;
background: linear-gradient(92deg, #8c9bff 0%, #707ffa 100%);
border-radius: 20px;
margin: 40px auto 0;
}
}
.close-btn{
position: absolute;
bottom: -50px;
left: 50%;
transform: translateX(-50%);
height: 20px;
width: 20px;
background-image: url("https://image.fulllinkai.com/202203/08/0119b47bbda33be02d0a4f6c60558602.png");
background-size: cover;
}
.my_list{
::v-deep .wrapperMy {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
.createdBox{
margin-top: -80px;
position: relative;
width: 300px;
height: 184px;
background: #FFFFFF;
border-radius: 12px;
.createdBoxV2{
display: flex;
flex-direction: column;
align-items: center;
width: 300px;
height: 184px;
.createdText1{
margin-top: 25px;
height: 25px;
font-size: 18px;
font-weight: 500;
color: #333333;
line-height: 25px;
}
.createdText2{
height: 20px;
font-size: 14px;
font-weight: 400;
color: #999999;
line-height: 20px;
}
.enterBox{
margin-top: 25px;
display: flex;
.cancelBox{
margin-right: 20px;
width: 100px;
height: 36px;
border-radius: 20px;
font-size: 16px;
color: #E5AC59;
line-height: 36px;
border: 1px solid #E5AC59;
text-align: center;
}
.confirmBox{
width: 100px;
height: 36px;
background: linear-gradient(90deg, #E9BA8B 0%, #E5AC59 100%);
border-radius: 20px;
font-size: 16px;
color: #ffffff;
line-height: 36px;
border: 1px solid #E5AC59;
text-align: center;
}
}
.shopCreatedBox{
margin-top: 25px;
width: 158px;
height: 104px;
background-image: url("https://image.fulllinkai.com/202112/24/fac5a4e8635d934c9e3a3da363900276.png");
background-size: cover;
}
.createdSHopBtn{
margin-top: 25px;
width: 200px;
height: 40px;
background: linear-gradient(90deg, #E9BA8B 0%, #E5AC59 100%);
border-radius: 20px;
font-size: 16px;
font-weight: 500;
color: #FFFFFF;
line-height: 40px;
text-align: center;
}
}
.createdClose{
position: absolute;
top: 300px;
right: 50%;
transform: translateX(50%);
width: 24px;
height: 24px;
background-image: url("https://image.fulllinkai.com/202112/24/612dbd14460583a936fbe1650935df0a.png");
background-size: cover;
z-index: 333;
}
}
}
}
</style>

View File

@ -0,0 +1,743 @@
<template>
<div class="my">
<div style='height: 10px'></div>
<div class="m_live_box" v-if="liveShow">
<div class="m_live alignment_left" @click="goToUrlId('liveList', liveData.id)">
<div class="m_live_to">
<van-image class="u_live_to" round fit="contain" :src="liveData.poster" alt="" />
<van-image class="u_live_to_icon" fit="contain" src="https://image.fulllinkai.com/202111/23/69812a694932506893e0e4572bd57cf2.gif" alt="" />
</div>
<div class="font13 color6">有人正在直播快来强势围观点击进入>></div>
</div>
</div>
<div class="userBgBox">
<div class="user_bg">
<div class='alignment_left' style='padding-left: 20px'>
<div class="user_photo backCover" v-bind:style="{ backgroundImage: 'url(' + detail.avatar + ')' }"></div>
<div>
<div class='alignment_left' style='margin-left: 20px'>
<div class='font18 color3 bold'>{{detail.nickname || '未填写'}}</div>
<div class='alignment_left' @click="goToUrl('editorUserData')">
<img class='editor_icon' src='https://image.fulllinkai.com/202207/01/ad7477186aa1e7a69b6dd28bae8aaf23.png' alt=''>
<div class='font12 color6'>编辑</div>
</div>
</div>
<van-image class="WeChatAuthorization" fit="contain" @click="authorization" src="https://image.fulllinkai.com/202207/01/5bbb03c673c8aee91f209d6c66d7ff31.png" alt="" />
</div>
</div>
</div>
</div>
<div class='tabs_box'>
<div class='alignment_left'>
<div class='tabs_item_box alignment_left' v-for='(item,index) in tabsList' :key='index' @click="goToUrl(item.urlName)">
<img class='tabs_item_icon' :src='item.icon' alt=''>
<div class='text-left'>
<div class='font14 color3 bold'>{{ $t(item.text) }}</div>
<div class='font11 color9'>{{item.textV2}}</div>
</div>
<div style='width: 1px;height: 26px;background: #f8f8f8;margin: 0 20px 0 30px' v-if='index == 0'></div>
</div>
</div>
<div class='marqueeWrap_box' v-if='showGroup'>
<div class="marqueeWrap">
<div class="animateBox">
<div class="animate" :class="{ 'animate-up': animateUp }">
<div class='alignment' v-for="(item, index) in groupList" :key="index" @click='goToGroup(item)'>
<div class='alignment_left'>
<div class="head_pic backCover" :class="item.type === 'shop'? 'shop_pic':''" :style="{ backgroundImage: 'url(' + item.pic + ')' }"></div>
<div>
<div class='font12 color3 bold'>拼团中</div>
<div class='font10 color6'>还差<span style='color: #FFAC4A'>{{item.need_count}}</span>拼团</div>
</div>
</div>
<div class='alignment_right'>
<div class='goToJoin alignment_center color3 font11'>邀请好友</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="vip_pic backCover alignment" v-bind:style="{ backgroundImage: 'url(' + 'https://image.fulllinkai.com/202207/01/064eeaf7e6acd8fe50c556907fa4713e.png' + ')' }" v-if='detail.member == 1' @click='goToUrl("VIPIndex")'>
<div>
<div class='font14 colorff bold' style='margin-left: 50px' v-if='!detail.member_expire_time'>开通VIP超级会员</div>
<div class='font14 colorff bold' style='margin-left: 46px' v-else>VIP超级会员</div>
</div>
<div class='font13 bold colorff' style='opacity: 0.8;margin-right: 15px;' v-if='!detail.member_expire_time'>专享超值权益 >></div>
<div class='font13 bold colorff alignment_right' style='opacity: 0.8;margin-right: 15px' v-else>{{detail.member_expire_time}}
<img style='width: 5px;height: 10px;display: block;margin-left: 10px;margin-top: -1px' src='https://image.fulllinkai.com/202206/30/794ae58096304f177454c93daba14179.png' alt=''>
</div>
</div>
<div style='margin: 15px' v-if='mobileShow'>
<div class='mobile-big-box alignment'>
<div class='mobile-box alignment_left'>
<img class='close-box' @click='mobileShow = false' src='https://image.fulllinkai.com/202203/08/0fb3ec31f29628d09d18135a826154fe.png' alt=''>
<div class='font13 color6'>你还没绑定手机号,绑定后将更好地服务您</div>
</div>
<div class='mobile-bind-box alignment_center font12 colorTheme' @click='goToBind'>去绑定</div>
</div>
</div>
<div class='operationBox'>
<myListComponent :isShop="detail.is_merchant == 0 ? false : true" :isDetail='detail' :isTemplate='3' :border="true" @updateData='updateData'></myListComponent>
</div>
<div class="logoBox" @click="clearLocalStorage">
<img class="logoImg" src="https://image.fulllinkai.com/202108/26/d9bb2c2d9f958a3d02ba96dff07a11a5.png" alt="" />
<div class="font11 text-center" style="color: #c2c2c2">
{{ $t('Full_Link_intelligent_to_provide_technical_service_support') }}
</div>
</div>
<van-popup v-model="showAccount" :close-on-click-overlay="false" :lock-scroll="true" :duration="0.5">
<div class="m_acc">
<div class="font18 text-center color3 bold" style="padding: 20px 0 5px">绑定手机号</div>
<div class="font12 text-center color9" style="padding: 0 0 10px">为了更好的服务您请绑定手机号</div>
<div class='mobile_box'>
<div class="alignment" style='padding-bottom: 10px'>
<van-field class="inputBox" type="text" v-model="mobile" placeholder="请输入手机号" />
</div>
<div class="alignment from_item_input">
<div class='font14 code_box' style='color: #707FFA' v-if='time == 60' @click.stop='getCode'>{{codeText}}</div>
<div class='font14 code_box color9' v-else>{{time}}</div>
<van-field class="inputBox" oninput="if(value.length>6)value=value.slice(0,6)" type="number" v-model="code" placeholder="请输入验证码" />
</div>
</div>
<div class="m_acc_bu f-fcc font16 colorff" @click="changeMobile">{{ $t('determine') }}</div>
<div class='close-btn' @click='showAccount=false'></div>
</div>
</van-popup>
<div class='my_list'>
<van-overlay :show="showCreatedModal" :lock-scroll="true">
<div class="wrapperMy">
<div class="createdBox" :style="{height: '286px'}">
<div class="createdBoxV2" :style="{height: '286px'}">
<div class="shopCreatedBox"></div>
<div class="font15 color6" style="margin-top: 15px;">您还不是服务商成为服务商即可</div>
<div class="font15 color6">搭建您的专属平台</div>
<div class="createdSHopBtn" @click="goToUrl('recruitingTeacher')">成为服务商</div>
</div>
<div class="createdClose" @click="showCreatedModal = false"></div>
</div>
</div>
</van-overlay>
</div>
</div>
</template>
<script>
import service from '@/utils/request'
import myListComponent from '@/components/myModule/my_list_component'
import { $toastText } from '@/config/toast'
export default {
computed: {},
components: { myListComponent },
data() {
return {
tabsList: [
{
urlName: 'myPlatform',
icon: 'https://image.fulllinkai.com/202207/01/c518646f1633b6e485625e748e523d55.png',
text: 'my_Platform',
textV2: '专属你的二维码'
},
{
urlName: 'myRecommend',
icon: 'https://image.fulllinkai.com/202207/01/f5771f127d129a138b8c93ab6be5f5d1.png',
text: 'my_recommend',
textV2: '收益赚个不停'
}
],
detail: {},
qrcode: '',
bg: 'https://image.fulllinkai.com/202109/07/fe9e791027aeec5509358f995c676e84.png',
showCreatedModal: false,
liveShow: false,
mobileShow: false, //
code: '',
showGroup: false,
groupList: [],
timer: null,
animateUp: false,
mobile: '',
showAccount: false,
codeThrottle: true,
time: 60,
codeTime: null,
codeText: '获取验证码',
liveData: {}
}
},
watch: {
'$route'(to, from) {
if (from.name === 'editorUserData') { this.getData() }
},
time() {
if (this.time === 0) {
clearInterval(this.codeTime)
this.time = 60
this.codeThrottle = true
this.codeText = '重新获取'
}
}
},
methods: {
clearLocalStorage() {
localStorage.clear()
},
authorization() {
const vm = this
localStorage.removeItem('saas_token')
// window.location.replace(
// `https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx36c72a00f1b2be64&redirect_uri=` +
// encodeURIComponent(
// `${vm.$shareCallback}/api/official/newNonSilenceAuth?merchant_id=${this.$store.state.app.merchant_id}`
// ) +
// `&response_type=code&scope=snsapi_userinfo&state=STATE&connect_redirect=1#wechat_redirect`
// )
vm.$authorization(vm.$shareCallback, vm.$store.state.app.merchant_id, 'my')
},
//
updateData() {
this.getGroupData()
this.getData()
},
goToBind() {
this.showAccount = true
},
getCode() {
const vm = this
const data = {
mobile: vm.mobile
}
if (!vm.mobile) {
$toastText('手机号不能为空')
return
}
if (!(/^1(3|4|5|6|7|8|9)\d{9}$/.test(vm.mobile))) {
$toastText('手机号无效,请重新输入')
return
}
if (vm.codeThrottle) {
vm.codeThrottle = false
service.post('s/m/admin/plat/sendCode', data).then(data => {
setTimeout(() => {
vm.codeThrottle = true
}, 700)
if (data.status === 0) {
vm.time = 59
vm.codeTime = setInterval(() => {
vm.time--
}, 1000)
setTimeout(() => {
$toastText('验证码已发送')
}, 300)
} else if (data.status === 6) {
$toastText('请求频率过快,请稍后再试')
vm.codeThrottle = true
}
})
.catch(error => {
vm.codeThrottle = true
console.log(error)
})
}
},
changeMobile() {
const vm = this
const data = {
mobile: vm.mobile,
code: vm.code
}
if (!vm.mobile) {
$toastText('手机号不能为空')
return
}
if (!(/^1(3|4|5|6|7|8|9)\d{9}$/.test(vm.mobile))) {
$toastText('手机号无效,请重新输入')
return
}
if (!vm.code) {
$toastText('验证码不能为空')
return
}
service.post(`s/h5/merchant/merchantUserBindMobile`, data)
.then(data => {
if (data.status === 1) {
return
}
if (data.status === 8) {
return $toastText('验证码有误')
}
if (data.status === 9) {
return $toastText('验证码过期')
}
if (data.status === 10) {
return $toastText('验证码已使用')
}
$toastText('绑定成功')
vm.showAccount = false
vm.getData()
})
},
scrollAnimate() {
const vm = this
this.animateUp = true
setTimeout(() => {
vm.groupList.push(vm.groupList[0])
vm.groupList.shift()
vm.animateUp = false
}, 3300)
},
goToGroup(e) {
const vm = this
if (e.is_initiator === 1) {
vm.$router.push({
name: 'groupOrder',
query: { order_id: e.m_order_id, type: e.type }
})
} else {
vm.$router.push({
name: 'groupData',
query: { order_id: e.m_order_id, type: e.type, history_id: e.id, id: e.type_id }
})
}
},
getGroupData() {
const vm = this
service.get(`s/h5/group/myGroups`).then(data => {
vm.groupList = data
if (vm.groupList && vm.groupList.length !== 0) {
vm.showGroup = true
console.log(vm.groupList, '-------------')
}
if (vm.groupList && vm.groupList.length > 1) {
this.timer = setInterval(this.scrollAnimate, 3500)
}
console.log(vm.showGroup, '-------------showGroup')
}).catch(error => {
console.log(error)
})
},
getData() {
const vm = this
const url = `s/h5/BusinessUser`
service
.get(url)
.then(data => {
data.avatar = data.avatar.replace(/\/\d*$/, '/0')
vm.detail = data
if (data.avatar === 'https://images.ufutx.com/202108/06/e1b03db630b24fd818d1aa9967ce3fb1.png') {
// vm.authorization()
}
if (data.mobile) {
vm.mobileShow = false
} else {
vm.mobileShow = true
}
vm.qrcode = data.avatar
console.log(data, '7897')
})
.catch(error => {
console.log(error)
})
},
getLiveData() {
const vm = this
const url = `/s/h5/live/list`
service.get(url).then(data => {
if (data.data.length > 0) {
data.data.forEach(item => {
if (item.status == 1) {
this.liveShow = true
}
if (item.poster && item.poster.indexOf('?') != -1) {
var urlArr = item.poster.split('?')
if (urlArr.length > 0) {
console.log(item.poster)
item.poster = urlArr[0]
}
}
})
this.liveData = data.data[0]
console.log(this.liveData, 'live=----------------')
}
}).catch(error => {
console.log(error)
})
},
goToUrl(url) {
if (url === 'myPlatform') {
if (this.detail.is_merchant) {
location.href = 'https://love.ufutx.com/api/official/merchat/auth/login'
} else {
this.showCreatedModal = true
}
return
}
this.$router.push({
name: url
})
},
goToUrlId(url, id) {
this.$router.push({
name: url,
params: { id: id }
})
}
},
destroyed() {
clearInterval(this.timer)
this.timer = null
},
activated() {
if (this.$route.query.jumpState) {
this.getData()
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
this.getData()
this.getGroupData()
this.getLiveData()
console.log(this.$i18n.t('Language_Settings'), '798798798')
}
}
</script>
<style lang="scss" scoped>
.my {
width: 100vw;
min-height: 100vh;
background: #ffffff;
}
.m_live_box {
padding: 0 20px 20px 20px;
background: #ffffff;
.m_live {
width: 100%;
height: 56px;
background: #F2F3FF;
border-radius: 28px;
.m_live_to {
width: 32px;
height: 32px;
border-radius: 50%;
border: 2px solid #96a2ff;
box-sizing: border-box;
position: relative;
margin-right: 10px;
margin-left: 17px;
.m_live_toDah {
width: 100%;
height: 100%;
border-radius: 50%;
border: 2px solid #96a2ff;
animation: myfirst 0.5s infinite;
box-shadow: 0px 0px 1px #96a2ff;
box-sizing: border-box;
}
.u_live_to {
width: 100%;
height: 100%;
border-radius: 50%;
}
.u_live_to_icon {
width: 14px;
height: 10px;
position: absolute;
background-color: #96a2ff;
border-radius: 10px;
bottom: -2px;
right: -2px;
z-index: 11;
}
}
}
.icon {
width: 26px;
height: 26px;
display: block;
margin-bottom: 1px;
}
.AngleIcon {
width: 5px;
height: 10px;
display: block;
margin-right: 15px;
}
.line {
width: 100%;
height: 1px;
background: #f5f5f5;
margin: 20px 0;
}
}
.userBgBox {
width: 100%;
.user_bg{
width: 100%;
.user_photo{
width: 80px;
height: 80px;
border: 1px solid #e2e2e2;
border-radius: 20px;
}
.editor_icon{
width: 12px;
height: 12px;
display: block;
margin: 0 2px 0 10px;
}
.WeChatAuthorization{
width: 120px;
height: 32px;
display: block;
margin-left: 12px;
margin-top: 7px;
}
}
}
.tabs_box{
margin: 15px;
box-shadow: 0 2px 14px 0 rgba(0,0,0,0.0600);
padding: 8px 15px 10px 8px;
border-radius: 8px;
background: #ffffff;
.tabs_item_box{
text-align: center;
.tabs_item_icon{
width: 52px;
height: 52px;
display: block;
margin-right: 6px;
}
}
.marqueeWrap_box{
padding: 8px 10px;
margin-left: 7px;
background: #f8f8f8;
border-radius: 8px;
.marqueeWrap {
height: 35px;
overflow: hidden;
display: flex;
.animateBox {
flex: none;
width: 100%;
height: 100%;
.animate {
width: 100%;
height: 100%;
.head_pic{
width: 62px;
height: 35px;
border-radius: 6px;
margin-right: 8px;
}
.shop_pic{
width: 35px;
}
.goToJoin{
width: 72px;
height: 22px;
border-radius: 13px;
border: 1px solid #D8D8D8;
}
}
.animate-up {
transition: all 1s;
margin-top: -35px;
flex: none;
width: 100%;
}
}
}
}
}
.vip_pic{
width: 345px;
margin: 0 auto;
height: 50px;
}
.mobile-big-box{
padding: 11px 15px 11px 13px;
box-shadow: 0 2px 14px 0 rgba(0, 0, 0, 0.06);
background: #ffffff;
border-radius: 8px;
.close-box{
width:12px;
height: 12px;
display: block;
margin-right: 4px;
}
.mobile-bind-box{
width: 52px;
height: 22px;
border-radius: 13px;
border: 1px solid rgba(112, 127, 250, 0.3);
}
}
.operationBox{
margin: 15px;
padding: 15px 15px 15px 10px;
box-shadow: 0 2px 14px 0 rgba(0, 0, 0, 0.06);
background: #ffffff;
border-radius: 12px;
}
.logoBox {
width: 100vw;
padding: 20px 0 140px 0;
.logoImg {
width: 51px;
height: 18px;
display: block;
margin: 0 auto 1px auto;
}
}
.m_acc {
width: 300px;
padding-bottom: 35px;
.alignment{
padding: 0;
}
.mobile_box{
padding: 0 20px;
.inputBox{
/*width: 74%;*/
font-size: 16px;
color: #333333;
outline: none;
appearance: none;
border-bottom: 1px solid #f5f5f5;
padding-top: 11px;
padding-left: initial;
padding-bottom: 8px;
}
.from_item_input{
position: relative;
.code_box{
position: absolute;
//bottom: 13px;
right: 0;
z-index: 1;
}
.van-cell{
padding-right: 90px;
}
}
}
.m_acc_bu {
width: 200px;
height: 36px;
background: linear-gradient(92deg, #8c9bff 0%, #707ffa 100%);
border-radius: 20px;
margin: 40px auto 0;
}
}
.close-btn{
position: absolute;
bottom: -50px;
left: 50%;
transform: translateX(-50%);
height: 20px;
width: 20px;
background-image: url("https://image.fulllinkai.com/202203/08/0119b47bbda33be02d0a4f6c60558602.png");
background-size: cover;
}
.my_list{
::v-deep .wrapperMy {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
.createdBox{
margin-top: -80px;
position: relative;
width: 300px;
height: 184px;
background: #FFFFFF;
border-radius: 12px;
.createdBoxV2{
display: flex;
flex-direction: column;
align-items: center;
width: 300px;
height: 184px;
.createdText1{
margin-top: 25px;
height: 25px;
font-size: 18px;
font-weight: 500;
color: #333333;
line-height: 25px;
}
.createdText2{
height: 20px;
font-size: 14px;
font-weight: 400;
color: #999999;
line-height: 20px;
}
.enterBox{
margin-top: 25px;
display: flex;
.cancelBox{
margin-right: 20px;
width: 100px;
height: 36px;
border-radius: 20px;
font-size: 16px;
color: #E5AC59;
line-height: 36px;
border: 1px solid #E5AC59;
text-align: center;
}
.confirmBox{
width: 100px;
height: 36px;
background: linear-gradient(90deg, #E9BA8B 0%, #E5AC59 100%);
border-radius: 20px;
font-size: 16px;
color: #ffffff;
line-height: 36px;
border: 1px solid #E5AC59;
text-align: center;
}
}
.shopCreatedBox{
margin-top: 25px;
width: 158px;
height: 104px;
background-image: url("https://image.fulllinkai.com/202112/24/fac5a4e8635d934c9e3a3da363900276.png");
background-size: cover;
}
.createdSHopBtn{
margin-top: 25px;
width: 200px;
height: 40px;
background: linear-gradient(90deg, #E9BA8B 0%, #E5AC59 100%);
border-radius: 20px;
font-size: 16px;
font-weight: 500;
color: #FFFFFF;
line-height: 40px;
text-align: center;
}
}
.createdClose{
position: absolute;
top: 300px;
right: 50%;
transform: translateX(50%);
width: 24px;
height: 24px;
background-image: url("https://image.fulllinkai.com/202112/24/612dbd14460583a936fbe1650935df0a.png");
background-size: cover;
z-index: 333;
}
}
}
}
</style>

View File

@ -0,0 +1,723 @@
<template>
<div class="my">
<div class="userBgBox">
<div class="user_bg backCover" v-bind:style="{ backgroundImage: 'url(' + bg + ')' }">
<div class='alignment_left' style='padding: 30px 0 0 20px'>
<div class="user_photo backCover" v-bind:style="{ backgroundImage: 'url(' + detail.avatar + ')' }"></div>
<div class=''>
<div class='alignment_left' style='margin-left: 22px'>
<div class='font18 color3 bold'>{{detail.nickname || '未填写'}}</div>
<div class='alignment_left' @click="goToUrl('editorUserData')">
<img class='editor_icon' src='https://image.fulllinkai.com/202207/01/ad7477186aa1e7a69b6dd28bae8aaf23.png' alt=''>
<div class='font12 color6'>编辑</div>
</div>
</div>
<van-image class="WeChatAuthorization" fit="contain" @click="authorization" src="https://image.fulllinkai.com/202207/01/5bbb03c673c8aee91f209d6c66d7ff31.png" alt="" />
</div>
</div>
</div>
</div>
<div class='vip_tabs_box'>
<div class="vip_pic backCover alignment" v-bind:style="{ backgroundImage: 'url(' + 'https://image.fulllinkai.com/202207/01/9517bd9cbb5f670246cf328445ee6952.png' + ')' }" v-if='detail.member == 1' @click='goToUrl("VIPIndex")'>
<div>
<div class='font14 colorff bold' style='margin-left: 63px' v-if='!detail.member_expire_time'>开通VIP超级会员</div>
<div class='font14 colorff bold' style='margin-left: 46px' v-else>VIP超级会员</div>
</div>
<div class='font13 bold colorff' style='opacity: 0.8;margin-right: 15px;' v-if='!detail.member_expire_time'>专享超值权益 >></div>
<div class='font13 bold colorff alignment_right' style='opacity: 0.8;margin-right: 15px' v-else>{{detail.member_expire_time}}
<img style='width: 5px;height: 10px;display: block;margin-left: 10px;margin-top: -1px' src='https://image.fulllinkai.com/202206/30/794ae58096304f177454c93daba14179.png' alt=''>
</div>
</div>
<div class='tabs_box alignment'>
<div class='tabs_item_box' v-for='(item,index) in tabsList' :key='index' @click="goToUrl(item.urlName)">
<img class='tabs_item_icon' :src='item.icon' alt=''>
<div class='font12 color3'>{{ $t(item.text) }}</div>
</div>
</div>
<div class='marqueeWrap_box' v-if='showGroup'>
<div class="marqueeWrap">
<div class="animateBox">
<div class="animate" :class="{ 'animate-up': animateUp }">
<div class='alignment' v-for="(item, index) in groupList" :key="index" @click='goToGroup(item)'>
<div class='alignment_left'>
<div class="head_pic backCover" :class="item.type === 'shop'? 'shop_pic':''" :style="{ backgroundImage: 'url(' + item.pic + ')' }"></div>
<div>
<div class='font12 color3 bold'>拼团中</div>
<div class='font10 color6'>还差<span style='color: #FFAC4A'>{{item.need_count}}</span>拼团</div>
</div>
</div>
<div class='alignment_right'>
<div class='goToJoin alignment_center color3 font11'>邀请好友</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div style='height: 15px;width: 100%;' v-if='showGroup'></div>
</div>
<div style='margin: 15px 20px' v-if='mobileShow'>
<div class='mobile-big-box alignment'>
<div class='mobile-box alignment_left'>
<img class='close-box' @click='mobileShow = false' src='https://image.fulllinkai.com/202203/08/0fb3ec31f29628d09d18135a826154fe.png' alt=''>
<div class='font13 color6' style='margin-top: -3px'>你还没绑定手机号,绑定后将更好地服务您</div>
</div>
<div class='mobile-bind-box alignment_center font12 colorTheme' @click='goToBind'>去绑定</div>
</div>
</div>
<div class="m_live_box" v-if="liveShow">
<div class="m_live alignment_left" @click="goToUrlId('liveList', liveData.id)">
<div class="m_live_to">
<van-image class="u_live_to" round fit="contain" :src="liveData.poster" alt="" />
<van-image class="u_live_to_icon" fit="contain" src="https://image.fulllinkai.com/202111/23/69812a694932506893e0e4572bd57cf2.gif" alt="" />
</div>
<div class="font13 color6">有人正在直播快来强势围观点击进入>></div>
</div>
</div>
<div class='operationBox'>
<myListComponent :isShop="detail.is_merchant == 0 ? false : true" :isDetail='detail' :isTemplate='2' :border="true" @updateData='updateData'></myListComponent>
</div>
<div class="logoBox" @click="clearLocalStorage">
<img class="logoImg" src="https://image.fulllinkai.com/202108/26/d9bb2c2d9f958a3d02ba96dff07a11a5.png" alt="" />
<div class="font11 text-center" style="color: #c2c2c2">
{{ $t('Full_Link_intelligent_to_provide_technical_service_support') }}
</div>
</div>
<van-popup v-model="showAccount" :close-on-click-overlay="false" :lock-scroll="true" :duration="0.5">
<div class="m_acc">
<div class="font18 text-center color3 bold" style="padding: 20px 0 5px">绑定手机号</div>
<div class="font12 text-center color9" style="padding: 0 0 10px">为了更好的服务您请绑定手机号</div>
<div class='mobile_box'>
<div class="alignment" style='padding-bottom: 10px'>
<van-field class="inputBox" type="text" v-model="mobile" placeholder="请输入手机号" />
</div>
<div class="alignment from_item_input">
<div class='font14 code_box' style='color: #707FFA' v-if='time == 60' @click.stop='getCode'>{{codeText}}</div>
<div class='font14 code_box color9' v-else>{{time}}</div>
<van-field class="inputBox" oninput="if(value.length>6)value=value.slice(0,6)" type="number" v-model="code" placeholder="请输入验证码" />
</div>
</div>
<div class="m_acc_bu f-fcc font16 colorff" @click="changeMobile">{{ $t('determine') }}</div>
<div class='close-btn' @click='showAccount=false'></div>
</div>
</van-popup>
<div class='my_list'>
<van-overlay :show="showCreatedModal" :lock-scroll="true">
<div class="wrapperMy">
<div class="createdBox" :style="{height: '286px'}">
<div class="createdBoxV2" :style="{height: '286px'}">
<div class="shopCreatedBox"></div>
<div class="font15 color6" style="margin-top: 15px;">您还不是服务商成为服务商即可</div>
<div class="font15 color6">搭建您的专属平台</div>
<div class="createdSHopBtn" @click="goToUrl('recruitingTeacher')">成为服务商</div>
</div>
<div class="createdClose" @click="showCreatedModal = false"></div>
</div>
</div>
</van-overlay>
</div>
</div>
</template>
<script>
import service from '@/utils/request'
import myListComponent from '@/components/myModule/my_list_component'
import { $toastText } from '@/config/toast'
export default {
computed: {},
components: { myListComponent },
data() {
return {
tabsList: [
{
urlName: 'myPlatform',
icon: 'https://image.fulllinkai.com/202207/01/a8cb410b5a6f5c1966852ff272bf2cb8.png',
text: 'my_Platform'
},
{
urlName: 'mySignUp',
icon: 'https://image.fulllinkai.com/202207/01/8f235ce3851a83b4ab7da1b0e8e1ab7c.png',
text: 'My_order'
},
{
urlName: 'myRecommend',
icon: 'https://image.fulllinkai.com/202207/01/784953aed78bcf0cf6e3b8e85a5171cb.png',
text: 'my_recommend'
}
],
detail: {},
qrcode: '',
bg: 'https://image.fulllinkai.com/202207/01/fe9e791027aeec5509358f995c676e84.png',
showCreatedModal: false,
liveShow: false,
mobileShow: false, //
code: '',
mobile: '',
showGroup: false,
groupList: [],
timer: null,
animateUp: false,
showAccount: false,
codeThrottle: true,
time: 60,
codeTime: null,
codeText: '获取验证码',
liveData: {}
}
},
watch: {
'$route'(to, from) {
if (from.name === 'editorUserData') { this.getData() }
},
time() {
if (this.time === 0) {
clearInterval(this.codeTime)
this.time = 60
this.codeThrottle = true
this.codeText = '重新获取'
}
}
},
methods: {
clearLocalStorage() {
localStorage.clear()
},
goToBind() {
this.showAccount = true
},
getCode() {
const vm = this
const data = {
mobile: vm.mobile
}
if (!vm.mobile) {
$toastText('手机号不能为空')
return
}
if (!(/^1(3|4|5|6|7|8|9)\d{9}$/.test(vm.mobile))) {
$toastText('手机号无效,请重新输入')
return
}
if (vm.codeThrottle) {
vm.codeThrottle = false
service.post('s/m/admin/plat/sendCode', data).then(data => {
setTimeout(() => {
vm.codeThrottle = true
}, 700)
if (data.status === 0) {
vm.time = 59
vm.codeTime = setInterval(() => {
vm.time--
}, 1000)
setTimeout(() => {
$toastText('验证码已发送')
}, 300)
} else if (data.status === 6) {
$toastText('请求频率过快,请稍后再试')
vm.codeThrottle = true
}
}).catch(error => {
vm.codeThrottle = true
console.log(error)
})
}
},
changeMobile() {
const vm = this
const data = {
mobile: vm.mobile,
code: vm.code
}
if (!vm.mobile) {
$toastText('手机号不能为空')
return
}
if (!(/^1(3|4|5|6|7|8|9)\d{9}$/.test(vm.mobile))) {
$toastText('手机号无效,请重新输入')
return
}
if (!vm.code) {
$toastText('验证码不能为空')
return
}
service.post(`s/h5/merchant/merchantUserBindMobile`, data).then(data => {
if (data.status === 1) {
return
}
if (data.status === 8) {
return $toastText('验证码有误')
}
if (data.status === 9) {
return $toastText('验证码过期')
}
if (data.status === 10) {
return $toastText('验证码已使用')
}
$toastText('绑定成功')
vm.showAccount = false
vm.getData()
})
},
authorization() {
const vm = this
localStorage.removeItem('saas_token')
vm.$authorization(vm.$shareCallback, vm.$store.state.app.merchant_id, 'my')
},
//
updateData() {
this.getData()
this.getGroupData()
},
scrollAnimate() {
const vm = this
this.animateUp = true
setTimeout(() => {
vm.groupList.push(vm.groupList[0])
vm.groupList.shift()
vm.animateUp = false
}, 3300)
},
goToGroup(e) {
const vm = this
if (e.is_initiator === 1) {
vm.$router.push({
name: 'groupOrder',
query: { order_id: e.m_order_id, type: e.type }
})
} else {
vm.$router.push({
name: 'groupData',
query: { order_id: e.m_order_id, type: e.type, history_id: e.id, id: e.type_id }
})
}
},
getGroupData() {
const vm = this
service.get(`s/h5/group/myGroups`).then(data => {
vm.groupList = data
if (vm.groupList && vm.groupList.length !== 0) {
vm.showGroup = true
console.log(vm.groupList, '-------------')
}
if (vm.groupList && vm.groupList.length > 1) {
this.timer = setInterval(this.scrollAnimate, 3500)
}
console.log(vm.showGroup, '-------------showGroup')
}).catch(error => {
console.log(error)
})
},
getData() {
const vm = this
const url = `s/h5/BusinessUser`
service.get(url).then(data => {
data.avatar = data.avatar.replace(/\/\d*$/, '/0')
vm.detail = data
if (data.avatar === 'https://images.ufutx.com/202108/06/e1b03db630b24fd818d1aa9967ce3fb1.png') {
// vm.authorization()
}
if (data.mobile) {
vm.mobileShow = false
} else {
vm.mobileShow = true
}
vm.qrcode = data.avatar
console.log(vm.mobileShow, 'vm.mobileShow---')
console.log(data, '7897')
}).catch(error => {
console.log(error)
})
},
getLiveData() {
const url = `/s/h5/live/list`
service.get(url).then(data => {
if (data.data.length > 0) {
data.data.forEach(item => {
if (item.status == 1) {
this.liveShow = true
}
if (item.poster && item.poster.indexOf('?') != -1) {
var urlArr = item.poster.split('?')
if (urlArr.length > 0) {
console.log(item.poster)
item.poster = urlArr[0]
}
}
})
this.liveData = data.data[0]
console.log(this.liveData, 'live=----------------')
}
}).catch(error => {
console.log(error)
})
},
goToUrl(url) {
if (url === 'myPlatform') {
if (this.detail.is_merchant) {
location.href = 'https://love.ufutx.com/api/official/merchat/auth/login'
} else {
this.showCreatedModal = true
}
return
}
this.$router.push({
name: url
})
},
goToUrlId(url, id) {
this.$router.push({
name: url,
params: { id: id }
})
}
},
destroyed() {
clearInterval(this.timer)
this.timer = null
},
activated() {
if (this.$route.query.jumpState) {
this.getData()
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
this.getData()
this.getGroupData()
this.getLiveData()
console.log(this.$i18n.t('Language_Settings'), '798798798')
}
}
</script>
<style lang="scss" scoped>
.my {
width: 100vw;
min-height: 100vh;
background: #ffffff;
}
.userBgBox {
width: 100%;
.user_bg{
width: 100%;
height: 180px;
.user_photo{
width: 62px;
height: 62px;
border: 1px solid #e2e2e2;
border-radius: 50%;
}
.editor_icon{
width: 12px;
height: 12px;
display: block;
margin: 0 2px 0 10px;
}
.WeChatAuthorization{
width: 120px;
height: 32px;
display: block;
margin-left: 15px;
margin-top: 7px;
}
}
}
.vip_tabs_box{
margin: -56px 20px 15px 20px;
box-shadow: 0 4px 10px 0 rgba(127, 132, 254, 0.08);
border-radius: 8px;
.vip_pic{
width: 100%;
height: 40px;
}
.tabs_box{
padding: 15px 30px;
border-radius: 8px;
background: #ffffff;
.tabs_item_box{
text-align: center;
.tabs_item_icon{
width: 22px;
height: 22px;
display: block;
margin: 0 auto 6px auto;
}
}
}
.marqueeWrap_box{
padding: 8px 10px;
margin: 0 15px;
background: #f8f8f8;
border-radius: 8px;
.marqueeWrap {
height: 35px;
overflow: hidden;
display: flex;
.animateBox {
flex: none;
width: 100%;
height: 100%;
.animate {
width: 100%;
height: 100%;
.head_pic{
width: 62px;
height: 35px;
border-radius: 6px;
margin-right: 8px;
}
.shop_pic{
width: 35px;
}
.goToJoin{
width: 72px;
height: 22px;
border-radius: 13px;
border: 1px solid #D8D8D8;
}
}
.animate-up {
transition: all 1s;
margin-top: -35px;
flex: none;
width: 100%;
}
}
}
}
}
.mobile-big-box{
padding: 11px 10px 11px 8px;
box-shadow: 0 2px 14px 0 rgba(0, 0, 0, 0.06);
background: #ffffff;
border-radius: 8px;
.close-box{
width:12px;
height: 12px;
display: block;
margin-right: 4px;
}
.mobile-bind-box{
width: 52px;
height: 22px;
border-radius: 13px;
border: 1px solid rgba(112, 127, 250, 0.3);
}
}
.m_live_box {
padding: 0 20px;
background: #ffffff;
.m_live {
width: 100%;
height: 56px;
background: #F2F3FF;
border-radius: 28px;
.m_live_to {
width: 32px;
height: 32px;
border-radius: 50%;
border: 2px solid #96a2ff;
box-sizing: border-box;
position: relative;
margin-right: 10px;
margin-left: 17px;
.u_live_to {
width: 100%;
height: 100%;
border-radius: 50%;
}
.u_live_to_icon {
width: 14px;
height: 10px;
position: absolute;
background-color: #96a2ff;
border-radius: 10px;
bottom: -2px;
right: -2px;
z-index: 11;
}
}
}
.icon {
width: 26px;
height: 26px;
display: block;
margin-bottom: 1px;
}
.AngleIcon {
width: 5px;
height: 10px;
display: block;
margin-right: 15px;
}
.line {
width: 100%;
height: 1px;
background: #f5f5f5;
margin: 20px 0;
}
}
.operationBox{
margin: 15px 20px;
padding-bottom: 20;
background: #ffffff;
border-radius: 12px;
}
.logoBox {
width: 100vw;
padding: 20px 0 140px 0;
.logoImg {
width: 51px;
height: 18px;
display: block;
margin: 0 auto 1px auto;
}
}
.m_acc {
width: 300px;
padding-bottom: 35px;
.alignment{
padding: 0;
}
.mobile_box{
padding: 0 20px;
.inputBox{
/*width: 74%;*/
font-size: 16px;
color: #333333;
outline: none;
appearance: none;
border-bottom: 1px solid #f5f5f5;
padding-top: 11px;
padding-left: initial;
padding-bottom: 8px;
}
.from_item_input{
position: relative;
.code_box{
position: absolute;
//bottom: 13px;
right: 0;
z-index: 1;
}
.van-cell{
padding-right: 90px;
}
}
}
.m_acc_bu {
width: 200px;
height: 36px;
background: linear-gradient(92deg, #8c9bff 0%, #707ffa 100%);
border-radius: 20px;
margin: 40px auto 0;
}
}
.close-btn{
position: absolute;
bottom: -50px;
left: 50%;
transform: translateX(-50%);
height: 20px;
width: 20px;
background-image: url("https://image.fulllinkai.com/202203/08/0119b47bbda33be02d0a4f6c60558602.png");
background-size: cover;
}
.my_list{
::v-deep .wrapperMy {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
.createdBox{
margin-top: -80px;
position: relative;
width: 300px;
height: 184px;
background: #FFFFFF;
border-radius: 12px;
.createdBoxV2{
display: flex;
flex-direction: column;
align-items: center;
width: 300px;
height: 184px;
.createdText1{
margin-top: 25px;
height: 25px;
font-size: 18px;
font-weight: 500;
color: #333333;
line-height: 25px;
}
.createdText2{
height: 20px;
font-size: 14px;
font-weight: 400;
color: #999999;
line-height: 20px;
}
.enterBox{
margin-top: 25px;
display: flex;
.cancelBox{
margin-right: 20px;
width: 100px;
height: 36px;
border-radius: 20px;
font-size: 16px;
color: #E5AC59;
line-height: 36px;
border: 1px solid #E5AC59;
text-align: center;
}
.confirmBox{
width: 100px;
height: 36px;
background: linear-gradient(90deg, #E9BA8B 0%, #E5AC59 100%);
border-radius: 20px;
font-size: 16px;
color: #ffffff;
line-height: 36px;
border: 1px solid #E5AC59;
text-align: center;
}
}
.shopCreatedBox{
margin-top: 25px;
width: 158px;
height: 104px;
background-image: url("https://image.fulllinkai.com/202112/24/fac5a4e8635d934c9e3a3da363900276.png");
background-size: cover;
}
.createdSHopBtn{
margin-top: 25px;
width: 200px;
height: 40px;
background: linear-gradient(90deg, #E9BA8B 0%, #E5AC59 100%);
border-radius: 20px;
font-size: 16px;
font-weight: 500;
color: #FFFFFF;
line-height: 40px;
text-align: center;
}
}
.createdClose{
position: absolute;
top: 300px;
right: 50%;
transform: translateX(50%);
width: 24px;
height: 24px;
background-image: url("https://image.fulllinkai.com/202112/24/612dbd14460583a936fbe1650935df0a.png");
background-size: cover;
z-index: 333;
}
}
}
}
</style>

View File

@ -0,0 +1,81 @@
<template>
<!--<div class="number-grow-warp">-->
<span ref="numberGrow" :data-time="time" class="number-grow" :data-value="value">0</span>
<!--</div>-->
</template>
<script>
export default {
props: {
time: {
type: Number,
default: 2
},
value: {
type: Number,
default: 999999999
}
},
watch: {
value(newValue, oldValue) {
if (oldValue === 0) {
this.start = 0
this.current = 0
this.value = newValue
this.numberGrow(this.$refs.numberGrow)
return
}
this.start = newValue
this.current = oldValue
this.numberGrow(this.$refs.numberGrow)
}
},
data() {
return {
current: 0,
start: 0
// time: 2,
// value: 720000
}
},
methods: {
numberGrow(ele) {
const _this = this
const step = (_this.value * 10) / (_this.time * 1000)
// let current = 0
// let start = 0
// console.log(_this.start, '7897978')
let t = setInterval(function() {
_this.start += step
if (_this.start > _this.value) {
clearInterval(t)
_this.start = _this.value
t = null
}
if (_this.current === _this.start) {
return
}
_this.current = _this.start
_this.$el.innerHTML = parseInt(_this.start)
}, 20)
}
},
mounted() {
this.current = 0
this.start = 0
this.numberGrow(this.$refs.numberGrow)
}
}
</script>
<style lang="scss" scoped>
.number-grow-warp{
transform: translateZ(0);
}
.number-grow {
/*letter-spacing: 2.67px;*/
/*margin:110px 0 20px;*/
/*display: block;*/
/*line-height:64px;*/
}
</style>

982
src/components/payModal.vue Normal file
View File

@ -0,0 +1,982 @@
<template>
<div class="userData" v-if="show">
<van-popup v-model="showBuyData" :close-on-click-overlay="false" :click-overlay="false" :lock-scroll="true" :duration="0.5" position="bottom">
<div class="buyDataBox">
<div class="m_avt_lst">
<div class="buyPic backCover" :class="type == 'shop'? 'shopClass':''" v-bind:style="{ backgroundImage: 'url(' + (detail.pic || detail.thumb || detail.icon) + ')' }"></div>
<div class="m_lst_ri">
<div>
<div class="font15 ellipsis_1 bold m_w_220" >{{ detail.title }}</div>
<div class="font12 color6 m_t_5" v-if="(detail.sku &&detail.sku.length>0) ? detail.sku[selectSkuIndex].name : false">规格{{ detail.sku[selectSkuIndex].name }}</div>
</div>
<div class="font15 bold hour c_fb9830" v-if="type == 'course'">
<div class="period">{{ detail.videos_count }}{{ $t('Class_time') }}</div>
<div class="money">
<div>{{ detail.user_count }}{{ $t('Sign_up') }}</div>
<div class="hourMoney">¥{{detail.selectGroup ==1 ? groupPrice : price }}</div>
</div>
</div>
<div class="font15 bold c_fb9830" v-else>
<span v-if="detail.price != 0">¥</span
><span class="font18 m_l_2">{{ price == 0 ? $t('free') : detail.selectGroup ==1 ? groupPrice : price }}</span>
</div>
</div>
</div>
</div>
<div class="pa_t_15">
<worldPhone v-if="type !== 'activity'&&type !== 'shop'" @getWorldPhoneData="getWorldPhoneData" :linkmen='detail.linkmen'></worldPhone>
<div class="m_sku_lst" v-if="detail.selectGroup ==1?(detail.group.sku && detail.group.sku.length > 0): (detail.sku && detail.sku.length > 0)">
<div class="m_skuLst_tt font14 color3 bold">{{ $t('specification') }}</div>
<div class="m_skuLst f-fc">
<div
:class="[selectSkuIndex == index ? 'u_skuLst sel f-fcc' : 'u_skuLst f-fcc',(type == 'activity'||type =='service')&&item.can_buy != 1 ? 'u_skuLst ui-sku-full-through' :'' ]"
v-for="(item, index) in (detail.selectGroup ==1? detail.group.sku : detail.sku)"
:key="index"
@click.stop="selectSku(index, item)"
>
<div class="ui-sku-full-through" v-if="(type == 'activity'||type =='service')&&item.can_buy != 1"> {{ item.name }}</div>
<div v-else> {{ item.name }}</div>
</div>
</div>
</div>
<div class="alignment m_t_20" v-if="type === 'shop'">
<div class="font14 color3 bold">{{ $t('number') }}</div>
<div class="skuNumBox">
<div class="skuLeft alignment_center" @click="reductionSku">
<div class="ReductionIcon" v-if="skuNum == 1"></div>
<div class="ReductionIcon1" v-else></div>
</div>
<div class="skuMiddle alignment_center">{{ skuNum }}</div>
<div class="skuRight alignment_center" @click="addSku">
<img
class="addIcon"
src="https://images.ufutx.com/202107/29/6c63598a0868f4a06e9677fe2d63b1db.png"
alt=""
/>
</div>
</div>
</div>
<div class="alignment m_t_13" v-if="type === 'shop'">
<div class="font14 color3 bold">{{ $t('totalPrice') }}</div>
<div class="font14 bold c_ffac4a">¥{{ shopPrice }}</div>
</div>
<div class="detailed m_t_13" v-if="type === 'shop'">
<div class="font14 color3 bold">{{ $t('address') }}</div>
<div @click="openWX">
<div
class="font14 color6 text-right ellipsis_1 max_w_240"
v-if="detailedAddress && detailedAddress != null && detailedAddress != undefined"
>
{{ detailedAddress }}
</div>
<div v-else class="alignment_right">
<div class="font14 color6">{{addressText}}</div>
<img
class="AngleIcon"
src="https://images.ufutx.com/202107/29/bac25c7ac07375c8b3928df436c0deda.png"
alt=""
/>
</div>
</div>
</div>
<div class='alignment coupon_top' v-if='detail.selectGroup !=1 &&stateList && stateList.length != 0'>
<div class='font14 color3 bold'>商家优惠券</div>
<div class='alignment_right' @click='showCoupons = true'>
<div class='font12 color9 m_t_-1' v-if='couponsState == 999'>请选择优惠券</div>
<div class='font15 bold c_ff5136' v-else><span class='font12'>-¥</span>{{discount_amount}}</div>
<img style='width: 5px;height: 10px;display: block;margin-left: 6px' src='https://image.fulllinkai.com/202207/14/794ae58096304f177454c93daba14179.png' alt=''>
</div>
</div>
<div class='agreement_box alignment_left' v-if='detail.agree_title'>
<img v-if='!chooseState' @click='chooseAgreement' class='chooseIcon' src='https://image.fulllinkai.com/202110/25/ed69b714884586a15cef958658d2e696.png' alt=''>
<img v-else @click='chooseAgreement' class='chooseIcon' src='https://image.fulllinkai.com/202112/29/34efc74efaf42c47f905ca7c9f4ab608.png' alt=''>
<div class='font12 color9'>同意并阅读<span class='colorTheme' @click.stop='toToagree'>{{detail.agree_title}}</span></div>
</div>
<div class='alignment coupon_top' v-if="type != 'shop'">
<div class='font14 color3 bold'>合计</div>
<div class='font14 bold' style='color: #FFAC4A'>¥{{detail.selectGroup !=1 ? total_price : groupPrice}}</div>
</div>
<div class="payButtonV2 font16 colorff bold alignment_center" @click.stop="paySubmit" v-if='detail.selectGroup == 1'>{{ $t('determine') }}</div>
<div class="payButton font16 colorff bold alignment_center" v-else @click="paySubmit">{{ $t('determine') }}</div>
</div>
<img
@click.stop="closeModal"
class="cancelIcon"
src="https://image.fulllinkai.com/202110/23/78698e898cd570e5e7751c323e4a5cb7.png"
alt=""
/>
</van-popup>
<div class='coupons_box'>
<van-popup v-model="showCoupons" position="right" :duration="0.5" :style="{ height: '100%',width: '100%' }">
<div class="coupons_content">
<div class='myCoupons_box' v-for="(item, index) in stateList" :key="index">
<div class='m_coupons_box'>
<div class='alignment_left'>
<div class="m-r-8">
<img class='discount_icon' v-if='item.coupon.coupon_type == 3' src='https://image.fulllinkai.com/202207/14/98a3d036b53cf1468bcb9100cad50afd.png' alt=''>
<img class='discount_icon' v-else-if='item.coupon.coupon_type == 2' src='https://image.fulllinkai.com/202207/14/4599e9f5623e25577cc606171b54d32f.png' alt=''>
<img class='discount_icon' v-else src='https://image.fulllinkai.com/202207/20/8f55c9c566385c2f84f54132dbcecca1.png' alt=''>
</div>
<div class="m_coupon_box">
<div class='alignment'>
<div class='font16 color3 bold' v-if='item.coupon.coupon_type == 2 || item.coupon.coupon_type == 3'>惊喜{{item.coupon.coupon_type == 2 ? '折扣' : '减扣'}}</div>
<div class='font16 color3 bold' v-else>惊喜免费券</div>
<div class='font13 m_coupon_price' v-if='item.coupon.coupon_type == 2 || item.coupon.coupon_type == 3'>最高可抵扣¥{{item.coupon.discount_amount}}</div>
</div>
<div class='font13 color6 p-t-8'>服务优惠劵</div>
<div class='font26 bold m_coupon_price_b' v-if='item.coupon.coupon_type == 2 || item.coupon.coupon_type == 3'>
<div v-if='item.coupon.coupon_type == 3'><span class='font12 f-w-i' >¥</span>{{item.coupon.discount_amount}}</div>
<div v-else>{{item.coupon.discount_rate}}<span class='font12 f-w-i'></span></div>
</div>
<div class='font20 bold m_coupon_free' v-else>
免费
</div>
<div class='choose_box' @click='chooseCoupons(item,index)'>
<img class='choose_icon' v-if='couponsState == index' src='https://image.fulllinkai.com/202207/14/b4d1838f63ca22e215ae75a5501ff3a6.png' alt=''>
<div class='uncheck_choose' v-else></div>
</div>
</div>
</div>
<div class='line'></div>
<div class='ellipsis_1 font12 color9' style='max-width: 230px'>限于{{item.coupon.name}}</div>
</div>
</div>
</div>
</van-popup>
<img class='return_icon' v-if='showCoupons' src='https://image.fulllinkai.com/202207/25/bb6b4dbd0eaed6a7c3aa66cd3e7e6447.png' alt='' @click='couponReturn'>
</div>
</div>
</template>
<script>
import service from '@/utils/request'
import worldPhone from '@/components/worldPhone'
import { $toastClear, $toastLoading, $toastText, $toastSuccess } from '@/config/toast'
import wx from 'weixin-js-sdk'
export default {
name: 'PayModal',
components: { worldPhone },
props: ['id', 'detail', 'show', 'type', 'coupons_ids', 'stateList', 'history_id'],
data() {
return {
couponsState: 999,
showCoupons: false,
chooseCouponData: {},
mobile: '',
name: '',
AreaValue: '+86',
price: 0,
groupPrice: 0,
discount_amount: 0,
selectSkuIndex: 0, // sku
total_price: 0, //
chooseState: false,
payThrottle: true,
skuNum: 1,
shopPrice: 0,
newPrice: 0,
sku_id: '',
addressText: '获取收货地址',
address: {
userName: '',
postalCode: '',
provinceName: '',
cityName: '',
countryName: '',
detailInfo: '',
nationalCode: '',
telNumber: ''
},
detailedAddress: '',
videoIndex: -1,
url: ''
}
},
watch: {
//
'show'(newV, oldV) {
console.log(newV, 'newV')
this.price = this.detail.one_price || this.detail.original_price || 0
if (this.detail.sku && this.detail.sku.length > 0) {
this.total_price = this.detail.sku[0].charge || this.detail.sku[0].price || 0
} else {
this.total_price = this.detail.charge || 0
}
if (this.detail.selectGroup === 1) {
this.groupPrice = (this.detail.group.sku && this.detail.group.sku.length > 0 && this.detail.group.sku[0].discount_price) || this.detail.group.price
if (this.type === 'shop') {
this.shopPrice = this.detail.group.sku[0].discount_price
this.newPrice = this.detail.group.sku[0].discount_price
this.sku_id = this.detail.group.sku[0].sku_id
}
}
console.log(this.detail, 'detiail----')
if (this.type === 'course') {
// if (this.coupons_ids) {
// this.discount_amount = this.detail.discount_amount
// }
this.url = `s/h5/course/pay/Business`
} else if (this.type === 'shop') {
if (this.detail.pay_type === 'wechat' && this.detail.selectGroup !== 1) {
this.shopPrice = this.detail.sku[0].price
this.newPrice = this.detail.sku[0].price
}
this.url = `s/h5/shops/BusinessPayOrder`
} else {
if (this.detail.sku && this.detail.sku.length > 0) {
this.discount_amount = this.detail.sku[0].discount_amount
}
this.url = `s/h5/communities/BusinessPayOrder`
}
this.showBuyData = newV
},
//
'detail'() {
//
if (this.detail.sku && this.detail.sku.length > 0) {
// this.selectSkuIndex = 0
this.price = this.detail.sku[this.selectSkuIndex].price
this.discount_amount = this.detail.sku[this.selectSkuIndex].discount_amount
this.total_price = this.detail.sku[this.selectSkuIndex].charge || this.detail.sku[this.selectSkuIndex].price || 0
} else {
this.total_price = this.detail.charge
}
}
},
methods: {
//
getWorldPhoneData(e) {
if (e.type == 'name') {
this.name = e.name
} else if (e.type == 'mobile') {
this.mobile = e.name
} else if (e.type == 'AreaValue') {
this.AreaValue = e.name
}
},
//
reductionSku() {
if (this.skuNum === 1) {
this.shopPrice = this.newPrice
return
}
this.skuNum--
this.shopPrice = (this.newPrice * this.skuNum).toFixed(2)
},
//
addSku() {
this.skuNum++
this.shopPrice = (this.newPrice * this.skuNum).toFixed(2)
},
//
closeModal() {
this.selectSkuIndex = 0
this.$emit('update:show', false)
this.$emit('changeCoupon')
},
//
selectSku(index) {
console.log(this.detail, index, '*********')
if (this.detail.sku[index].total_limit_num && !this.detail.sku[index].can_buy) {
return $toastText('该规格报名人数已满')
}
this.selectSkuIndex = index
this.price = this.detail.sku[index].price
if (this.detail.selectGroup === 1) {
this.groupPrice = this.detail.group.sku[index].discount_price
}
this.total_price = this.detail.sku[index].charge || this.detail.sku[index].price
this.skuNum = 1
if (this.type === 'shop') {
if (this.detail.selectGroup === 1) {
this.shopPrice = this.detail.group.sku[index].discount_price
this.newPrice = this.detail.group.sku[index].discount_price
this.sku_id = this.detail.group.sku[index].sku_id
} else {
this.shopPrice = this.detail.sku[index].price
this.newPrice = this.detail.sku[index].price
this.sku_id = this.detail.sku[index].sku_id
}
}
console.log(this.price, 'price*******')
this.discount_amount = this.detail.sku[index].discount_amount
this.sdkName = this.detail.sku[index].name
},
//
openWX() {
const vm = this
if (vm.isWxMini) {
this.$router.push({ name: 'editAddress', query: { id: vm.id }})
} else {
wx.openAddress({
success: function(res) {
vm.address.userName = res.userName //
vm.address.postalCode = res.postalCode //
vm.address.provinceName = res.provinceName //
vm.address.cityName = res.cityName //
vm.address.countryName = res.countryName //
vm.address.detailInfo = res.detailInfo //
vm.address.nationalCode = res.nationalCode //
vm.address.telNumber = res.telNumber //
vm.detailedAddress = `${res.provinceName}` + `${res.cityName}` + `${res.countryName}` + `${res.detailInfo}`
const data = {
detailedAddress: vm.detailedAddress,
userName: res.userName,
telNumber: res.telNumber
}
localStorage.setItem('detailedAddress', JSON.stringify(data))
},
cancel: function(errMsg) {
}
})
}
},
//
chooseAgreement() {
this.chooseState = !this.chooseState
},
//
toToagree() {
const vm = this
console.log(vm.id, '33-3')
vm.$router.push({
name: 'customAgreement',
params: { id: vm.id }
})
},
//
chooseCoupons(e, index) {
console.log(e, index, 'index33----')
if (this.couponsState === index) {
this.couponsState = 999
this.chooseCouponData = {}
} else {
this.couponsState = index
this.chooseCouponData = {
id: e.id,
discount_amount: e.coupon.discount_amount
}
}
if (this.type === 'course') {
this.discount_amount = e.coupon.discount_amount
}
console.log(e.coupon.discount_amount, 'this.total_price----')
console.log(this.chooseCouponData, 'chooseCouponData')
this.showCoupons = false
this.$emit('changeCoupon', this.chooseCouponData)
// this.getDetail()
},
//
couponReturn() {
this.showCoupons = false
},
//
paySubmit() {
const vm = this
if (this.history_id) { // id
if (vm.type !== 'activity' && vm.type !== 'shop') {
var regu = '^[ ]+$'
var re = new RegExp(regu)
if (!vm.name || re.test(vm.name)) {
vm.name = ''
return $toastText('请输入联系人')
}
if (!vm.mobile) {
return $toastText('请输入手机号码')
}
if (vm.AreaValue + '' === '+86') {
if (!/^1(3|4|5|6|7|8|9)\d{9}$/.test(vm.mobile)) {
$toastText('手机号码错误')
return
}
}
}
console.log(vm.address, 'address')
if (vm.type === 'shop' && !vm.address.telNumber) {
if (!vm.vm.address.telNumber) { $toastText('请填写收货地址') }
return
}
if (vm.detail.agree_title && !vm.chooseState) {
return $toastText(`请选同意并阅读《${vm.detail.agree_title}`)
}
vm.$emit('joinIn', vm.groupPrice, vm.selectSkuIndex, vm.name || vm.address.userName, vm.mobile || vm.address.telNumber, vm.AreaValue, vm.skuNum, vm.detailedAddress)
return
}
if (vm.detail.sku && vm.detail.sku.length > 0 && vm.detail.sku[vm.selectSkuIndex] && vm.detail.sku[vm.selectSkuIndex].total_limit_num && !vm.detail.sku[vm.selectSkuIndex].can_buy) {
return $toastText(`请选择规格`)
}
console.log('12312---')
if (vm.type === 'activity') {
let orderData = {}
if (vm.detail.sku && vm.detail.sku.length > 0) {
orderData = vm.detail.sku[vm.selectSkuIndex]
} else {
orderData.num = 1
orderData.price = 0
orderData.name = '--'
}
orderData.title = vm.detail.title
orderData.skuIndex = vm.selectSkuIndex
orderData.selectGroup = vm.detail.selectGroup
orderData.groupPrice = vm.groupPrice
orderData.id = vm.detail.id
orderData.coupons_ids = vm.coupons_ids
orderData.anchor_id = vm.detail.anchor_id
orderData.pic = vm.detail.pic
orderData.insurance = vm.detail.insurance
orderData.linkmen = vm.detail.linkmen
orderData.history_id = vm.history_id
console.log(orderData, 'orderData===')
if (vm.detail.agree_title && !vm.chooseState) {
return $toastText(`请选同意并阅读《${vm.detail.agree_title}`)
}
vm.$emit('update:show', !this.show)
this.$router.push({
name: 'confirmOrder',
query: { orderData: JSON.stringify(orderData) }
})
} else {
var regu = '^[ ]+$'
var re = new RegExp(regu)
let data = ''
if (vm.type === 'course') {
data = {
pay_type: 'wechat',
course_id: vm.id,
buy_type: vm.detail.selectGroup === 1 ? 'group' : 'normal',
cash: vm.detail.selectGroup === 1 ? vm.groupPrice : vm.total_price,
name: vm.name,
mobile: vm.mobile,
linkmen: [{ name: vm.name, mobile: vm.mobile }],
area_code: vm.AreaValue,
user_coupons_id: vm.detail.selectGroup === 1 ? '' : vm.chooseCouponData.id || '',
from_user_id: localStorage.getItem('from_user_id'),
openid: localStorage.getItem('openid')
}
} else if (vm.type === 'shop') {
data = {
id: vm.detail.id,
num: vm.skuNum,
name: vm.address.userName,
mobile: vm.address.telNumber,
linkmen: [{ name: vm.address.userName, mobile: vm.address.telNumber }],
address: vm.detailedAddress,
price: vm.shopPrice,
sku_id: vm.detail.sku[vm.selectSkuIndex] ? vm.detail.sku[vm.selectSkuIndex].sku_id : '',
buy_type: vm.detail.selectGroup === 1 ? 'group' : 'normal'
}
if (!vm.address.telNumber) {
$toastText('请填写收货地址')
return
}
} else if (vm.detail.sku && vm.detail.sku.length > 0) {
data = {
id: vm.id,
num: vm.skuNum,
name: vm.name,
area_code: vm.AreaValue,
mobile: vm.mobile,
linkmen: [{ name: vm.name, mobile: vm.mobile }],
user_coupons_id: vm.chooseCouponData.id || '',
sku_id: vm.detail.sku[vm.selectSkuIndex].sku_id,
merchant_id: vm.$store.state.app.merchant_id,
anchor_id: vm.detail.anchor_id,
buy_type: vm.detail.selectGroup === 1 ? 'group' : 'normal'
}
} else {
data = {
id: vm.id,
name: vm.name,
area_code: vm.AreaValue,
mobile: vm.mobile,
anchor_id: vm.detail.anchor_id,
user_coupons_id: vm.chooseCouponData.id || '',
merchant_id: vm.$store.state.app.merchant_id,
price: vm.detail.selectGroup === 1 ? vm.groupPrice : vm.detail.price
}
}
if (vm.type !== 'activity' && vm.type !== 'shop') {
if (!vm.name || re.test(vm.name)) {
vm.name = ''
return $toastText('请输入联系人')
}
if (!vm.mobile) {
return $toastText('请输入手机号码')
}
if (vm.AreaValue + '' === '+86') {
if (!/^1(3|4|5|6|7|8|9)\d{9}$/.test(vm.mobile)) {
$toastText('手机号码错误')
return
}
}
}
if (vm.detail.agree_title && !vm.chooseState) {
return $toastText(`请选同意并阅读《${vm.detail.agree_title}`)
}
if (vm.payThrottle) {
// vm.payThrottle = false
}
if (vm.payThrottle) {
vm.payThrottle = false
var isWxMini = window.__wxjs_environment === 'miniprogram' //
console.log(isWxMini, 'isWxMini-----')
if (isWxMini) {
vm.showBuyData = false
data.type = 'service'
data.type_id = vm.id
service
.post(`/s/h5/communities/BusinessPayOrder/v2`, data)
.then(data => {
vm.$emit('update:show', !this.show)
const { trade_no, need_pay } = data
vm.payThrottle = true
if (need_pay == 1) {
isWxMiniFnV2(trade_no).then((res) => {
if (res.is_pay == 1) {
$toastText('支付成功')
vm.showBuyData = false
setTimeout(() => {
vm.payThrottle = true
vm.$emit('changeCoupon')
if (vm.detail.flow && vm.detail.flow.length != 0) {
vm.$router.push({
name: 'stepsOperation',
params: { id: vm.id },
query: { jumpType: 'service' }
})
}
}, 1000)
} else {
$toastText('系统未检测到支付订单,请稍后重试')
vm.$emit('changeCoupon')
}
})
} else {
$toastSuccess(vm.$i18n.t('Pay_success'))
setTimeout(() => {
vm.payThrottle = true
vm.$emit('changeCoupon')
if (vm.detail.flow && vm.detail.flow.length != 0) {
vm.$router.push({
name: 'stepsOperation',
params: { id: vm.id },
query: { jumpType: 'service' }
})
}
}, 1000)
}
})
} else {
service.post(vm.url, data).then(data => {
vm.$emit('update:show', !this.show)
if (vm.type === 'course' && data.status == 1) {
vm.$emit('changeCoupon')
return
}
if (data.wx_pay && data.wx_pay.length === 0) {
$toastSuccess(vm.$i18n.t('registration_success'))
vm.showBuyData = false
if (vm.type === 'shop') {
vm.$emit('shopBuy', vm.shopPrice, data.id)
return
}
setTimeout(() => {
vm.payThrottle = true
if (vm.detail.flow && vm.detail.flow.length != 0) {
vm.$router.push({
name: 'stepsOperation',
params: { id: vm.id },
query: { jumpType: vm.type }
})
}
vm.$emit('changeCoupon')
}, 1000)
return
}
const wxconfig = data.config
if (data.attributes) {
vm.orderId = data.attributes.id
vm.trade_no = data.attributes.out_trade_no
vm.trade_id = data.id || data.attributes.order_id
}
if (data.mweb_url) {
vm.payThrottle = true
window.location.href = data.mweb_url
} else {
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
{
appId: wxconfig.appId,
timeStamp: wxconfig.timestamp,
nonceStr: wxconfig.nonceStr,
package: wxconfig.package,
signType: wxconfig.signType,
paySign: wxconfig.paySign
},
function(res) {
if (res.err_msg === 'get_brand_wcpay_request:ok') {
$toastText('支付成功')
vm.showBuyData = false
setTimeout(() => {
$toastClear()
vm.payThrottle = true
if (vm.detail.selectGroup === 1) {
vm.$router.push({
name: 'groupOrder',
query: { order_id: vm.trade_id, type: vm.type }
})
return
}
if (vm.detail.flow && vm.detail.flow.length != 0) {
vm.$router.push({
name: 'stepsOperation',
params: { id: vm.id },
query: { jumpType: 'service' }
})
} else {
if (vm.type === 'shop') {
vm.$emit('shopBuy', vm.shopPrice, vm.trade_id)
}
vm.$emit('changeCoupon')
}
}, 1000)
} else if (res.err_msg === 'get_brand_wcpay_request:cancel') {
$toastText('取消支付')
vm.payThrottle = true
vm.$emit('changeCoupon')
} else if (res.err_msg === 'get_brand_wcpay_request:fail') {
$toastText('网络异常,请重试')
vm.payThrottle = true
vm.$emit('changeCoupon')
}
}
)
}
})
.catch(error => {
console.log(error)
})
}
}
}
}
},
mounted() {
if (localStorage.getItem('detailedAddress')) {
this.detailedAddress = JSON.parse(localStorage.getItem('detailedAddress')).detailedAddress
this.address.userName = JSON.parse(localStorage.getItem('detailedAddress')).userName
this.address.telNumber = JSON.parse(localStorage.getItem('detailedAddress')).telNumber
}
}
}
</script>
<style lang="scss" scoped>
.userData > .van-popup {
top: auto !important;
min-height: 200px;
border-radius: 12px 12px 0 0 !important;
}
.buyDataBox {
padding: 0 15px;
margin-top: 36px;
position: relative;
.buyPic {
background-position: center;
width: 142px;
height: 80px;
border-radius: 8px;
margin-right: 8px;
}
.shopClass{
width: 100px;
height: 100px;
}
.buyTitle {
margin: 12px 0 7px 0;
}
.line {
width: 100%;
height: 1px;
background: #f5f5f5;
margin: 13px 0;
}
}
.m_avt_lst {
display: flex;
align-items: stretch;
.m_lst_ri {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
.m_w_220{
max-width: 220px;
}
}
}
.m_sku_lst {
margin-top: 20px;
.m_skuLst_tt {
}
.m_skuLst {
flex-wrap: wrap;
.u_skuLst {
position: relative;
padding: 5px 15px;
background: #f5f5f5;
border-radius: 4px;
color: #666666;
margin: 15px 10px 0 0;
.ui-sku-full-through{
background: #f5f5f5!important;
color: #666666;
text-decoration: line-through;
}
}
.u_skuLst.sel {
background: #f2f3ff;
color: #707ffa;
}
.u_skuLst.ui-sku-full-through{
background: #f5f5f5!important;
color: #666666;
text-decoration: line-through;
}
}
}
.payButton, .payButtonV2 {
width: 220px;
height: 40px;
border-radius: 20px;
margin: 20px auto;
background: linear-gradient(90deg, #8c9bff 0%, #707ffa 100%);
}
.payButtonV2{
background: linear-gradient(90deg, #FFC485 0%, #FFA653 100%);
}
.cancelIcon {
width: 14px;
height: 14px;
position: absolute;
right: 15px;
top: 15px;
}
.coupons_box{
.return_icon{
width: 80px;
height: 80px;
position: fixed;
right: 0;
bottom: 40px;
z-index: 999999999;
}
}
</style>
<style lang='scss'>
.coupons_box{
.van-popup{
overflow-y: auto!important;
background: #f2f3f5!important;
border-radius: initial!important;
top: 50%!important;
}
.myCoupons_box{
padding: 15px 15px 0 15px;
.m_coupons_box{
padding: 16px 12px 12px 12px;
background: #ffffff;
border-radius: 12px;
.discount_icon{
width: 50px;
height: 50px;
display: block;
}
.choose_box{
position: absolute;
right: 0;
top: 12px;
.uncheck_choose{
width: 20px;
height: 20px;
border-radius: 50%;
background: #f5f5f5;
}
.choose_icon{
width: 20px;
height: 20px;
display: block;
}
}
.line{
width: 100%;
border: 1px dashed #d8d8d8;
margin: 16px 0 11px 0;
}
}
}
}
.skuNumBox {
//width: 88px;
height: 22px;
border: 1px solid #ececec;
border-radius: 12px;
overflow: hidden;
.skuLeft {
float: left;
width: 24px;
height: 22px;
border-right: 1px solid #ececec;
.ReductionIcon,
.ReductionIcon1 {
width: 8px;
height: 1px;
background: #d8d8d8;
display: block;
}
.ReductionIcon1 {
background: #666666;
}
}
.skuMiddle {
float: left;
width: 38px;
height: 22px;
}
.skuRight {
float: right;
width: 24px;
height: 22px;
border-left: 1px solid #ececec;
.addIcon {
width: 10px;
height: 10px;
display: block;
}
}
}
.detailed {
display: flex;
justify-content: space-between;
}
.AngleIcon {
width: 6px;
height: 10px;
display: block;
margin-left: 8px;
margin-top: 2px;
}
.hour {
flex: 1;
display: flex;
flex-flow: column;
position: relative;
.headline {
font-size: 14px;
font-weight: 600;
color: #333333;
line-height: 20px;
margin-bottom: 4px;
}
.period {
height: 17px;
font-size: 12px;
font-weight: 400;
color: #666666;
line-height: 17px;
}
.money {
position: absolute;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 12px;
font-weight: 400;
color: #666666;
.hourMoney {
font-size: 18px;
color: #333333;
}
}
}
.c_fb9830{
color: #fb9830
}
.m_l_2{
margin-left: 2px;
}
.pa_t_15{
padding: 0 15px 0;
}
.m_t_5{
margin-top: 5px;
}
.m_t_20{
margin-top: 20px;
}
.m_t_13{
margin-top: 13px;
}
.m-r-8{
margin-right: 8px;
}
.p-t-8{
padding-top: 8px
}
.c_ffac4a{
color: #ffac4a;
}
.max_w_240{
max-width: 240px;
}
.agreement_box{
padding-bottom: 5px;
padding-top: 20px;
.chooseIcon{
width: 12px;
height: 12px;
display: block;
margin-right: 5px;
margin-top: -1px;
}
}
.coupon_top{
width: 100%;
padding-top: 20px
}
.c_ff5136{
color: #ff5136
}
.coupons_content{
position: relative;
padding-bottom: 80px;
}
.m_coupon_box{
position: relative;
width: 100%;
.m_coupon_price{
margin-right: 28px;
color: #ff5136
}
.m_coupon_price_b{
position: absolute;
right: 28px;
top: 24px;
color: #ff5136;
}
.m_coupon_free{
position: absolute;
right: 28px;
top: 12px;
color: #ff5136;
}
}
.f-w-i{
font-weight: initial;
}
</style>

View File

@ -0,0 +1,198 @@
<template>
<div class="hoList">
<van-pull-refresh v-model="refreshing" @refresh="onRefresh" loosing-text="释放即可刷新..." loading-text="加载中...">
<van-list v-model="loading" :finished="finished" @load="getList">
<div style="padding-bottom: 110px;background: #ffffff">
<div class="text-center" style="padding: 170px 0" v-if="!emptyData">
<img class="emptyDataIcon" src="https://images.ufutx.com/202106/23/4f155f1df966f264d5b531044ef0b358.png" alt="" />
<div class="color9 font14" style="margin-top: 14px">暂无数据</div>
</div>
<div v-else>
<div class='activ_box' v-for="(item, index) in list" :key="index">
<div class="m_activ_Box f-fdc" @click="goToUrlId(item)">
<div class="f-fs">
<div class='activityPic backCover' v-bind:style="{ backgroundImage: 'url(' + item.cover + ')' }"></div>
<div class="m_lst_ri">
<div class="ellipsis_2 activityTitle font16 bold color3">
{{ item.name }}
</div>
<div class="m_Price f-fbc">
<div class="m_Price_to">
<div class="font12 color9 ellipsis_1" style='width: 160px;'>{{ item.subtitle }}</div>
<div class="font12 color6">{{ item.evaNum }}人已测</div>
</div>
<div class="m_Price_bo f-fcc f-fdc">
<div class="m_PriceBo_dis font11" v-if='item.price != 0'>{{item.price}}</div>
<div class="m_PriceBo_free font12" v-else>免费</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- 我也是有底线的 -
</div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
url: {
type: String,
default: null
},
tabTypet: {
type: String,
default: null
}
},
data() {
return {
list: [],
page: 1,
finished: false,
loading: false,
refreshing: false,
emptyData: true,
noMoreData: false
}
},
watch: {
},
methods: {
getList() {
const vm = this
if (vm.list.length === 0) {
$toastLoading('加载中...')
}
let url = ''
url = `s/h5/ces/testList?page=${vm.page}`
service.post(url).then(data => {
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
vm.loading = false
$toastClear()
}
setTimeout(() => {
vm.page++
$toastClear()
}, 500)
})
.catch(error => {
$toastClear()
console.log(error)
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToUrlId(e) {
this.$router.push({
name: 'evaluateDetails',
params: { id: e.evaluate_id },
query: { evaluate_type: e.type }
})
}
},
activated() {
},
created() {},
mounted() {
}
}
</script>
<style lang="scss" scoped>
.hoList {
height: calc(100vh - 44px) !important;
background: #ffffff;
.activ_box {
margin: 15px 15px 0 15px;
padding: 15px 15px 10px;
background: #ffffff;
box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.08);
border-radius: 8px;
}
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.m_activ_Box {
.m_lst_ri {
flex: 1;
height: auto;
display: flex;
flex-direction: column;
justify-content: space-between;
.activityTitle {
word-break: break-all;
width: 220px;
}
.m_Price {
.m_Price_to {
}
.m_Price_bo {
.m_PriceTo_dis {
color: #C8C8C8;
text-decoration: line-through;
}
.m_PriceBo_dis {
border-radius: 50px;
border: 1px solid #FD936F;
color: #FD6739;
line-height: 12px;
padding: 3px 9px;
}
.m_PriceBo_free{
color: #707FFA;
margin-right: 7px;
}
}
}
}
.activityPic {
background-position: center;
min-width: 80px;
min-height: 80px;
border-radius: 8px;
display: block;
margin-right: 10px;
}
}
.bottomLine {
padding-top: 20px;
padding-bottom: 20px;
}
</style>

View File

@ -0,0 +1,105 @@
<template>
<div class="richTextParsing">
<div v-html="richText" class="rich_text" @click='previewImg($event)'></div>
</div>
</template>
<script>
import { ImagePreview } from 'vant'
export default {
computed: {},
components: {},
props: ['richText'],
data() {
return {
id: ''
}
},
watch: {},
methods: {
previewImg(e) {
if (e.target.nodeName === 'IMG') {
ImagePreview({
images: [e.target.currentSrc],
showIndex: false,
loop: false
})
}
}
},
created() {},
mounted() {
}
}
</script>
<style lang="scss" scoped>
.rich_text {
max-width: 100vw !important;
overflow-x: hidden;
display: flex;
flex-direction: column;
flex-wrap: wrap;
::v-deep img {
max-width: 100% !important;
max-height: 100% !important;
}
::v-deep span {
//max-width: 100% !important;
}
::v-deep .list-paddingleft-2{
padding-left: 25px;
}
::v-deep li::marker {
unicode-bidi: isolate;
font-variant-numeric: tabular-nums;
text-transform: none;
text-indent: 0 !important;
text-align: start !important;
text-align-last: start !important;
}
::v-deep video {
max-width: 100% !important;
}
::v-deep div,
::v-deep article,
::v-deep p{
max-width: 100% !important;
word-wrap: break-word !important;
float: none !important;
position: static !important;
}
::v-deep pre{
white-space: initial!important;
}
::v-deep iframe{
width: 100% !important;
height: 100% !important;
max-width: 100% !important;
}
::v-deep .common_share_title{
padding: initial!important;
}
}
.aboutUs{
padding: 0 15px 15px 15px;
}
</style>
<style>
section {
max-width: 100% !important;
}
</style>
<style lang='scss'>
.rich_text{
::v-deep img {
width: 100%!important;
max-width: 100% !important;
}
}
.van-image-preview{
z-index: 99999999999999!important;
background: rgba(0, 0, 0, 0.9);
}
</style>

View File

@ -0,0 +1,71 @@
<template>
<div class="richTextParsing">
<div v-html="richText" class="rich_text" :class="aboutUs === 'true'? 'aboutUs': ''" @click='previewImg($event)'></div>
</div>
</template>
<script>
import { ImagePreview } from 'vant'
export default {
computed: {},
components: {},
props: ['richText', 'aboutUs'],
data() {
return {
id: ''
}
},
watch: {},
methods: {
previewImg(e) {
if (e.target.nodeName === 'IMG') {
ImagePreview({
images: [e.target.currentSrc],
showIndex: false,
loop: false
})
}
}
},
created() {},
mounted() {
}
}
</script>
<style lang="scss" scoped>
.rich_text {
max-width: 100vw !important;
display: flex;
flex-direction: column;
flex-wrap: wrap;
::v-deep img {
max-width: 100% !important;
max-height: 100% !important;
border-radius: 8px !important;
}
::v-deep video {
max-width: 100% !important;
}
::v-deep div,
::v-deep article,
::v-deep p {
max-width: 100% !important;
word-wrap: break-word !important;
float: none !important;
position: static !important;
}
}
.aboutUs{
padding: 0 15px 15px 15px;
/*margin-bottom: calc(15px + constant(safe-area-inset-bottom));*/
/*margin-bottom: calc(15px + env(safe-area-inset-bottom));*/
}
</style>
<style lang='scss'>
.van-image-preview{
z-index: 99999999999999!important;
background: rgba(0, 0, 0, 0.9);
}
</style>

View File

@ -0,0 +1,254 @@
<template>
<div class="activity">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div style="padding-bottom: 110px">
<div class="text-center" style="padding: 170px 0" v-if="!emptyData">
<img
class="emptyDataIcon"
src="https://image.fulllinkai.com/202108/23/939c529ca16a91e3ee3b22bef2fe92ca.png"
alt=""
/>
<div class="color9 font14" style="margin-top: 14px">{{ $t('Temporarily_no_data') }}</div>
</div>
<div v-else>
<div
class="activityBox f-fdc"
v-for="(item, index) in list"
:key="index"
@click="goToUrlId('activityDetails', item.id)"
>
<div class="f-fs">
<van-image
class="activityPic backCover"
width="142"
height="80"
radius="8"
fit="cover"
:src="item.pic"
/>
<div class="m_lst_ri">
<div class="ellipsis_2 activityTitle font16 bold color3">
<div class="group-icon backCover" v-if="item.is_group"></div>
<div>{{ item.title }}</div>
</div>
<div class="font18 bold" style="color: #FB9830">
<div class="font18" v-if="item.pay_type == 'facetalk'">{{ $t('discuss_personally') }}</div>
<div v-else>
<span v-if="item.price != 0">¥</span
><span class="font18">{{ item.price == 0 ? $t('free') : item.price }}</span>
</div>
</div>
</div>
</div>
<div class="signUpBox f-fbc">
<div class="ellipsis_1 activityIntroduce ellipsis_1 color9 font12">
{{ item.Subtitle }}
</div>
<div class="signUp f-fcc font13 colorff">{{ $t('Apply_here') }}</div>
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
<div style="height: 50px;"></div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
url: {
type: String,
default: null
},
tabTypet: {
type: String,
default: null
},
urlClass: {
type: String,
default: null
}
},
data() {
return {
list: [],
page: 1,
finished: false,
loading: false,
refreshing: false,
emptyData: true,
noMoreData: false
}
},
watch: {},
methods: {
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
const url = `${vm.url}?page=${vm.page}&type=business&class=${vm.urlClass}`
service
.get(url)
.then(data => {
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
$toastClear()
}
vm.page++
vm.loading = false
setTimeout(() => {
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToUrlId(url, id) {
console.log(this.tabTypet)
if (url == 'activityDetails' && this.tabTypet == 'serve') {
url = 'serveDetails'
}
this.$router.push({
name: url,
params: { id: id, tabTypet: this.tabTypet }
})
},
goToUrl(url) {
this.$router.push({
name: url
})
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
}
}
</script>
<style lang="scss" scoped>
.activity {
width: 100vw;
height: calc(100vh - 44px) !important;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.activityBox {
margin: 15px 15px 0 15px;
padding: 15px 15px 10px;
background: #ffffff;
box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.08);
border-radius: 8px;
display: flex;
justify-content: left;
//overflow: hidden;
.m_lst_ri {
flex: 1;
height: auto;
display: flex;
flex-direction: column;
justify-content: space-between;
.group-icon{
float: left;
margin-top: 2px;
margin-right: 4px;
width: 32px;
height: 16px;
background-image: url("https://image.fulllinkai.com/202211/15/631d937276380af19ec646cf7563a64a.png");
}
.activityTitle {
/*display: flex;*/
/*align-items: center;*/
margin-bottom: 5px;
width: 160px;
}
}
.activityPic {
//float: left;
background-position: center;
width: 142px;
height: 80px;
border-radius: 8px;
display: block;
margin-right: 10px;
}
.signUpBox {
padding-top: 5px;
.activityIntroduce {
width: 200px;
}
.signUp {
width: 80px;
height: 28px;
background: linear-gradient(90deg, #8c9bff 0%, #707ffa 100%);
border-radius: 100px;
}
}
}
.bottomLine {
padding-top: 30px;
}
.myBox {
position: relative;
position: fixed;
right: 0;
bottom: 100px;
.myIcon {
width: 80px;
height: 80px;
display: block;
}
.badgeBox {
width: 15px;
height: 15px;
border-radius: 50%;
position: absolute;
background: #fb6d25;
right: 12px;
top: 12px;
}
}
</style>

View File

@ -0,0 +1,250 @@
<template>
<div class="activity">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div style="padding-bottom: 110px">
<div class="text-center" style="padding: 170px 0" v-if="!emptyData">
<img
class="emptyDataIcon"
src="https://image.fulllinkai.com/202108/23/939c529ca16a91e3ee3b22bef2fe92ca.png"
alt=""
/>
<div class="color9 font14" style="margin-top: 14px">{{ $t('Temporarily_no_data') }}</div>
</div>
<div v-else>
<div
class="activityBox f-fdc"
v-for="(item, index) in list"
:key="index"
@click="goToUrlId('activityDetails', item.id)"
>
<van-image class="activityPic backCover" width="100%" height="194" fit="cover" :src="item.pic" />
<div class="m_act_ct">
<div class="m_lst_ri">
<div class=" activityTitle font16 bold color3">
<div class="group-icon backCover" v-if="item.is_group"></div>
<div class="ellipsis_1">{{ item.title }}</div>
</div>
<div class="ellipsis_1 activityIntroduce ellipsis_1 color9 font12">
{{ item.Subtitle }}
</div>
</div>
<div class="signUpBox f-fbc">
<div class="font18 bold" style="color: #FB9830">
<div class="font18" v-if="item.pay_type == 'facetalk'">{{ $t('discuss_personally') }}</div>
<div v-else>
<span v-if="item.price != 0">¥</span
><span class="font18">{{ item.price == 0 ? $t('free') : item.price }}</span>
</div>
</div>
<div class="signUp bold f-fcc font14 colorff">
{{ $t('Apply_here') }}
<van-image
class="sign_icon"
width="6"
height="8"
fit="contain"
src="https://image.fulllinkai.com/202109/13/6c39c0a86db31f1817d59aa569b23e62.png"
/>
</div>
</div>
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
<div style="height: 50px;"></div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
url: {
type: String,
default: null
},
tabTypet: {
type: String,
default: null
},
urlClass: {
type: String,
default: null
}
},
data() {
return {
list: [],
page: 1,
finished: false,
loading: false,
refreshing: false,
emptyData: true,
noMoreData: false
}
},
watch: {},
methods: {
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
const url = `${vm.url}?page=${vm.page}&type=business&class=${vm.urlClass}`
service
.get(url)
.then(data => {
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
$toastClear()
}
vm.page++
vm.loading = false
setTimeout(() => {
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToUrlId(url, id) {
console.log(this.tabTypet)
if (url == 'activityDetails' && this.tabTypet == 'serve') {
url = 'serveDetails'
}
this.$router.push({
name: url,
params: { id: id, tabTypet: this.tabTypet }
})
},
goToUrl(url) {
this.$router.push({
name: url
})
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
}
}
</script>
<style lang="scss" scoped>
.activity {
width: 100vw;
height: calc(100vh - 44px) !important;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.activityBox {
margin: 15px 15px 0 15px;
background: #ffffff;
box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.08);
border-radius: 12px;
overflow: hidden;
.m_act_ct {
padding: 10px 12px 15px;
box-sizing: border-box;
}
.m_lst_ri {
.activityTitle {
width: 100%;
margin-bottom: 5px;
.group-icon{
float: left;
margin-top: 2px;
margin-right: 4px;
width: 32px;
height: 16px;
background-image: url("https://image.fulllinkai.com/202211/15/631d937276380af19ec646cf7563a64a.png");
}
}
.activityIntroduce {
width: 100%;
}
}
.activityPic {
//float: left;
background-position: center;
width: 142px;
height: 80px;
border-radius: 8px;
display: block;
margin-right: 10px;
}
.signUpBox {
padding-top: 5px;
.signUp {
color: #707ffa;
.sign_icon {
margin-left: 10px;
}
}
}
}
.bottomLine {
padding-top: 30px;
}
.myBox {
position: relative;
position: fixed;
right: 0;
bottom: 100px;
.myIcon {
width: 80px;
height: 80px;
display: block;
}
.badgeBox {
width: 15px;
height: 15px;
border-radius: 50%;
position: absolute;
background: #fb6d25;
right: 12px;
top: 12px;
}
}
</style>

View File

@ -0,0 +1,244 @@
<template>
<div class="activity">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div style="padding-bottom: 110px">
<div class="text-center" style="padding: 170px 0" v-if="!emptyData">
<img
class="emptyDataIcon"
src="https://image.fulllinkai.com/202108/23/939c529ca16a91e3ee3b22bef2fe92ca.png"
alt=""
/>
<div class="color9 font14" style="margin-top: 14px">{{ $t('Temporarily_no_data') }}</div>
</div>
<div v-else>
<div
class="activityBox f-fdc"
v-for="(item, index) in list"
:key="index"
@click="goToUrlId('activityDetails', item.id)"
>
<van-image class="activityPic backCover" width="100%" height="194" fit="cover" :src="item.pic" />
<div class="m_act_ct">
<div class="m_lst_ri">
<div class=" activityTitle font16 bold color3">
<div class="group-icon backCover" v-if="item.is_group"></div>
<div class="ellipsis_1">{{ item.title }}</div>
</div>
<div class="ellipsis_1 activityIntroduce ellipsis_1 color9 font12">
{{ item.Subtitle }}
</div>
</div>
<div class="signUpBox f-fbc">
<div class="font18 bold" style="color: #FB9830">
<div class="font18" v-if="item.pay_type == 'facetalk'">{{ $t('discuss_personally') }}</div>
<div v-else>
<span v-if="item.price != 0">¥</span
><span class="font18">{{ item.price == 0 ? $t('free') : item.price }}</span>
</div>
</div>
<div class="signUp f-fcc font14 colorff">{{ $t('Apply_here') }}</div>
</div>
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
<div style="height: 50px;"></div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
url: {
type: String,
default: null
},
tabTypet: {
type: String,
default: null
},
urlClass: {
type: String,
default: null
}
},
data() {
return {
list: [],
page: 1,
finished: false,
loading: false,
refreshing: false,
emptyData: true,
noMoreData: false
}
},
watch: {},
methods: {
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
const url = `${vm.url}?page=${vm.page}&type=business&class=${vm.urlClass}`
service
.get(url)
.then(data => {
console.log('111111111')
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
$toastClear()
}
vm.page++
vm.loading = false
setTimeout(() => {
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToUrlId(url, id) {
console.log(this.tabTypet)
if (url == 'activityDetails' && this.tabTypet == 'serve') {
url = 'serveDetails'
}
this.$router.push({
name: url,
params: { id: id, tabTypet: this.tabTypet }
})
},
goToUrl(url) {
this.$router.push({
name: url
})
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
}
}
</script>
<style lang="scss" scoped>
.activity {
width: 100vw;
height: calc(100vh - 44px) !important;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.activityBox {
margin: 15px 15px 0 15px;
background: #ffffff;
box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.08);
border-radius: 12px;
overflow: hidden;
.m_act_ct {
padding: 10px 12px 15px;
box-sizing: border-box;
}
.m_lst_ri {
.activityTitle {
/*display: flex;*/
/*align-items: center;*/
width: 100%;
margin-bottom: 5px;
.group-icon{
float: left;
margin-top: 2px;
margin-right: 4px;
width: 32px;
height: 16px;
background-image: url("https://image.fulllinkai.com/202211/15/631d937276380af19ec646cf7563a64a.png");
}
}
.activityIntroduce {
width: 100%;
}
}
.activityPic {
//float: left;
background-position: center;
width: 142px;
height: 80px;
border-radius: 8px;
display: block;
margin-right: 10px;
}
.signUpBox {
padding-top: 5px;
.signUp {
padding: 8px 25px;
line-height: 20px;
background: linear-gradient(90deg, #97a4fe 0%, #707ffa 100%);
border-radius: 100px;
}
}
}
.bottomLine {
padding-top: 30px;
}
.myBox {
position: relative;
position: fixed;
right: 0;
bottom: 100px;
.myIcon {
width: 80px;
height: 80px;
display: block;
}
.badgeBox {
width: 15px;
height: 15px;
border-radius: 50%;
position: absolute;
background: #fb6d25;
right: 12px;
top: 12px;
}
}
</style>

View File

@ -0,0 +1,178 @@
<template>
<div class="sharePosters" v-if="show">
<div class="canvasArea">
<vue-canvas-poster :widthPixels="1000" :painting="envelope" @success="success" @fail="fail"></vue-canvas-poster>
<img class="canvasImg" :class="screenShow ? 'sel' : ''" :src="posterImg" alt="" v-if="posterImg" />
<div class="font15 colorff bold text-center" style="margin-top: 15px">长按保存图片分享给好友或朋友圈</div>
<img class="cancelIcon_show" :class="screenShow ? 'sel' : ''" v-if="iconShow" @click.stop="clickShare" src="https://image.fulllinkai.com/202110/23/78698e898cd570e5e7751c323e4a5cb7.png" alt="" />
<img class="cancelIcon" :class="screenShow ? 'sel' : ''" v-else @click.stop="clickShare" src="https://image.fulllinkai.com/202108/27/78698e898cd570e5e7751c323e4a5cb7.png" alt="" />
</div>
</div>
</template>
<script>
import { $toastClear } from '@/config/toast'
export default {
computed: {},
components: {},
props: {
show: {
type: Boolean,
default: false
},
iconShow: {
type: Boolean,
default: false
},
qrcode: {
type: String,
default: ''
},
envelope: {
type: Object,
default: () => {
return {}
}
}
},
data() {
return {
newQrcode: '',
posterImg: '',
painting: {},
screenWidth: 0,
screenHeight: 0,
screenShow: false
}
},
methods: {
clickShare() {
this.$emit('update:show', !this.show)
},
getBase64Image(img) {
var canvas = document.createElement('canvas')
canvas.width = img.width
canvas.height = img.height
console.log(img.width, 'qrcodeImage--------------------------')
var ctx = canvas.getContext('2d')
ctx.drawImage(img, 0, 0, img.width, img.height)
var dataURL = canvas.toDataURL('image/jpeg') // image/jpeg
return dataURL
},
getNewQrcode() {
const vm = this
if (vm.envelope.views && vm.envelope.views.length > 0) {
vm.envelope.views.forEach(item => {
if (item.url && item.url.indexOf('?') != -1) {
var urlArr = item.url.split('?')
if (urlArr.length > 0) {
console.log(item.url)
item.url = urlArr[0]
}
}
if (item.url && !item.localShow) {
var qrcodeImage = new Image()
qrcodeImage.setAttribute('crossOrigin', 'anonymous') // iOS securityError...insource
qrcodeImage.src = item.url + '?v=' + Math.random() //
qrcodeImage.crossOrigin = 'Anonymous'
qrcodeImage.onload = () => {
// onloadundefind
var base64 = vm.getBase64Image(qrcodeImage)
vm.newQrcode = base64 //
item.url = base64 //
}
}
})
}
},
success(src) {
this.posterImg = src
$toastClear()
},
fail(err) {
$toastClear()
alert(err)
},
childMethod() {
this.getNewQrcode()
}
},
watch: {
newQrcode() {
if (this.newQrcode) {
setTimeout(() => {
this.painting = this.envelope
}, 200)
}
},
envelope() {
this.getNewQrcode()
}
},
created() {},
mounted() {
var that = this
that.screenWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth //
that.screenHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight //
if (that.screenHeight < 670) {
that.screenShow = true
}
}
}
</script>
<style lang="scss" scoped>
.sharePosters {
width: 100vw;
height: 100vh;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.6);
position: fixed;
z-index: 9999999999999;
}
.canvasArea {
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 90%;
z-index: 99999999999;
.canvasImg {
// width: 300px;
// height: 534px;
width: 90%;
// height: 90%;
display: block;
margin: 0 auto;
}
.canvasImg.sel {
width: 80%;
}
.cancelIcon {
width: 30px;
height: 30px;
position: absolute;
z-index: 222;
top: 5px;
right: 20px;
}
.cancelIcon.sel {
width: 24px;
height: 24px;
right: 38px;
}
.cancelIcon_show {
width: 15px;
height: 15px;
position: absolute;
z-index: 222;
top: 10px;
right: 28px;
}
.cancelIcon_show.sel {
width: 12px;
height: 12px;
right: 38px;
}
}
</style>

View File

@ -0,0 +1,244 @@
<template>
<div class="courseList">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div style="padding-bottom: 110px">
<div class="text-center" style="padding: 170px 0" v-if="!emptyData">
<img
class="emptyDataIcon"
src="https://image.fulllinkai.com/202108/23/939c529ca16a91e3ee3b22bef2fe92ca.png"
alt=""
/>
<div class="color9 font14" style="margin-top: 14px">{{ $t('Temporarily_no_data') }}</div>
</div>
<div v-else>
<div class="moreCourseBox">
<div
class="courseBox"
v-for="(item, index) in list"
:key="index"
@click="goToUrlId(`courseDetail`, item.id)"
>
<div class="f-fs">
<div class="coursePic backCover">
<van-image class="" width="100%" height="100%" radius="8" fit="cover" :src="item.thumb" />
<div v-if="item.discount_status == 1" class="preferential colorff font10">
{{ $t('preferential') }}
</div>
</div>
<div class="m_lst_ri">
<div class="font14 color3 bold ellipsis_2" style="max-width: 160px">{{ item.title }}</div>
<div class="coursePrice bold font18">
<span style="margin-left: -2px">{{ item.charge || 0 }}</span
><span class="color9 font12 originalPrice" v-if="item.discount_status == 1">{{
item.price
}}</span>
</div>
</div>
</div>
<div class="signUpBox f-fbc" style="margin-top: 5px">
<div class="font12 color9 ellipsis_1" style="width: 200px;">
{{ item.short_description || '' }}
</div>
<div class="signUp f-fcc font13 colorff">{{ $t('Apply_here') }}</div>
</div>
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
<div style="height: 50px;"></div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
url: {
type: String,
default: null
}
},
data() {
return {
list: [],
page: 1,
finished: false,
loading: false,
refreshing: false,
emptyData: true,
noMoreData: false
}
},
watch: {},
methods: {
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
service
.get(`${vm.url}?page=${vm.page}`)
.then(data => {
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
vm.$nextTick(() => {
vm.loading = false
vm.page++
})
$toastClear()
}
// vm.page++
setTimeout(() => {
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToUrlId(url, id) {
this.$router.push({
name: url,
params: { id: id }
})
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
}
}
</script>
<style lang="scss" scoped>
.courseList {
height: calc(100vh - 44px) !important;
}
.van-tab__pane {
width: 100vw;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.moreCourseBox {
margin: 0 15px;
.courseBox {
padding: 15px 15px 10px;
margin: 15px 0;
background: #ffffff;
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.1);
border-radius: 8px;
overflow: hidden;
.m_lst_ri {
flex: 1;
height: auto;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.coursePic {
flex: none;
width: 142px;
height: 80px;
margin-right: 10px;
border-radius: 8px;
position: relative;
.preferential {
position: absolute;
top: 0;
left: 0;
background: #ff4a4c;
display: flex;
justify-content: center;
align-items: center;
padding: 0 5px;
height: 17px;
border-radius: 8px 0;
}
}
.coursePrice {
color: #fb9830;
max-width: 80px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.originalPrice {
text-decoration: line-through;
margin-left: 5px;
position: relative;
top: -1px;
}
}
.joinButton,
.joinCourseV2 {
position: absolute;
right: 15px;
bottom: 20px;
width: 78px;
height: 28px;
border-radius: 15px;
border: 1px solid #ffc67d;
}
.joinCourseV2 {
border: 1px solid #c2c2c2;
}
.signUpBox {
.signUp {
width: 80px;
height: 28px;
background: linear-gradient(90deg, #8c9bff 0%, #707ffa 100%);
border-radius: 100px;
}
}
}
}
.bottomLine {
padding-top: 20px;
}
</style>
<style lang="scss">
.van-tab__pane {
width: 100%;
min-height: 100%;
background: #ffffff;
}
</style>

View File

@ -0,0 +1,302 @@
<template>
<div class="courseList">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div :style="mySignUp ? '' : 'padding-bottom: 110px'">
<div class="text-center" style="padding: 170px 0" v-if="!emptyData">
<img
class="emptyDataIcon"
src="https://image.fulllinkai.com/202108/23/939c529ca16a91e3ee3b22bef2fe92ca.png"
alt=""
/>
<div class="color9 font14" style="margin-top: 14px">{{ $t('Temporarily_no_data') }}</div>
</div>
<div v-else>
<div class="moreCourseBox">
<div
class="courseBox"
v-for="(item, index) in list"
:key="index"
@click="
goToUrlId(
`questionnaire`,
mySignUp ? item.q_a_test_id : item.id,
item.status,
mySignUp ? item.id : ''
)
"
>
<div class="coursePic backCover">
<van-image class="" width="100%" height="100%" radius="8" fit="cover" :src="item.pic" />
<div v-if="item.discount_status == 1" class="preferential colorff font10">
{{ $t('preferential') }}
</div>
</div>
<div class="m_cou_ct">
<div class="m_lst_ri">
<div class="font16 color3 bold ellipsis_1">{{ item.title }}</div>
<div class="font12 color9 ellipsis_1"></div>
</div>
<div class="signUpBox f-fbc" v-if="mySignUp">
<div class="coursePrice color9 font12 f-fcc">{{ item.question_num }}</div>
<div class="signUp f-fcc font13">
<div class="u_bu color6 font13 f-fcc">重新测试</div>
<div class="u_bu blue font13 f-fcc">查看结果</div>
</div>
</div>
<div class="signUpBox f-fbc" v-else>
<div class="coursePrice color9 font12 f-fcc">
<van-image
class="sign_icon_re"
width="14"
height="14"
fit="contain"
show-loading="false"
src="https://local-pictures.oss-cn-shenzhen.aliyuncs.com/202109/29/08ee5b9a3e528787ecae44ebdfe2c374.png"
/>{{ item.user_num }}
</div>
<div class="signUp f-fcc font14 colorff">
进入测试
<van-image
class="sign_icon"
width="6"
height="8"
fit="contain"
src="https://image.fulllinkai.com/202109/13/6c39c0a86db31f1817d59aa569b23e62.png"
/>
</div>
</div>
</div>
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
<div style="height: 50px;"></div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
url: {
type: String,
default: null
},
mySignUp: {
type: Boolean,
default: false
}
},
data() {
return {
list: [],
page: 1,
finished: false,
loading: false,
refreshing: false,
emptyData: true,
noMoreData: false
}
},
watch: {},
methods: {
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
service
.get(`${vm.url}?page=${vm.page}`)
.then(data => {
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
vm.$nextTick(() => {
vm.loading = false
vm.page++
})
// vm.loading = false
$toastClear()
}
// vm.page++
setTimeout(() => {
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToUrlId(url, id, status, q_a_test_id) {
var type = ''
if (this.mySignUp) {
status = 1
type = 'user'
}
this.$router.push({
name: url,
params: { id: id },
query: {
status,
q_a_test_id,
type
}
})
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
}
}
</script>
<style lang="scss" scoped>
.courseList {
height: 100vh !important;
background: #ffffff;
}
.van-tab__pane {
width: 100vw;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.moreCourseBox {
margin: 0 15px;
.courseBox {
margin: 15px 0;
padding: 15px;
background: #ffffff;
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.1);
border-radius: 12px;
overflow: hidden;
.coursePic {
width: 100%;
height: 105px;
position: relative;
.preferential {
position: absolute;
top: 0;
left: 0;
background: #ff4a4c;
display: flex;
justify-content: center;
align-items: center;
padding: 0 5px;
height: 17px;
border-radius: 8px 0;
}
}
.m_cou_ct {
padding-top: 10px;
box-sizing: border-box;
.m_lst_ri {
width: 100%;
padding-bottom: 5px;
div {
width: 100%;
margin-bottom: 5px;
}
}
.signUpBox {
width: 100%;
.coursePrice {
max-width: 80px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.originalPrice {
text-decoration: line-through;
margin-left: 5px;
position: relative;
top: -1px;
}
.sign_icon_re {
margin-right: 2px;
}
}
.signUp {
color: #707ffa;
.sign_icon {
margin-left: 10px;
margin-top: 1px;
}
}
}
}
.joinButton,
.joinCourseV2 {
position: absolute;
right: 15px;
bottom: 20px;
width: 78px;
height: 28px;
border-radius: 15px;
border: 1px solid #ffc67d;
}
.joinCourseV2 {
border: 1px solid #c2c2c2;
}
}
}
.bottomLine {
padding-top: 20px;
}
.u_bu {
width: 80px;
height: 28px;
border: 1px solid #c2c2c2;
border-radius: 100px;
margin-left: 10px;
}
.u_bu.blue {
color: #707ffa;
border: 1px solid #96a2ff;
}
</style>
<style lang="scss">
.van-tab__pane {
width: 100%;
min-height: 100%;
background: #ffffff;
}
</style>

View File

@ -0,0 +1,243 @@
<template>
<div class="courseList">
<van-pull-refresh
v-model="refreshing"
@refresh="onRefresh"
:loosing-text="$t('loosing_text')"
:loading-text="$t('loading_text')"
>
<van-list v-model="loading" :finished="finished" @load="getList">
<div style="padding-bottom: 110px">
<div class="text-center" style="padding: 170px 0" v-if="!emptyData">
<img
class="emptyDataIcon"
src="https://image.fulllinkai.com/202108/23/939c529ca16a91e3ee3b22bef2fe92ca.png"
alt=""
/>
<div class="color9 font14" style="margin-top: 14px">{{ $t('Temporarily_no_data') }}</div>
</div>
<div v-else>
<div class="moreCourseBox">
<div
class="courseBox"
v-for="(item, index) in list"
:key="index"
@click="goToUrlId(`courseDetail`, item.id)"
>
<div class="coursePic backCover">
<van-image class="" width="100%" height="100%" fit="cover" :src="item.thumb" />
<div v-if="item.discount_status == 1" class="preferential colorff font10">
{{ $t('preferential') }}
</div>
</div>
<div class="m_cou_ct">
<div class="m_lst_ri">
<div class="font16 color3 bold ellipsis_1">{{ item.title }}</div>
<div class="font12 color9 ellipsis_1">{{ item.videos_count || 0 }}{{ $t('Class_time') }}</div>
</div>
<div class="signUpBox f-fbc">
<div class="coursePrice bold font18">
<span style="margin-left: -2px">{{ item.charge || 0 }}</span
><span class="color9 font12 originalPrice" v-if="item.discount_status == 1">{{
item.price
}}</span>
</div>
<div class="signUp font14 colorff">{{ $t('join_learning') }}</div>
</div>
</div>
</div>
</div>
<div class="bottomLine font12 color6 text-center" v-if="noMoreData">
- {{ $t('I_have_a_line_in_the_sand') }} -
</div>
<div style="height: 50px;"></div>
</div>
</div>
</van-list>
</van-pull-refresh>
</div>
</template>
<script>
import { $toastClear, $toastLoading } from '@/config/toast'
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
url: {
type: String,
default: null
}
},
data() {
return {
list: [],
page: 1,
finished: false,
loading: false,
refreshing: false,
emptyData: true,
noMoreData: false
}
},
watch: {},
methods: {
getList() {
const vm = this
$toastLoading(vm.$i18n.t('loading_text'))
service
.get(`${vm.url}?page=${vm.page}`)
.then(data => {
const dataV = vm.page === 1 ? [] : vm.list
dataV.push(...data.data)
vm.list = dataV
vm.refreshing = false
if (vm.list.length !== 0) {
vm.emptyData = true
} else {
vm.emptyData = false
}
if (vm.list.length < 15 || data.data.length < 15) {
vm.finished = true
vm.noMoreData = true
if (vm.list.length === 0) {
vm.noMoreData = false
}
$toastClear()
return
} else {
vm.$nextTick(() => {
vm.loading = false
vm.page++
})
$toastClear()
}
// vm.page++
// vm.loading = false
setTimeout(() => {
$toastClear()
}, 500)
})
.catch(error => {
console.log(error)
})
},
onRefresh() {
this.page = 1
this.finished = false
this.loading = true
this.getList()
},
goToUrlId(url, id) {
this.$router.push({
name: url,
params: { id: id }
})
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
}
}
</script>
<style lang="scss" scoped>
.courseList {
height: calc(100vh - 44px) !important;
}
.van-tab__pane {
width: 100vw;
background: #ffffff;
}
.emptyDataIcon {
width: 135px;
height: 100px;
display: block;
margin: 0 auto;
}
.moreCourseBox {
margin: 0 15px;
.courseBox {
margin: 15px 0;
background: #ffffff;
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.1);
border-radius: 12px;
overflow: hidden;
.coursePic {
width: 100%;
height: 194px;
position: relative;
.preferential {
position: absolute;
top: 0;
left: 0;
background: #ff4a4c;
display: flex;
justify-content: center;
align-items: center;
padding: 0 5px;
height: 17px;
border-radius: 8px 0;
}
}
.m_cou_ct {
padding: 10px 12px 15px;
box-sizing: border-box;
.m_lst_ri {
width: 100%;
div {
width: 100%;
margin-bottom: 5px;
}
}
.signUpBox {
width: 100%;
.coursePrice {
color: #fb9830;
max-width: 80px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.originalPrice {
text-decoration: line-through;
margin-left: 5px;
position: relative;
top: -1px;
}
}
.signUp {
padding: 8px 25px;
background: linear-gradient(90deg, #8c9bff 0%, #707ffa 100%);
border-radius: 100px;
}
}
}
.joinButton,
.joinCourseV2 {
position: absolute;
right: 15px;
bottom: 20px;
width: 78px;
height: 28px;
border-radius: 15px;
border: 1px solid #ffc67d;
}
.joinCourseV2 {
border: 1px solid #c2c2c2;
}
}
}
.bottomLine {
padding-top: 20px;
}
</style>
<style lang="scss">
.van-tab__pane {
width: 100%;
min-height: 100%;
background: #ffffff;
}
</style>

View File

@ -0,0 +1,287 @@
<template>
<div class="uploaderCut">
<van-uploader :after-read="afterRead" :multiple='true' :max-count="3" :max-size="10200 * 1024" @oversize="onOversize">
<slot name="upload"></slot>
</van-uploader>
<div class="container" v-show='cropperState'>
<div class="img-container">
<img :src="pic" :id='cutId' ref="image" alt="">
</div>
</div>
<div class='cut_operation font16' v-show='cropperState'>
<div class='alignment operation_box'>
<div class='color9 clearBto alignment_center' @click='clearCut'>取消</div>
<div class='colorff determineBto alignment_center bcTheme' @click='sureSava'>确定</div>
</div>
</div>
</div>
</template>
<script>
import { $toastClear, $toastLoading, $toastText } from '@/config/toast'
import service from '@/utils/request'
import { imgCompress } from '@/plugins/timeTransition'
// import $ from 'jquery'
export default {
props: ['tailoringData', 'cutId'],
data() {
return {
id: '',
pic: '',
cropperState: false,
file: null,
myCropper: null
}
},
watch: {},
methods: {
//
onOversize(file) {
$toastText('图片大小不能超过 10M')
},
//
afterRead(event) {
console.log(event, '79879')
const vm = this
if (event.length > 1) {
return $toastText('请勿上传多张照片')
}
const imgType = event.file.type === 'image/jpeg' || event.file.type === 'image/png' || event.file.type === 'image/jpg'
if (!imgType) {
$toastText('上传图片只能是 jpg、png、jpeg 格式!')
return false
}
if (event.status === 'failed') {
$toastText('上传失败,请重新上传')
return
}
console.log(event, '123******')
vm.pic = event.content
let bs64data
// BASE64
const reader = new FileReader()
// 2 base64
reader.readAsDataURL(event.file)
//
reader.onloadend = function() {
const result = this.result
const img = new Image()
img.src = result
img.onload = function() {
bs64data = imgCompress(img)
// BASE64
var arr = bs64data.split(','); var mime = arr[0].match(/:(.*?);/)[1]; var
bstr = atob(arr[1]); var n = bstr.length; var u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
const newfile = new File([u8arr], event.file.name, { type: mime })
vm.file = newfile
console.log(vm.file, 'file---')
}
}
setTimeout(() => {
if (vm.pic) {
vm.cropperState = true
} else {
vm.cropperState = false
}
vm.init()
}, 800)
},
//
init() {
const vm = this
console.log(vm.$refs.image, 'vm.$refs.image--------')
vm.myCropper = new Cropper(vm.$refs.image, {
viewMode: 1,
dragMode: 'move',
initialAspectRatio: 1,
aspectRatio: vm.tailoringData.widthProportion / vm.tailoringData.heightProportion,
background: false,
scalable: false,
outputType: 'png',
minCropBoxWidth: vm.tailoringData.width,
minCropBoxHeight: vm.tailoringData.height,
autoCropArea: 0.8,
zoomOnWheel: false,
crop: function(e) {
vm.tailoringWidth = Math.floor(e.detail.width) + 'px'
vm.tailoringHeight = Math.floor(e.detail.height) + 'px'
},
destroy: function() {}
})
},
//
clearCut() {
this.file = ''
this.pic = ''
this.cropperState = false
this.myCropper.destroy()
this.myCropper = null
},
//
sureSava() {
const vm = this
$toastLoading('图片截取中...')
vm.afterImg = this.myCropper.getCroppedCanvas({
imageSmoothingQuality: 'high'
}).toDataURL('image/png')
const blob = this.dataURLtoBlob(this.afterImg, new Date().getTime())
this.file = blob
console.log(this.file, 'file--****')
let bs64data
// BASE64
const reader = new FileReader()
reader.readAsDataURL(this.file)
//
reader.onloadend = function() {
const result = this.result
const img = new Image()
img.src = result
img.onload = function() {
bs64data = imgCompress(img)
// BASE64
var arr = bs64data.split(','); var mime = arr[0].match(/:(.*?);/)[1]; var
bstr = atob(arr[1]); var n = bstr.length; var u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
console.log(vm.file, 'file---***111')
const newfile = new File([u8arr], vm.file.name, { type: mime })
vm.file = newfile
console.log(vm.file, 'file---')
vm.submit(vm.file)
}
}
// setTimeout(() => {
// this.submit(this.file)
// })
},
//
dataURLtoBlob(dataurl, filename) {
var arr = dataurl.split(',')
var mime = arr[0].match(/:(.*?);/)[1]
var suffix = mime.split('/')[1]
var bstr = atob(arr[1])
var n = bstr.length
var u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], `${filename}.${suffix}`, { type: mime })
},
submit(file) {
var vm = this
var formData = new FormData()
var fileName = vm.$md5(file.name) + Math.random() + '.' + file.type.split('/').pop().toLowerCase()
var filePath = vm.host + '/' + vm.ossConfig.dir + fileName
formData.append('name', vm.ossConfig.dir + fileName)
formData.append('key', vm.ossConfig.dir + fileName)
formData.append('policy', vm.ossConfig.policy)
formData.append('OSSAccessKeyId', vm.ossConfig.accessid)
formData.append('success_action_status', '200')
formData.append('signature', vm.ossConfig.signature)
formData.append('file', file)
formData.append('filename', file.name)
service.post(vm.host, formData, { headers: { 'Content-Type': 'multipart/form-data' }}).then(data => {
if (filePath.includes('html')) {
vm.clearCut()
$toastText('上传文件不符合要求,请重新上传')
return
}
$toastText('截取成功')
vm.$emit('onSuccess', filePath)
vm.clearCut()
setTimeout(() => {
$toastClear()
}, 1200)
}).catch(error => {
vm.clearCut()
$toastText('网络延时,请重新上传')
setTimeout(() => {
$toastClear()
}, 1200)
console.log(error)
})
},
//
getSignature() {
const vm = this
service.get('/upload/signature').then(data => {
vm.ossConfig = data
vm.host = data.host
console.log('12312312---')
vm.$store.commit('changeUploadConfig', data)
console.log('12312312--1231232-')
}).catch(error => {
console.log(error)
})
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
this.getSignature()
}
}
</script>
<style lang="scss" scoped>
.uploaderCut{
width: 100%;
height: 100%;
}
::v-deep .van-uploader, ::v-deep.van-uploader__wrapper,::v-deep .van-uploader__input-wrapper{
width: 100%;
height: 100%;
}
.van-uploader__input{
width: 100%;
height: 100%;
position: absolute;
opacity: 0;
}
.container{
width: 100%;
max-width: 100%!important;
height: 100%;
background: #000000;
position: fixed;
top: 0;
left: 0;
z-index: 88888;
}
.img-container{
width: 100%!important;
max-width: 100%!important;
height: 85vh!important;
overflow: hidden;
}
.cut_operation{
position: fixed;
height: 15vh;
width: 100%;
background: #000000;
bottom: 0;
left: 0;
z-index: 99999;
.operation_box{
padding: 0 60px;
height: 15vh;
.clearBto{
border-radius: 20px;
width: 98px;
height: 32px;
border: 1px solid #999999;
}
.determineBto{
border-radius: 20px;
width: 100px;
height: 34px;
/*background: var(--bcTheme);*/
}
}
}
</style>

View File

@ -0,0 +1,121 @@
<template>
<div class="accountMGT">
<!--<div class="m_tt font14 color9" style="margin-bottom: 10px">{{ tailoringData.title || '上传封面' }}</div>-->
<div class="contact_box" v-if='equipmentType' @click='passAppData()'>
<div class="add_box f-fcc f-fdc" v-if="!detail.pic">
<van-image fit="contain" :width="addStyle?addStyle.width: 20" :height="addStyle?addStyle.width: 20" class="u_tipsIcon" src="https://image.fulllinkai.com/202110/29/c8524b7eb04ac3d525a37aabe283d2eb.png" alt="" />
<div class="text-center font12" style="color: #c8c8c8">
上传封面
</div>
</div>
<div class="contact backCover" v-bind:style="{backgroundImage: 'url(' + detail.pic + ')'}">
<van-image fit="contain" class="u_el_cion" :width="addStyle?addStyle.width: 20" :height="addStyle?addStyle.width: 20" v-if="detail.pic" @click.stop="clickDelete()" src="https://image.fulllinkai.com/202110/29/5be31302bc2ab0c71d7d95a08b810317.png" alt="" />
</div>
</div>
<div class="contact_box" v-else>
<div class="add_box f-fcc f-fdc" v-if="!detail.pic">
<van-image fit="contain" width="20" height="20" class="u_tipsIcon" src="https://image.fulllinkai.com/202110/29/c8524b7eb04ac3d525a37aabe283d2eb.png" alt="" />
<div class="text-center font12" :style="{marginTop: addStyle?addStyle.top: '',fontSize: addStyle?addStyle.fontSize: ''}" style="color: #c8c8c8">
上传图片
</div>
</div>
<div class="contact backCover" v-bind:style="{backgroundImage: 'url(' + detail.pic + ')'}">
<uploaderCut @onSuccess="onSuccess" :cutId="'imageCut'" :tailoringData="tailoringData">
<div slot="upload" class="upload_contact font14" v-bind:style="{ width: '100%', height: '100%' }"></div>
</uploaderCut>
<van-image fit="contain" class="u_el_cion" width="20" height="20" v-if="detail.pic" @click.stop="clickDelete()" src="https://image.fulllinkai.com/202110/29/5be31302bc2ab0c71d7d95a08b810317.png" alt="" />
</div>
</div>
</div>
</template>
<script>
import uploaderCut from '@/components/uploaderCut'
import { $toastText } from '@/config/toast'
export default {
computed: {},
components: { uploaderCut },
props: ['tailoringData', 'detail', 'addStyle', 'appTailoringData'],
data() {
return {
equipmentType: ''
}
},
watch: {},
methods: {
// app
passAppData() {
if (localStorage.getItem('equipmentType')) {
window.android.selectFile(JSON.stringify(this.appTailoringData))
}
},
// apptype
acceptUrl(type, url) {
this.detail.pic = url
},
onSuccess(val) {
this.detail.pic = val
},
clickDelete(index) {
this.detail.pic = ''
}
},
created() {
// appvue
window.acceptUrl = this.acceptUrl
},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
this.equipmentType = localStorage.getItem('equipmentType')
}
}
</script>
<style lang="scss" scoped>
.accountMGT {
position: relative;
width: 100%;
height: 100%;
}
.contact_box {
width: 100%;
height: 100%;
/*width: 174px;*/
/*height: 130px;*/
/*background: #f8f8f8;*/
border-radius: 8px;
/*position: relative;*/
.add_box {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
color: #c8c8c8;
.add_icon {
width: 20px;
height: 20px;
display: block;
margin: 0 auto 13px auto;
}
}
.contact {
border-radius: 8px;
position: relative;
height: 100%;
width: 100%;
.u_el_cion {
position: absolute;
top: 6px;
right: 4px;
}
.upload_contact {
border-radius: 8px;
}
}
}
.u_tipsIcon {
margin-bottom: 5px;
}
</style>

View File

@ -0,0 +1,93 @@
<template>
<div>
<van-uploader :after-read="afterRead" :multiple='true' :max-count="3" :max-size="5200 * 1024" @oversize="onOversize">
<slot name="upload"></slot>
</van-uploader>
</div>
</template>
<script>
import service from '@/utils/request'
import { $toastLoading, $toastClear, $toastText } from '@/config/toast'
export default {
computed: {},
components: {},
data() {
return {
ossConfig: {},
file: '',
host: ''
}
},
watch: {},
methods: {
onOversize(file) {
$toastText(this.$i18n.t('No_more_than'))
},
afterRead(event) {
const vm = this
const imgType = event.file.type === 'image/jpeg' || event.file.type === 'image/png' || event.file.type === 'image/jpg'
if (!imgType) {
$toastText(vm.$i18n.t('limit_upload'))
return false
}
$toastLoading(vm.$i18n.t('in_upload'))
if (event.status === 'failed') {
$toastText(vm.$i18n.t('Network_anomalies'))
}
if (event.length > 1) {
event.forEach((item) => {
vm.submit(item.file)
})
} else {
vm.submit(event.file)
}
},
submit(file) {
var self = this
var formData = new FormData()
var fileName = self.$md5(file.name) + Math.random() + '.' + file.type.split('/').pop().toLowerCase()
var filePath = self.host + '/' + self.ossConfig.dir + fileName
formData.append('name', self.ossConfig.dir + fileName)
formData.append('key', self.ossConfig.dir + fileName)
formData.append('policy', self.ossConfig.policy)
formData.append('OSSAccessKeyId', self.ossConfig.accessid)
formData.append('success_action_status', '200')
formData.append('signature', self.ossConfig.signature)
formData.append('file', file)
formData.append('filename', file.name)
service.post(self.host, formData, { headers: { 'Content-Type': 'multipart/form-data' }}).then(data => {
$toastClear()
self.$emit('onSuccess', filePath)
}).catch(error => {
$toastText(self.$i18n.t('Network_anomalies'))
console.log(error)
})
},
//
getSignature() {
const vm = this
service.get('/upload/signature').then(data => {
vm.ossConfig = data
vm.host = data.host
}).catch(error => {
console.log(error)
})
}
},
created() {
},
mounted() {
this.getSignature()
}
}
</script>
<style lang="scss" scoped>
.van-uploader__input{
width: 100%;
height: 100%;
position: absolute;
opacity: 0;
}
</style>

View File

@ -0,0 +1,159 @@
<template>
<div>
<!-- :max-size="5200 * 1024" -->
<van-uploader :after-read="afterRead" multiple :max-count="9" @oversize="onOversize">
<slot name="uploads"></slot>
</van-uploader>
</div>
</template>
<script>
import service from '@/utils/request'
import { $toastLoading, $toastClear, $toastText } from '@/config/toast'
import { imgCompress } from '@/plugins/timeTransition'
export default {
computed: {},
components: {},
props: {
indexs: Number
},
data() {
return {
ossConfig: {},
imgType: true,
file: [],
host: ''
}
},
watch: {},
methods: {
onOversize(file) {
// console.log(file)
$toastText(this.$i18n.t('No_more_than'))
},
afterRead(event) {
const vm = this
console.log(event)
vm.imgType = true
if (event && event.length > 1) {
event.forEach((item) => {
if (item.file.type !== 'image/png' && item.file.type !== 'image/jpeg' && item.file.type !== 'image/jpg') {
vm.imgType = false
}
})
} else {
vm.imgType = event.file.type === 'image/jpeg' || event.file.type === 'image/png' || event.file.type === 'image/jpg'
}
if (!vm.imgType) {
$toastText(vm.$i18n.t('limit_upload'))
return false
}
$toastLoading(vm.$i18n.t('in_upload'))
if (event.status === 'failed') {
$toastText('上传失败')
}
if (event.length > 1) {
event.forEach(item => {
vm.compress(item)
})
} else {
vm.compress(event)
}
},
compress(ele) {
const vm = this
let bs64data
// BASE64
const reader = new FileReader()
// 2 base64
reader.readAsDataURL(ele.file)
//
reader.onloadend = function() {
const result = this.result
const img = new Image()
img.src = result
img.onload = function() {
bs64data = imgCompress(img)
// BASE64
var arr = bs64data.split(','); var mime = arr[0].match(/:(.*?);/)[1]; var
bstr = atob(arr[1]); var n = bstr.length; var u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
const newfile = new File([u8arr], ele.file.name, { type: mime })
vm.file = newfile
vm.submit(vm.file)
console.log(vm.file, 'file---')
}
}
},
dataURLtoFile(dataurl, filename) {
var arr = dataurl.split(',')
var mime = arr[0].match(/:(.*?);/)[1]
var bstr = atob(arr[1])
var n = bstr.length
var u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], filename, {
type: mime
})
},
submit(file) {
var self = this
var formData = new FormData()
var fileName =
self.$md5(file.name) +
Math.random() +
'.' +
file.type
.split('/')
.pop()
.toLowerCase()
var filePath = self.host + '/' + self.ossConfig.dir + fileName
formData.append('name', self.ossConfig.dir + fileName)
formData.append('key', self.ossConfig.dir + fileName)
formData.append('policy', self.ossConfig.policy)
formData.append('OSSAccessKeyId', self.ossConfig.accessid)
formData.append('success_action_status', '200')
formData.append('signature', self.ossConfig.signature)
formData.append('file', file)
formData.append('filename', file.name)
service
.post(self.host, formData, { headers: { 'Content-Type': 'multipart/form-data' }})
.then(data => {
$toastClear()
if (self.indexs) {
self.$emit('onSuccess', filePath, self.indexs)
} else {
self.$emit('onSuccess', filePath)
}
})
.catch(error => {
$toastText(self.$i18n.t('Network_anomalies'))
console.log(error)
})
},
//
getSignature() {
const vm = this
service
.get('/upload/signature')
.then(data => {
vm.ossConfig = data
vm.host = data.host
})
.catch(error => {
console.log(error)
})
}
},
created() {},
mounted() {
this.getSignature()
}
}
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,126 @@
<template>
<div>
<input type="file" @change="onChange" class="uploaderInput" accept="video/*" capture="user" />
</div>
</template>
<script>
import service from '@/utils/request'
import serviceV3 from '@/utils/requestV3'
import { $toastText } from '@/config/toast'
export default {
computed: {},
components: {},
data() {
return {
timer: null,
ossConfig: {},
file: '',
host: ''
}
},
watch: {},
methods: {
onChange(event) {
const vm = this
// $toastClear()
vm.file = event.target.files[0]
if (vm.$isIOS()) {
const oVideo = document.createElement('video')
oVideo.src = URL.createObjectURL(vm.file)
const audioElement = new Audio(oVideo.src)
audioElement.muted = true
audioElement.play().then(() => audioElement.pause())
audioElement.addEventListener('loadedmetadata', () => {
const duration = audioElement.duration
if (duration > 8) {
vm.$emit('onSuccess', 1)
} else {
console.log(vm.file)
if (!vm.file) return
vm.$emit('loadingState', true)
vm.submit(vm.file)
}
})
audioElement.muted = false
} else {
const oVideo = document.createElement('video')
oVideo.src = URL.createObjectURL(vm.file)
oVideo.onloadedmetadata = function() {
//
if (oVideo.duration > 8) {
vm.$emit('onSuccess', 1)
URL.revokeObjectURL(vm.file)
} else {
console.log(vm.file)
if (!vm.file) return
vm.$emit('loadingState', true)
vm.submit(vm.file)
}
}
}
// vm.timer = setInterval(() => {
// console.log('...')
// }, 1000)
},
submit(file) {
var self = this
var formData = new FormData()
var fileName = self.$md5(file.name) + Math.random() + '.' + file.type.split('/').pop().toLowerCase()
var filePath = self.host + '/' + self.ossConfig.dir + fileName
formData.append('name', self.ossConfig.dir + fileName)
formData.append('key', self.ossConfig.dir + fileName)
formData.append('policy', self.ossConfig.policy)
formData.append('OSSAccessKeyId', self.ossConfig.accessid)
formData.append('success_action_status', '200')
formData.append('signature', self.ossConfig.signature)
formData.append('file', file)
formData.append('filename', file.name)
serviceV3.post(self.host, formData, { headers: { 'Content-Type': 'multipart/form-data' }}).then(data => {
if (data.status === 200) {
// clearInterval(self.timer)
// self.timer = null
// console.log('...')
self.$emit('onSuccess', filePath)
} else {
self.$emit('loadingState', false)
$toastText('网络不稳定,请稍后再试')
}
}).catch(error => {
self.$emit('loadingState', false)
// clearInterval(self.timer)
// self.timer = null
$toastText('网络不稳定,请稍后再试')
console.log(error, '777888')
})
},
//
getSignature() {
const vm = this
service.get('/upload/signature').then(data => {
vm.ossConfig = data
vm.host = data.host
}).catch(error => {
console.log(error)
})
}
},
created() {
},
mounted() {
this.getSignature()
}
}
</script>
<style lang="scss" scoped>
.uploaderInput{
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
right: 0;
top: 0;
opacity: 0;
}
</style>

View File

@ -0,0 +1,234 @@
<template>
<div id='app' class='videoCourse'>
<vue-aliplayer-v2
@ready='handleReady'
@play='play'
@pause='pause'
ref='VueAliplayerV2'
style='width: 100%;height: 100%'
:options='options' />
<div class='cd-wrapper' ref='cdWrapper' v-if='audioCover'>
<div class='cd' :class='cdCls'>
<div class='image' :style="{backgroundImage:'url('+audioCover+')'}" @click='pause'></div>
</div>
</div>
<img
class='playIcon'
style='z-index: 1000'
v-if='onPlayIcon'
@click.stop='play'
src='https://images.ufutx.com/202101/29/fef68b642b5954d015f6d2740864e75d.png'
alt='' />
<!-- <button @click='play()'>播放</button>-->
<!-- <button @click='pause()'>暂停</button>-->
<!-- <button @click='replay()'>重播</button>-->
<!-- <button @click='getCurrentTime()'>播放时刻</button>-->
<!-- <span>{{ options.source }}</span>-->
</div>
</template>
<script>
import VueAliplayerV2 from 'vue-aliplayer-v2'
export default {
components: {
VueAliplayerV2
},
props: ['source', 'cover', 'autoplay'],
computed: {
cdCls() {
return this.playing ? 'play' : 'play pause'
}
},
data() {
return {
onPlayIcon: false,
playing: false,
audioCover: '',
forbidFastForward: { //
required: true,
type: [Boolean],
default: true
},
options: {
//
source: '', //
cover: '', //
autoplay: false, //
rePlay: true, //
controlBarVisibility: 'hover' // hoverclickhoveralways
// isLive: true //
// language: 'zh-custom' //
// languageTexts: { //
// 'zh-custom': {
// 'Video_Error': TipMessage, //
// 'Error_Load_M3U8_Timeout_Text': TipMessage, // m3u8
// 'Error_Load_M3U8_Failed_Text': TipMessage, // m3u8
// 'Live_Abrot': TipMessage, //
// 'Error_Not_Found': TipMessage, //
// 'Refresh_Text': '',
// 'Retry': '',
// 'Detection_Text': ''
// }
// }
}
}
},
watch: {
source: {
handler(newValue, oldValue) {
this.options.source = newValue
if (newValue.includes('mp3')) {
this.onPlayIcon = true
this.audioCover = this.options.cover
this.options.controlBarVisibility = 'always'
}
}
},
cover: {
handler(newValue, oldValue) {
this.options.cover = newValue
if (this.options.source.includes('mp3')) {
this.onPlayIcon = true
this.audioCover = newValue
}
}
},
autoplay: {
handler(newValue, oldValue) {
this.options.autoplay = newValue
}
}
},
methods: {
/**
* 在这里需要注意的是 this.$refs 可能会返回是数组,或者对象,这个在用的时候需要注意一下.且因为是异步渲染dom,所以最好是在 this.$nextTick(()=>{ //todo });
* 事件可以参考文档 https://help.aliyun.com/document_detail/125572.html?spm=a2c4g.11186623.6.1085.36fc6fc57WKZ5P#h2-u64ADu653Eu5668u4E8Bu4EF63
*/
play() {
this.$refs.VueAliplayerV2.play()
this.onPlayIcon = false
this.playing = true
console.log('12')
},
pause() {
this.$refs.VueAliplayerV2.pause()
this.onPlayIcon = true
this.playing = false
console.log('13')
},
replay() {
this.$refs.VueAliplayerV2.replay()
},
getCurrentTime() {
this.$refs.VueAliplayerV2.getCurrentTime()
},
/**
* 播放器事件回调
*/
handleReady(e) {
console.log(`ready`, e)
}
},
mounted() {
}
}
</script>
<style lang='scss' scoped>
//::v-deep .prism-player{
//background-repeat: no-repeat;
//background-position: center;
//background-size: cover;
//position: relative;
//&::after{
// content: '';
// width: 100%;
// height: 100%;
// background: rgba(88, 88, 88, 0.3);
// position: absolute;
// filter: blur(4px);
// left: 0;
// top: 0;
//}
//}
.cd-wrapper {
position: absolute;
width: 100px;
height: 100px;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
border: 4px solid #fff4f7;
border-radius: 50%;
background: white;
box-shadow: 0 0 12px #cacaca;
.cd {
.image {
width: 100px;
height: 100px;
border-radius: 50%;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
}
}
.play{
//animation-name: Rotate; /*keyframe */
//animation-iteration-count: infinite; /* ,infinite*/
animation-play-state: running; /*规定动画正在运行还是暂停,paused为暂停*/
//animation-timing-function: linear; /*线*/
//animation-duration: 5s; /**/
animation: Rotate 5S infinite linear;
@keyframes Rotate {
from {
transform: rotateZ(0);
}
to {
transform: rotateZ(360deg);
}
}
}
.pause {
animation-play-state: paused; /*规定动画正在运行还是暂停,paused为暂停*/
}
.videoCourse {
width: 100vw;
min-height: 210px;
position: relative;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
.playIcon {
position: absolute;
width: 46px;
height: 46px;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
}
}
* {
margin: 0;
padding: 0;
}
::v-deep .prism-player .prism-cc-btn {display: none !important;}
::v-deep .prism-player .prism-volume {
margin-right: 12px !important;}
::v-deep .prism-player .prism-setting-btn {
margin-right: 12px !important;
}
</style>

View File

@ -0,0 +1,143 @@
<template>
<div class="waterfallFlowList">
<div class="list_box">
<div :id="type + '_list_box_left'" ref="listBoxLeft">
<div class="list_item_box">
<div class="list_item_add_box f-fcc">
<div class="f-fdc" @click="toWear(type)">
<img
class="add_icon"
src="https://image.fulllinkai.com/202110/25/9ba1b1b22520ad6983bd5cf4d34e7c7a.png"
alt=""
/>
<div class="colorTheme font15">自定义创建</div>
</div>
</div>
</div>
<div class="list_item_box" v-for="(item, index) in listLeft" :key="index" @click="goToUrlId(item)">
<slot name="upload" :msg="item"></slot>
</div>
</div>
<div :id="type + '_list_box_right'" ref="listBoxRight">
<div class="list_item_box" v-for="(item, index) in listRight" :key="index" @click="goToUrlId(item)">
<slot name="upload" :msg="item"></slot>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
computed: {},
components: {},
props: {
list: {
type: Array,
default: () => {
return []
}
},
type: {
type: String,
default: ''
},
page: {
type: Number,
default: 1
}
},
data() {
return {
listLeft: [],
listRight: []
}
},
watch: {
list(e) {
if (this.page === 1) {
this.listLeft = []
this.listRight = []
}
if (e.length > 0) {
e.forEach((item, index) => {
this.getOffsetWidth(item)
})
}
},
listRight() {
// this.getOffsetWidth()
},
listLeft() {
// this.getOffsetWidth()
}
},
methods: {
getOffsetWidth(item) {
const vm = this
setTimeout(() => {
vm.$nextTick(() => {
var listLeft = document.getElementById(vm.type + '_list_box_left')
var listRight = document.getElementById(vm.type + '_list_box_right')
var h_l = listLeft.offsetHeight
var h_r = listRight.offsetHeight
if (h_l < h_r) {
vm.listLeft.push(item)
} else {
vm.listRight.push(item)
}
})
}, 200)
},
toWear(e) {
this.$emit('toWearWat', e)
},
goToUrlId(e) {
this.$emit('goToUrlId', e)
}
},
created() {},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
}
}
</script>
<style lang="scss" scoped>
.waterfallFlowList {
.list_box {
padding-top: 5px;
margin: 8px 15px 15px 15px;
display: flex;
justify-content: space-between;
align-items: flex-start;
.list_item_box {
position: relative;
margin-bottom: 12px;
.list_item_icon {
position: absolute;
right: 10px;
top: 10px;
}
.list_item_add_box {
width: 162px;
height: 184px;
border-radius: 8px;
border: 1px dashed #979797;
.add_icon {
width: 26px;
height: 26px;
display: block;
margin: 0 auto 13px auto;
}
.list_item_add {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
}
}
}
</style>

View File

@ -0,0 +1,221 @@
<template>
<div class="worldPhone">
<div>
<div class="alignment">
<div class="font14 color3 bold text-center">真实姓名</div>
<van-field class="inputBox u_hx" :readonly='readonly' type="text" v-model="name" :placeholder="$t('name_Tips')" />
</div>
</div>
<div>
<div class="alignment f-fc">
<div class="font14 color3 bold text-left" style="max-width: 26%">手机号码</div>
<div class="area_code_box f-fc" :class="areaTipa">
<div class="area_code alignment" @click.stop="switchChoose">
<div class="font13 color3">{{ AreaValue }}</div>
<div class="alignment_right">
<img class="Angle_icon" v-if="showChooseArea" src="https://image.fulllinkai.com/202112/10/697cbb5933196bbc21165cb974f2e343.png" alt="" />
<img class="Angle_icon" v-else src="https://image.fulllinkai.com/202112/10/02d4c797f6de6494643f506c5d2b85b7.png" alt="" />
</div>
</div>
<div class="vertical_line"></div>
<van-field class="inputBox" :readonly='readonly' type="number" maxlength="16" v-model="mobile" :placeholder="$t('iphone_Tips')" />
<div class="area_code_choose_box" :class="areaTipa" v-if="showChooseArea">
<div class="alignment area_code_choose" v-for="(item, index) in arerList" :key="index" @click="selectedArea(item)">
<div class="font14 color3" :class="AreaValue == item.nation_code ? 'chooseColor' : ''">
{{ item.nation_code }} {{ item.nation_name }}
</div>
</div>
</div>
</div>
</div>
</div>
<div v-if="n_type==='activity'">
<div class="alignment">
<div class="font14 color3 bold text-center ui-sex-title">性别</div>
<van-radio-group v-model="sex" direction="horizontal" class="ui-sex-style" :disabled='readonly'>
<van-radio name="男"></van-radio>
<van-radio name="女"></van-radio>
</van-radio-group>
</div>
</div>
</div>
</template>
<script>
import service from '@/utils/request'
export default {
computed: {},
components: {},
props: {
linkmen: {
type: Object,
default: () => {
return {}
}
},
introduces: {
type: String,
default: ''
},
areaTipa: {
type: String,
default: 'top'
},
n_type: {
type: String,
default: ''
},
readonly: {
type: Boolean,
default: false
}
},
data() {
return {
arerList: [],
showChooseArea: false,
AreaValue: '+86',
name: '',
mobile: '',
sex: ''
}
},
watch: {
name(e) {
this.$emit('getWorldPhoneData', { type: 'name', name: e })
},
mobile(e) {
this.$emit('getWorldPhoneData', { type: 'mobile', name: e })
},
AreaValue(e) {
this.$emit('getWorldPhoneData', { type: 'AreaValue', name: e })
},
sex(e) {
this.$emit('getWorldPhoneData', { type: 'sex', name: e })
}
},
methods: {
//
selectedArea(e) {
this.AreaValue = e.nation_code
this.showChooseArea = !this.showChooseArea
},
//
switchChoose() {
this.showChooseArea = !this.showChooseArea
},
//
getAreaCode() {
const vm = this
const url = `s/h5/get/nation/mobile/area/code`
service
.get(url)
.then(data => {
vm.arerList = data.list
})
.catch(error => {
console.log(error)
})
}
},
created() {
},
mounted() {
const ScrollTop = document.getElementById('app')
ScrollTop.scrollTop = 0
this.getAreaCode()
if (this.introduces !== 'confirmOrder') {
if (this.linkmen && this.linkmen.mobile) {
// this.mobile = this.linkmen.mobile
}
if (this.linkmen && this.linkmen.name) {
// this.name = this.linkmen.name
}
if (this.linkmen && this.linkmen.sex) {
// this.sex = this.linkmen.sex
}
}
}
}
</script>
<style lang="scss" scoped>
.worldPhone {
width: 100%;
.area_code_box.top {
border-bottom: 1px solid #f5f5f5;
}
.area_code_box {
flex: 1;
position: relative;
margin-left: 6px;
.area_code {
.Angle_icon {
width: 10px;
height: 6px;
display: block;
margin-left: 5px;
}
}
.vertical_line {
width: 1px;
height: 24px;
background: #f5f5f5;
margin: 0 10px;
}
.area_code_choose_box.bottom {
top: 40px;
}
.area_code_choose_box {
position: absolute;
left: 0;
top: -166px;
width: 76%;
height: 166px;
background: #ffffff;
border: 1px solid #f5f5f5;
border-radius: 8px;
z-index: 22222;
overflow-x: hidden;
overflow-y: scroll;
.area_code_choose {
padding: 15px 15px 0 15px;
.selected_icon {
width: 18px;
height: 18px;
display: block;
}
}
.area_code_choose:last-child {
padding-bottom: 15px;
}
.chooseColor {
color: #f33b6c;
}
}
.van-cell {
padding-left: 80px;
}
}
.inputBox {
flex: 1;
outline: none;
appearance: none;
padding: 15px 0;
font-size: 14px;
padding-left: 0 !important;
}
.inputBox.u_hx {
margin-left: 6px;
border-bottom: 1px solid #f5f5f5;
}
.ui-sex-title{
margin-left: 12px;
}
.ui-sex-style{
flex: 1;
padding: 15px 0;
font-size: 14px;
}
}
</style>

View File

@ -0,0 +1,12 @@
// 本地环境配置
module.exports = {
title: '',
// baseApi: '//h5.ufutx.net/api' // 本地api请求地址,注意:如果你使用了代理,请设置成'/'
baseApi: '//sh5.ufutx.net/api', // 本地api请求地址,注意:如果你使用了代理,请设置成'/'
baseApiV2: '//sh5.ufutx.net/api', // 本地api请求地址,注意:如果你使用了代理,请设置成'/'
baseApiV3: '//eval.fulllinkai.net/api', // 本地api请求地址,注意:如果你使用了代理,请设置成'/'
// baseApi: '//api.ufutx.net/mock' // 本地api请求地址,注意:如果你使用了代理,请设置成'/'
// APPID: 'xxx',
// APPSECRET: 'xxx'
// $cdn: 'https://www.sunniejs.cn/static'
}

View File

@ -0,0 +1,11 @@
// 正式
module.exports = {
title: '',
// baseUrl: 'https://love.ufutx.com/h5/', // 正式项目地址
baseApi: '//love.ufutx.cn/api', // 正式api请求地址
baseApiV2: '//sh5.ufutx.net/api', // 正式api请求地址
baseApiV3: '//eval.fulllinkai.com/api' // 正式api请求地址
// APPID: 'xxx',
// APPSECRET: 'xxx',
// $cdn: 'https://www.sunniejs.cn/static'
}

View File

@ -0,0 +1,8 @@
module.exports = {
// title: '',
// baseUrl: 'https://test.xxx.com', // 测试项目地址
// baseApi: 'https://test.xxx.com/api', // 测试api请求地址
// APPID: 'xxx',
// APPSECRET: 'xxx',
// $cdn: 'https://www.sunniejs.cn/static'
}

4
src/config/index.js Normal file
View File

@ -0,0 +1,4 @@
// 根据环境引入不同配置 process.env.VUE_APP_ENV
const environment = process.env.VUE_APP_ENV || 'production'
const config = require('./env.' + environment)
module.exports = config

14
src/config/swiper.js Normal file

File diff suppressed because one or more lines are too long

27
src/config/toast.js Normal file
View File

@ -0,0 +1,27 @@
import { Toast } from 'vant'
export const $toastText = (title) => {
Toast({
message: title,
duration: 3000
})
}
export const $toastSuccess = (title) => {
Toast.success({
message: title,
forbidClick: true
})
}
export const $toastLoading = (title) => {
Toast.loading({
message: title,
duration: 0,
forbidClick: true
})
}
export const $toastClear = () => {
Toast.clear()
}

85
src/filters/filter.js Normal file
View File

@ -0,0 +1,85 @@
import { Dialog } from 'vant'
/**
*格式化时间
*yyyy-MM-dd hh:mm:ss
*/
export function formatDate(time, fmt) {
if (time === undefined || '') {
return
}
const date = new Date(time)
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
}
const o = {
'M+': date.getMonth() + 1,
'd+': date.getDate(),
'h+': date.getHours(),
'm+': date.getMinutes(),
's+': date.getSeconds()
}
for (const k in o) {
if (new RegExp(`(${k})`).test(fmt)) {
const str = o[k] + ''
fmt = fmt.replace(RegExp.$1, RegExp.$1.length === 1 ? str : padLeftZero(str))
}
}
return fmt
}
function padLeftZero(str) {
return ('00' + str).substr(str.length)
}
/**
*
*格式化现在距${endTime}的剩余时间
*{Date} endTime
*{String}
*/
export function formatRemainTime(endTime) {
var startDate = new Date() // 开始时间
var endTimeArr = endTime.replace(/-/g, '/')
var endDate = new Date(endTimeArr) // 结束时间
var t = endDate.getTime() - startDate.getTime() // 时间差
var d = 0
var h = 0
var m = 0
var s = 0
if (t >= 0) {
d = Math.floor(t / 1000 / 3600 / 24)
h = Math.floor((t / 1000 / 60 / 60) % 24)
m = Math.floor((t / 1000 / 60) % 60)
s = Math.floor((t / 1000) % 60)
}
return d + '天 ' + h + '小时 ' + m + '分钟 ' + s + '秒'
}
/*
* 隐藏用户手机号中间四位
*/
export function hidePhone(phone) {
return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}
/*
* 授权获取微信头像名称
*/
export function authorization(shareCallback, merchant_id, jump_url) {
// alpha: wx36c72a00f1b2be64 master: wx36c72a00f1b2be64
Dialog.confirm({
title: '需要您的授权',
confirmButtonText: '确认授权',
message: '为了提供更好的服务请在稍后的提示框中点击“允许”'
})
.then(() => {
const appid = location.href.includes('https') ? 'wx36c72a00f1b2be64' : 'wx4adff200da8333ca'
window.location.replace(
`https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=` +
encodeURIComponent(
`${shareCallback}/api/official/newNonSilenceAuth?merchant_id=${merchant_id}&from_openid=${localStorage.getItem('from_openid')}&alliance_id=${localStorage.getItem('from_alliance_id')}&jump_url=${jump_url}`
) +
`&response_type=code&scope=snsapi_userinfo&state=STATE&connect_redirect=1#wechat_redirect`
)
})
.catch(() => {
})
}

10
src/filters/index.js Normal file
View File

@ -0,0 +1,10 @@
import Vue from 'vue'
import * as filter from './filter'
Object.keys(filter).forEach(k => Vue.filter(k, filter[k]))
Vue.prototype.$formatDate = Vue.filter('formatDate')
Vue.prototype.$formatRemainTime = Vue.filter('formatRemainTime')
Vue.prototype.$hidePhone = Vue.filter('hidePhone')
Vue.prototype.$authorization = Vue.filter('authorization')
Vue.prototype.$commentTimeHandle = Vue.filter('commentTimeHandle')

226
src/main.js Normal file
View File

@ -0,0 +1,226 @@
// 兼容 IE
// https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md#babelpolyfill
import 'core-js/stable'
import 'regenerator-runtime/runtime'
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
import wxShare from '@/plugins/wxShare'
import md5 from 'js-md5'
import CanvasPoster from 'vue-canvas-poster'
import service from '@/utils/request'
// 设置 js中可以访问 $cdn
import { $cdn } from '@/config'
Vue.prototype.$cdn = $cdn
Vue.config.ignoredElements = ['wx-open-launch-weapp']
// 全局引入按需引入UI库 vant
import '@/plugins/vant'
// 引入全局样式
import '@/assets/css/index.scss'
// 移动端适配
import 'lib-flexible/flexible.js'
import clipboard from 'clipboard'
// 颜色选择器
import vcolorpicker from 'vcolorpicker'
Vue.use(vcolorpicker)
// 地图
import VueAMap from 'vue-amap'
Vue.use(VueAMap)
VueAMap.initAMapApiLoader({
key: 'cb272bd52971913f1b6c4dbce3269e9b',
plugin: [
'AMap.Autocomplete',
'AMap.PlaceSearch',
'AMap.Scale',
'AMap.OverView',
'AMap.ToolBar',
'AMap.MapType',
'AMap.PolyEditor',
'AMap.CircleEditor',
'AMap.Geocoder'
],
// 默认高德 sdk 版本为 1.4.4
v: '1.4.4'
})
// filters
import './filters'
import VueI18n from 'vue-i18n'
import VueWechatTitle from 'vue-wechat-title'
Vue.use(VueWechatTitle)
Vue.use(VueI18n)
// Vue.use(require('vue-wechat-title'))
Vue.config.productionTip = false
Vue.prototype.$clipboard = clipboard
Vue.prototype.$md5 = md5
Vue.use(wxShare)
Vue.use(CanvasPoster)
import { RadioGroup, Radio, AddressEdit } from 'vant'
Vue.use(AddressEdit)
Vue.use(Radio)
Vue.use(RadioGroup)
var i18n = new VueI18n({
locale: localStorage.getItem('locale') || 'zh',
messages: {
zh: require('@/assets/i18n/zh-CN.json')
// en: require('@/assets/i18n/en.json'),
// tw: require('@/assets/i18n/zh-TW.json')
},
silentTranslationWarn: true
})
router.onError(error => {
const pattern = /Loading chunk (\d)+ failed/g
const isChunkLoadFailed = error.message.match(pattern)
if (isChunkLoadFailed) {
window.location.reload()
} else {
console.log(error)
}
})
router.beforeEach((to, from, next) => {
store.commit('editShareChannelId', '')
store.commit('editRouterTo', to)
store.commit('editRouterName', to.name)
localStorage.removeItem('aliplayer_lang_data_h5_2_8_8_zh-cn')
localStorage.removeItem('wxConfig')
// if (to.query.openid) {
// localStorage.setItem('openid', to.query.openid)
// }
if (to.query.platform) {
localStorage.setItem('platform', to.query.platform)
}
if (to.query.share_channel_id) {
store.commit('editShareChannelId', to.query.share_channel_id)
}
if (to.query.locale) {
localStorage.setItem('locale', to.query.locale)
}
if (to.query.anchor_openid) {
localStorage.setItem('anchor_openid', to.query.anchor_openid)
localStorage.removeItem('merchant_id')
}
if (to.query.from_openid && to.query.from_openid !== '' && to.query.from_openid !== 'null' && to.query.from_openid !== null) {
localStorage.setItem('from_openid', to.query.from_openid || '')
} else {
localStorage.setItem('from_openid', '')
}
if (to.query.alliance_id && to.query.alliance_id !== '' && to.query.alliance_id !== 'null' && to.query.alliance_id !== null) {
localStorage.setItem('from_alliance_id', to.query.alliance_id || '')
}
if (to.query.merchant_id) {
const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)
console.log('开发环境', IS_PROD)
if (!IS_PROD) {
localStorage.setItem(
'saas_token',
'eyJpdiI6ImNoV0hTOFJCSjlSMklkYis4OHUrblE9PSIsInZhbHVlIjoicGZCZjFjS3d1UUl0ek1sUW52aVdqcGo2V0VwZGE4SCtpZTUrS1lGQ0czcDJLcDB2YlpENlNZd28xNkl1ZGJCTiIsIm1hYyI6IjhkYzlkMzAzZGQ2YTljMTVlY2YwOWIxMmQ2Y2I0ODE2M2Y5MDExNDdjMWMxZWU0ZDYyNWNmNmFkYTlhMmMzNTEifQ=='
)
localStorage.setItem('authorize_at', '2022-01-17 10:39:24')
}
if (to.path != '/welcome' && to.path != '/login' && !localStorage.getItem('saas_token') && to.path != '/downloadApp' && to.path != '/channelFailure' && !to.path.includes('/reviewResults') && !to.path.includes('/dynamicParticulars')) {
const url = `/official/communities/get_token`
service
.get(url)
.then(data => {
if (data.token) {
store.commit('editToken', data.token)
localStorage.setItem('saas_token', data.token)
localStorage.setItem('user_id', data.id)
localStorage.removeItem('one_first')
next()
} else {
if (location.href.includes('https')) {
window.location.href = `${Vue.prototype.$shareCallback}/api/official/live/wechat/FamilyAuth?merchant_id=${to.query.merchant_id}&from_openid=${localStorage.getItem('from_openid')}&url=` + encodeURIComponent(`${Vue.prototype.$shareCallback}/pu/#/information`)
} else {
window.location.href = `http://sh5.ufutx.net/api/official/live/wechat/FamilyAuth?merchant_id=${to.query.merchant_id}&from_openid=${localStorage.getItem('from_openid')}&url=` + encodeURIComponent(`http://sh5.ufutx.net/pu/#/information`)
}
}
})
.catch(error => {
console.log(error)
})
} else {
next()
}
store.commit('editMerchantId', to.query.merchant_id)
if (to.query.spread_merchant_id) {
store.commit('editSpreadMerchantId', to.query.spread_merchant_id)
localStorage.setItem('spread_merchant_id', to.query.spread_merchant_id)
}
localStorage.setItem('merchant_id', to.query.merchant_id)
localStorage.removeItem('anchor_openid')
} else {
if (from.query.merchant_id) {
var toQuery = JSON.parse(JSON.stringify(to.query))
toQuery.merchant_id = from.query.merchant_id
toQuery.spread_merchant_id = from.query.spread_merchant_id || ''
toQuery.from_openid = from.query.from_openid || ''
toQuery.share_channel_id = from.query.share_channel_id
next({
path: to.path,
query: toQuery
})
} else {
next()
}
if (!store.state.app.merchant_id) {
if (to.path != '/missingPage') {
next({ path: '/missingPage' })
} else {
next()
}
}
}
})
router.afterEach((to, from) => {
if (window.ga) {
window.ga('set', 'page', to.meta.title) // 你可能想根据请求参数添加其他参数,可以修改这里的 to.fullPath
window.ga('send', 'pageview')
}
})
// 全局授权、分享回调域名
// alpha: http://sh5.ufutx.net master: https://love.ufutx.com
if (!window.location.origin) {
window.location.origin = window.location.protocol + '//' + window.location.host
}
Vue.prototype.$shareCallback = window.location.origin
// 全局谷歌统计事件
Vue.prototype.$BuriedPoint = (action, label, value) => {
if (value === undefined) {
window.ga && window.ga('send', 'event', action, label)
} else {
window.ga && window.ga('send', 'event', action, label, value)
}
}
Vue.prototype.$isWeiXin = () => {
var ua = window.navigator.userAgent.toLowerCase()
if (ua.includes('micromessenger')) {
return true
} else {
return false
}
}
Vue.prototype.$isIOS = () => {
const u = navigator.userAgent
const isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1
if (isAndroid) {
return false
} else {
return true
}
}
new Vue({
el: '#app',
router,
i18n,
store,
render: h => h(App)
}).$mount('#app')

View File

@ -0,0 +1,132 @@
/**
* @desc 格式化日期字符串
* @param { Nubmer} - 时间戳
* @returns { String } 格式化后的日期字符串
*/
export function formatDate(timestamps) {
// 补全为13位
let timestamp = timestamps.replace(/-/g, '/')
timestamp = new Date(timestamp).getTime().toString()
const minute = 1000 * 60
const hour = minute * 60
const day = hour * 24
const month = day * 30
const now = new Date().getTime()
const diffValue = now - timestamp
// 如果本地时间反而小于变量时间
if (diffValue < 0) {
return '不久前'
}
// 计算差异时间的量级
const monthC = diffValue / month
const weekC = diffValue / (7 * day)
const dayC = diffValue / day
const hourC = diffValue / hour
const minC = diffValue / minute
// 数值补0方法
const zero = function(value) {
if (value < 10) {
return '0' + value
}
return value
}
// 使用
if (monthC > 4) {
// 超过1年直接显示年月日
return (function() {
const date = new Date(timestamps)
return date.getFullYear() + '年' + zero(date.getMonth() + 1) + '月' + zero(date.getDate()) + '日'
})()
} else if (monthC >= 1) {
return parseInt(monthC) + '月前'
} else if (weekC >= 1) {
return parseInt(weekC) + '周前'
} else if (dayC >= 1) {
return parseInt(dayC) + '天前'
} else if (hourC >= 1) {
return parseInt(hourC) + '小时前'
} else if (minC >= 1) {
return parseInt(minC) + '分钟前'
}
return '刚刚'
}
export function formatDateV2(timestamps) {
// 补全为13位
let timestamp = timestamps.replace(/-/g, '/')
timestamp = new Date(timestamp).getTime().toString()
const minute = 1000 * 60
const hour = minute * 60
const day = hour * 24
const month = day * 30
const now = new Date().getTime()
const diffValue = now - timestamp
// 如果本地时间反而小于变量时间
if (diffValue < 0) {
return '不久前'
}
// 计算差异时间的量级
const monthC = diffValue / month
const weekC = diffValue / (7 * day)
const dayC = diffValue / day
const hourC = diffValue / hour
const minC = diffValue / minute
// 数值补0方法
// const zero = function(value) {
// if (value < 10) {
// return '0' + value
// }
// return value
// }
// 使用
if (monthC > 12) {
// 超过1年直接显示年月日
return (function() {
const date = new Date(timestamps)
const dateV2 = new Date()
return dateV2.getFullYear() - date.getFullYear() + '年前'
})()
} else if (monthC >= 1) {
return parseInt(monthC) + '个月前'
} else if (weekC >= 1) {
return parseInt(weekC) + '周前'
} else if (dayC >= 1) {
return parseInt(dayC) + '天前'
} else if (hourC >= 1) {
return parseInt(hourC) + '小时前'
} else if (minC >= 1) {
return parseInt(minC) + '分钟前'
}
return '刚刚'
}
// 倒计时
export function formatRemainTimeData(endTime) {
var startDateV2 = new Date() // 开始时间
var endTimeArrV2 = endTime.replace(/-/g, '/')
var endDateV2 = new Date(endTimeArrV2) // 结束时间
var tV2 = endDateV2.getTime() - startDateV2.getTime() // 时间差
var dV2 = 0
var hV2 = 0
var mV2 = 0
var sV2 = 0
if (tV2 >= 0) {
dV2 = Math.floor(tV2 / 1000 / 3600 / 24)
hV2 = Math.floor((tV2 / 1000 / 60 / 60) % 24)
mV2 = Math.floor((tV2 / 1000 / 60) % 60)
sV2 = Math.floor((tV2 / 1000) % 60)
}
// 修改小时格式
if (hV2 >= 0 && hV2 <= 9) {
hV2 = '0' + hV2
}
// 修改分钟格式
if (mV2 >= 0 && mV2 <= 9) {
mV2 = '0' + mV2
}
// 修改秒格式
if (sV2 >= 0 && sV2 <= 9) {
sV2 = '0' + sV2
}
return { d: dV2, h: hV2, m: mV2, s: sV2 }
}

View File

@ -0,0 +1,99 @@
function formatDate(date, fmt) {
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
}
const o = {
'M+': date.getMonth() + 1,
'd+': date.getDate(),
'h+': date.getHours(),
'm+': date.getMinutes(),
's+': date.getSeconds()
}
for (const k in o) {
if (new RegExp(`(${k})`).test(fmt)) {
const str = o[k] + ''
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str))
}
}
return fmt
}
function padLeftZero(str) {
return ('00' + str).substr(str.length)
}
function imgCompress(img, Orientation) {
const imgType = img.type
var newImg
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
// 瓦片canvas
const tCanvas = document.createElement('canvas')
const tctx = tCanvas.getContext('2d')
const initSize = img.src.length
let width = img.width
let height = img.height
// 如果图片大于四百万像素计算压缩比并将大小压至400万以下
let ratio
if ((ratio = width * height / 4000000) > 1) {
console.log('大于400万像素')
ratio = Math.sqrt(ratio)
width /= ratio
height /= ratio
} else {
ratio = 1
}
canvas.width = width
canvas.height = height
// 铺底色
ctx.fillStyle = '#fff'
ctx.fillRect(0, 0, canvas.width, canvas.height)
// 如果图片像素大于100万则使用瓦片绘制
let count
if ((count = width * height / 1000000) > 1) {
console.log('超过100W像素')
count = ~~(Math.sqrt(count) + 1) // 计算要分成多少块瓦片
// 计算每块瓦片的宽和高
const nw = ~~(width / count)
const nh = ~~(height / count)
tCanvas.width = nw
tCanvas.height = nh
for (let i = 0; i < count; i++) {
for (let j = 0; j < count; j++) {
tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh)
ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh)
}
}
} else {
ctx.drawImage(img, 0, 0, width, height)
}
// 修复ios上传图片的时候 被旋转的问题
if (Orientation !== '' && Orientation !== 1) {
switch (Orientation) {
case 6: // 需要顺时针向左90度旋转
this.rotateImg(img, 'left', canvas)
break
case 8: // 需要逆时针向右90度旋转
this.rotateImg(img, 'right', canvas)
break
case 3: // 需要180度旋转
this.rotateImg(img, 'right', canvas) // 转两次
this.rotateImg(img, 'right', canvas)
break
}
}
// 进行最小压缩
const ndata = canvas.toDataURL('image/jpeg', 0.4)
console.log('压缩前:' + initSize)
console.log('压缩后:' + ndata.length)
// console.log('ndata:' + JSON.stringify(ndata))
console.log('压缩率:' + ~~(100 * (initSize - ndata.length) / initSize) + '%')
tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0
return ndata
}
export {
formatDate,
imgCompress
}

66
src/plugins/vant.js Normal file
View File

@ -0,0 +1,66 @@
// 按需全局引入 vant组件
import Vue from 'vue'
import {
Button,
List,
PullRefresh,
Cell,
Rate,
Picker,
Tabbar,
TabbarItem,
Swipe,
SwipeItem,
ActionSheet,
Tab,
Tabs,
Popup,
Uploader,
Dialog,
Popover,
NoticeBar,
Image as VanImage,
Overlay,
DropdownMenu,
DropdownItem,
Field,
DatetimePicker,
Collapse,
Area,
RadioGroup,
Checkbox,
CheckboxGroup,
Radio,
CollapseItem
} from 'vant'
Vue.use(Button)
Vue.use(RadioGroup)
Vue.use(Radio)
Vue.use(CheckboxGroup)
Vue.use(Checkbox)
Vue.use(Cell)
Vue.use(List)
Vue.use(PullRefresh)
Vue.use(Popup)
Vue.use(Rate)
Vue.use(Swipe)
Vue.use(SwipeItem)
Vue.use(Tab)
Vue.use(Tabs)
Vue.use(Dialog)
Vue.use(Popover)
Vue.use(NoticeBar)
Vue.use(Picker)
Vue.use(Area)
Vue.use(Overlay)
Vue.use(Uploader)
Vue.use(ActionSheet)
Vue.use(Tabbar).use(TabbarItem)
Vue.use(VanImage)
Vue.use(DropdownMenu)
Vue.use(DropdownItem)
Vue.use(Field)
Vue.use(DatetimePicker)
Vue.use(Collapse)
Vue.use(CollapseItem)

68
src/plugins/wxShare.js Normal file
View File

@ -0,0 +1,68 @@
import wx from 'weixin-js-sdk'
import store from '@/store'
// import { $toastText } from '@/config/toast'
const base = {}
base.install = function(Vue, options) {
Vue.prototype.$shareList = function(imgUrl, link, desc, title) {
// 分享
let share_title = ``
if (!localStorage.getItem('from_openid') || (localStorage.getItem('from_openid') && localStorage.getItem('from_openid').length < 20)) {
share_title = ''
} else if (store.state.app.info.nickname && store.state.app.info.nickname.length > 4) {
share_title = store.state.app.info.nickname.substring(0, 4) + '..推送'
} else {
share_title = store.state.app.info.nickname + '推送'
}
wx.config(store.state.app.configData)
wx.ready(function() {
wx.hideMenuItems({
menuList: [] // 屏蔽复制链接
})
wx.updateAppMessageShareData({
title: desc !== '欢迎和我预约' ? share_title + '《' + title + '》' : `${title}】商家预约`, // 分享标题
desc: desc, // 分享描述
link: link, // 分享链接
imgUrl: imgUrl, // 分享图标
success: function() {
console.log('分享成功')
},
cancel: function() {
console.log('分享失败')
}
})
// 微信分享菜单测试
wx.updateTimelineShareData({
title: share_title + '《' + title + '》', // 分享标题
desc: desc, // 分享描述
link: link, // 分享链接
imgUrl: imgUrl, // 分享图标
success: function() {
console.log('分享成功')
},
cancel: function() {
console.log('分享失败')
}
})
wx.onMenuShareAppMessage({
title: share_title + '《' + title + '》', // 分享标题
desc: desc, // 分享描述
link: link, // 分享链接;在微信上分享时,该链接的域名必须与企业某个应用的可信域名一致
imgUrl: imgUrl, // 分享图标
success: function() {
console.log('分享成功-企业') // 用户确认分享后执行的回调函数
},
cancel: function() {
// 用户取消分享后执行的回调函数
}
})
})
wx.error(function(err) {
// $toastText('网络异常,请稍后重试')
console.log(JSON.stringify(err), '7777777777777')
// alert(JSON.stringify(err))
})
}
}
export default base

42
src/router/index.js Normal file
View File

@ -0,0 +1,42 @@
import Vue from 'vue'
import Router from 'vue-router'
import { constantRouterMap } from './router.config.js'
// hack router push callback
const originalPush = Router.prototype.push
Router.prototype.push = function push(location, resolve, reject) {
if (resolve || reject) {
return originalPush.call(this, location, resolve, reject)
} else {
return originalPush.call(this, location).catch(err => err)
}
}
Vue.use(Router)
const createRouter = () =>
new Router({
// mode: 'history', // 如果你是 history模式 需要配置vue.config.js publicPath
// base: process.env.BASE_URL,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
if (from.meta.keepAlive) {
from.meta.savedPosition = document.body.scrollTop
}
return { x: 0, y: to.meta.savedPosition || 0 }
}
},
routes: constantRouterMap
})
const router = createRouter()
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher // reset router
}
export default router

1203
src/router/router.config.js Normal file

File diff suppressed because it is too large Load Diff

25
src/store/getters.js Normal file
View File

@ -0,0 +1,25 @@
const getters = {
token: state => state.app.token,
userName: state => state.app.userName,
// qrCodeId: state => state.app.qrCodeId,
template: state => state.app.template,
myPosition: state => state.app.myPosition,
servePosition: state => state.app.servePosition,
activityPosition: state => state.app.activityPosition,
coursePosition: state => state.app.coursePosition,
consultPosition: state => state.app.consultPosition,
merchant_id: state => state.app.merchant_id,
spread_merchant_id: state => state.app.spread_merchant_id,
mallPosition: state => state.app.mallPosition,
info: state => state.app.info,
userArr: state => state.app.userArr,
sortingArr: state => state.app.sortingArr,
sortingState: state => state.app.sortingState,
userData: state => state.app.userData,
routerName: state => state.app.routerName,
routerTo: state => state.app.routerTo,
configData: state => state.app.configData,
dsPosition: state => state.app.dsPosition,
shareChannelId: state => state.app.shareChannelId
}
export default getters

Some files were not shown because too many files have changed in this diff Show More