Compare commits

...

39 Commits

Author SHA1 Message Date
yujialong c26e1fc4f0 fix 2 weeks ago
yujialong 333d47faa8 fix 3 months ago
yujialong b04cf6a314 fix 3 months ago
yujialong 88a91b011a 订单相关 4 months ago
yujialong 05a9bc94bc fix 4 months ago
yujialong d5146fab77 订单:试用默认1月,批量设置期限 5 months ago
yujialong 960bd8ec5c 添加订单续费功能 5 months ago
yujialong c5d0dbc3b0 默认进入页面改成/index/index,去掉/home/home 5 months ago
yujialong 95dfc84958 fix 5 months ago
yujialong 26d4d20643 抖音小程序上线 5 months ago
yujialong 3123e5f30b 用户协议 6 months ago
yujialong 74b0922b21 抖音登录(试运营版) 6 months ago
yujialong 83255d6f91 抖音登录 6 months ago
yujialong 913886a897 默认页面设置为/pages/index/index,即不登录也可以看首页 6 months ago
yujialong 0f1a67fa54 抖音版适配 6 months ago
yujialong eadeccee20 上传头像更改为阿里云上传 8 months ago
yujialong 700f576596 fix 8 months ago
yujialong 77554b79ad fix 12 months ago
yujialong 9f45d81bee 抖音小程序(未审核通过,待修改) 1 year ago
yujialong edd2c9ea0c 分享、暂无权限 1 year ago
yujialong d23d45f8a6 友盟统计 1 year ago
yujialong 79b808404a fix 1 year ago
yujialong 1c95bf74ea fix 1 year ago
yujialong 19f0e898af fix 1 year ago
yujialong cf1162858b fix 1 year ago
yujialong bb753c0b02 fix 1 year ago
yujialong 0d1dd45c8b fix 1 year ago
yujialong 66b112f80f fix 1 year ago
yujialong 9d78448e9e fix 1 year ago
yujialong 138c3221a1 图片压缩 1 year ago
yujialong 693d4852c0 全部开发完成 1 year ago
yujialong 8d2d820c40 购物车、产品详情等 1 year ago
yujialong 61114ba893 首页、产品详情等开发 1 year ago
yujialong 1cebaa25e9 Merge branch 'master' of ssh://121.37.12.51:10022/huoran/FE_CRM 2 years ago
yujialong 014d19782d 收藏学习课程 2 years ago
wangchenguang 667f91dd3f 完成需求 2 years ago
wangchenguang 94b359091d 修复bug 2 years ago
wangchenguang bfe24d5161 Merge branch 'master' of http://121.37.12.51:13000/huoran/FE_CRM 2 years ago
wangchenguang c0eec5316f 修复bug 2 years ago
  1. 8
      .hbuilderx/launch.json
  2. 2
      README.md
  3. 4
      apis/modules/article.js
  4. 4
      apis/modules/order.js
  5. 44
      apis/modules/product.js
  6. 21
      apis/modules/user.js
  7. 33
      apis/request.js
  8. 136
      components/filter-popup/filter-popup.vue
  9. 28
      components/gaoyia-parse/components/wxParseAudio.vue
  10. 94
      components/gaoyia-parse/components/wxParseImg.vue
  11. 55
      components/gaoyia-parse/components/wxParseTable.vue
  12. 98
      components/gaoyia-parse/components/wxParseTemplate0.vue
  13. 88
      components/gaoyia-parse/components/wxParseTemplate1.vue
  14. 88
      components/gaoyia-parse/components/wxParseTemplate10.vue
  15. 86
      components/gaoyia-parse/components/wxParseTemplate11.vue
  16. 88
      components/gaoyia-parse/components/wxParseTemplate2.vue
  17. 88
      components/gaoyia-parse/components/wxParseTemplate3.vue
  18. 88
      components/gaoyia-parse/components/wxParseTemplate4.vue
  19. 88
      components/gaoyia-parse/components/wxParseTemplate5.vue
  20. 88
      components/gaoyia-parse/components/wxParseTemplate6.vue
  21. 88
      components/gaoyia-parse/components/wxParseTemplate7.vue
  22. 88
      components/gaoyia-parse/components/wxParseTemplate8.vue
  23. 88
      components/gaoyia-parse/components/wxParseTemplate9.vue
  24. 15
      components/gaoyia-parse/components/wxParseVideo.vue
  25. 261
      components/gaoyia-parse/libs/html2json.js
  26. 156
      components/gaoyia-parse/libs/htmlparser.js
  27. 209
      components/gaoyia-parse/libs/wxDiscode.js
  28. 258
      components/gaoyia-parse/parse.css
  29. 228
      components/gaoyia-parse/parse.vue
  30. 26
      components/notAuth/notAuth.vue
  31. 140
      components/uni-section/uni-section.vue
  32. 6
      config/request.js
  33. 16
      directives/auth.js
  34. 12
      directives/index.js
  35. 135
      libs/Oss/base64.js
  36. 117
      libs/Oss/crypto.js
  37. 37
      libs/Oss/hmac.js
  38. 82
      libs/Oss/sha1.js
  39. 71
      libs/Oss/upload.js
  40. 39
      libs/mtj-wx-sdk.config.js
  41. 1
      libs/mtj-wx-sdk.js
  42. 36
      libs/share.js
  43. 18
      libs/uma.js
  44. 37
      libs/util.js
  45. 10
      main.js
  46. 14
      manifest.json
  47. 204
      order/addCourse/addCourse.vue
  48. 19
      order/clientDetail/clientDetail.vue
  49. 42
      order/clients/clients.vue
  50. 7
      order/curClient/curClient.vue
  51. 210
      order/editCourse/editCourse.vue
  52. 710
      order/orderDetail/orderDetail.vue
  53. 41
      order/ordered/ordered.vue
  54. 107
      order/privacyAgreement/privacyAgreement.vue
  55. 487
      order/productDetail/productDetail.vue
  56. 399
      order/products/products.vue
  57. 88
      order/serviceAgreement/serviceAgreement.vue
  58. 317
      order/shopCart/shopCart.vue
  59. 5
      package-lock.json
  60. 3
      package.json
  61. 161
      pages.json
  62. 554
      pages/index/index.vue
  63. 134
      pages/login/login.vue
  64. 67
      pages/orders/orders.vue
  65. 155
      pages/person/person.vue
  66. 218
      pages/products/products.vue
  67. 49
      pages/reg/reg.vue
  68. 530
      pages/workbench/workbench.vue
  69. BIN
      static/image/avatar.png
  70. BIN
      static/image/index/1.png
  71. BIN
      static/image/index/2.png
  72. BIN
      static/image/index/3.png
  73. BIN
      static/image/index/4.png
  74. BIN
      static/image/index/5.png
  75. BIN
      static/image/index/6.png
  76. BIN
      static/image/index/7.png
  77. BIN
      static/image/index/8.png
  78. BIN
      static/image/index/9.png
  79. BIN
      static/image/index/banner.png
  80. BIN
      static/image/index/banner1.png
  81. BIN
      static/image/index/index10.png
  82. BIN
      static/image/index/index2.png
  83. BIN
      static/image/index/index3.png
  84. BIN
      static/image/index/index4.png
  85. BIN
      static/image/index/index5.png
  86. BIN
      static/image/index/index6.png
  87. BIN
      static/image/index/index7.png
  88. BIN
      static/image/index/index8.png
  89. BIN
      static/image/index/index9.png
  90. BIN
      static/image/info-bg.jpg
  91. BIN
      static/image/info.png
  92. BIN
      static/image/login1.png
  93. BIN
      static/image/login2.png
  94. BIN
      static/image/logo.png
  95. BIN
      static/image/logo1.png
  96. BIN
      static/image/none.png
  97. BIN
      static/image/person-bg.png
  98. BIN
      static/image/person1.png
  99. BIN
      static/image/person2.png
  100. BIN
      static/image/person26.png
  101. Some files were not shown because too many files have changed in this diff Show More

@ -6,6 +6,14 @@
{
"launchtype" : "local"
},
"h5" :
{
"launchtype" : "local"
},
"mp-toutiao" :
{
"launchtype" : "local"
},
"mp-weixin" :
{
"launchtype" : "local"

@ -1 +1 @@
# 或然科技产业平台合伙人版
# 职站商城

@ -20,3 +20,7 @@ export const schemeList = data => {
export const schemeFindById = id => {
return post('nakadai/nakadai/partner/schemeManagement/findById?id=' + id)
}
export const collectCourse = (id, state) => {
return post('nakadai/nakadai/partner/article/management/collectCourse?contentId=' + id + '&state=' + state)
}

@ -36,3 +36,7 @@ export const del = (data) => {
export const miniProgramOrderRecord = (data) => {
return post('nakadai/nakadai/applets/order/miniProgramOrderRecord', data)
}
export const queryCitySettlementPrice = (mallId, provinceId, cityId) => {
return post(`nakadai/mallPrice/queryCitySettlementPrice?mallId=${mallId}&provinceId=${provinceId}&cityId=${cityId}`)
}

@ -4,3 +4,47 @@ const { get, post } = request
export const AppletsDataProductList = (data) => {
return post('nakadai/nakadai/dataProduct/AppletsDataProductList', data)
}
export const tagsList = () => {
return get('nakadai/tags/tagsList')
}
export const listOfGoods = (data) => {
return post('nakadai/mall/listOfGoods', data)
}
export const detailsOfGoods = (id) => {
return get('nakadai/mall/detailsOfGoods?mallId=' + id)
}
export const productCategoryList = () => {
return get('nakadai/productClassification/productCategoryList')
}
export const productTypeList = () => {
return get('nakadai/productType/productTypeList')
}
export const addToShoppingCart = (data) => {
return post('nakadai/mini/program/shopping/cart/addToShoppingCart', data)
}
export const delCart = (data) => {
return post('nakadai/mini/program/shopping/cart/batchDeletion', data)
}
export const shoppingCartList = (data) => {
return post('nakadai/mini/program/shopping/cart/shoppingCartList', data)
}
export const courseDiscipline = () => {
return get('nakadai/nakadai/subject/courseDiscipline')
}
export const courseProfessionalClass = id => {
return get('nakadai/nakadai/subject/courseProfessionalClass?disciplineId=' + id)
}
export const courseProfessional = id => {
return get('nakadai/nakadai/subject/courseProfessional?professionalClassId=' + id)
}

@ -5,6 +5,18 @@ export const login = (data) => {
return post('users/users/user/weChatAppletCallbackByPartner', data)
}
export const douYinLogin = (data) => {
return post('users/users/user/douYinLogin?code=' + data)
}
export const douYinLoginByOpenid = (data) => {
return post('users/users/user/douYinLoginByOpenid?openid=' + data)
}
export const douYinUserBinding = (data) => {
return post('users/users/user/douYinUserBinding', data)
}
export const queryProvince = () => {
return get('nakadai/nakadai/province/queryProvince')
}
@ -20,6 +32,9 @@ export const updateAvatars = url => {
export const userBinding = (data) => {
return post('users/users/user/userBinding', data)
}
export const sendPhoneOrEmailCode = (data) => {
return post('users/users/userAccount/sendPhoneOrEmailCode', data)
}
export const examinePassword = (data) => {
return post('users/users/userAccount/examinePassword', data)
@ -61,8 +76,8 @@ export const checkIfThePhoneNumberExists = phone => {
return post(`users/users/applets/mine/checkIfThePhoneNumberExists?phone=${phone}`)
}
export const queryPartnerAccount = phone => {
return post(`nakadai/nakadai/partnerAccount/queryPartnerAccount?phone=${phone}`)
export const queryPartnerAccount = data => {
return post(`nakadai/nakadai/partnerAccount/queryPartnerAccount?phone=${data.phone}&openId=${data.openId}&douYinOpenId=${data.douYinOpenId}`)
}
export const getSessionKey = data => {
@ -74,7 +89,7 @@ export const partnerAccountApplication = data => {
}
export const loginByOpenid = openid => {
return post(`users/users/user/loginByOpenid?openid=` + openid)
return post(`users/users/user/loginByOpenid?openid=${openid}`)
}
export const checkWorkNumOrAccount = account => {

@ -1,16 +1,7 @@
import config from '@/config/request'
let HTTP_COUNT = 0 // loading次数
let logouted = 0
const request = options => {
HTTP_COUNT++
if (config.showLoading) {
// 请求数据时的loading
// uni.showToast({
// title: '加载中',
// duration: 200,
// icon: 'loading'
// })
}
const header = Object.assign({}, config.headers, {
token: uni.getStorageSync('token')
})
@ -24,23 +15,29 @@ const request = options => {
method: options.method || 'GET', // 请求类型,默认为GET
data: options.data || {}, // 请求参数,默认空对象
success: ({ data }) => {
const { status, message } = data
const { status, message, code } = data
// 状态判断,根据后台定义并提示
if (status === 200) {
resolve(data)
} else if (status == 401) {
} else if (status == 401 || code === 401) {
if (!logouted) {
// 登录过期
uni.clearStorageSync()
uni.showToast({
title: message,
title: message || '登录过期,请重新登录',
icon: 'none'
})
setTimeout(() => {
uni.navigateTo({
url: '../login/login'
logouted = 0
uni.reLaunch({
url: '/pages/index/index'
})
}, 1500)
reject(data)
logouted = 1
}
} else if (status == 10028 || status == 10014) { // 用户不存在
resolve(data)
} else if (!status) {
resolve(data)
} else {
@ -58,12 +55,6 @@ const request = options => {
})
reject(err)
},
complete: () => {
if (config.showLoading) {
// HTTP_COUNT--
// HTTP_COUNT || uni.hideLoading()
}
}
})
})
}

@ -11,12 +11,22 @@
:mask-custom-style="{ background: 'rgba(0, 0, 0, 0.7)' }"
>
<view class="top-title flex-row-sb" v-if="showTop">
<view></view> <view class="popup-title flex-row-c-c">{{ title }}</view
><text class="saasIcon flex-row-c-c" @click="close">&#xe60c;</text>
<view class="popup-title flex-row-c-c">{{ title }}</view>
<text class="saasIcon flex-row-c-c" @click="close">&#xe60c;</text>
</view>
<scroll-view class="select-scroll" scroll-y :style="{ height: `calc( ${height} - 120rpx - 152rpx )` }">
<view class="select-main">
<view v-if="showCategory" class="select-item">
<view class="title">学科专业</view>
<view class="category-wrap">
<picker mode="multiSelector" v-model="category" @change="change" @columnchange="columnchange" :range="categories" range-key="title">
<view class="category">{{categoryName ? categoryName : '请选择'}}</view>
</picker>
<uni-icons v-if="categoryName" class="icon" type="closeempty" size="16" color="#333" @click.stop="delCatagory"></uni-icons>
</view>
</view>
<view class="select-item" v-for="(item, index) in data" :key="index">
<view class="title"> {{ item.title }} </view>
<view class="tag-list" v-if="!item.children">
@ -59,6 +69,7 @@
</template>
<script>
import { courseDiscipline, courseProfessionalClass, courseProfessional } from '@/apis/modules/product.js'
import Popup from './components/popup.vue';
export default {
components:{
@ -103,6 +114,11 @@ export default {
type: Boolean,
default: true,
},
//
showCategory: {
type: Boolean,
default: false,
},
},
computed: {
//
@ -135,9 +151,19 @@ export default {
},
data() {
return {
originForm: {}
originForm: {},
categoryName:'',
categoryId: '',
professionalCategoryId: '',
professionalId: '',
categories:[],
category: []
}
},
mounted() {
this.getDis()
},
methods: {
//value id
selectTagBuyValueOrId(item, key, keyValue, isRadio) {
@ -172,8 +198,93 @@ export default {
this.acceptForm = this.acceptForm;
},
//
async getDis() {
const { list } = await courseDiscipline()
list.map(e => {
e.id = e.disciplineId
e.title = e.disciplineName
})
this.categories.push(list)
const res = await courseProfessionalClass(1)
res.list.map(e => {
e.id = e.professionalClassId
e.title = e.professionalClassName
})
this.categories.push(res.list)
const res1 = await courseProfessional(1)
res1.list.map(e => {
e.id = e.professionalId
e.title = e.professionalName
})
this.categories.push(res1.list)
},
//
change(e) {
const i0 = e.detail.value[0]
const i1 = e.detail.value[1]
const i2 = e.detail.value[2]
const i1IsNumber = typeof i1 === 'number'
const i2IsNumber = typeof i2 === 'number'
const list = this.categories
this.categoryId = list[0][i0].id
this.categoryName = list[0][i0].title
this.professionalCategoryId = ''
this.professionalId = ''
if (i1IsNumber && list[1].length > 0) {
this.professionalCategoryId = list[1][i1].id
this.categoryName += '/' + list[1][i1].title
}
if (i2IsNumber && list[2].length > 0) {
this.professionalId = list[2][i2].id
this.categoryName += '/' + list[2][i2].title
}
},
//
async columnchange(e) {
const { column } = e.detail
if (column == 0) {
const { list } = await courseProfessionalClass(this.categories[0][e.detail.value].id)
list.map(e => {
e.id = e.professionalClassId
e.title = e.professionalClassName
})
this.categories[1] = list
this.categories[2] = []
this.$set(this.categories, 1, list)
console.log('inner',this.categories)
} else
if (column == 1) {
const { list } = await courseProfessional(this.categories[1][e.detail.value].id)
list.map(e => {
e.id = e.professionalId
e.title = e.professionalName
})
this.categories[2] = list
this.$set(this.categories, 2, list)
}
},
//
delCatagory() {
this.category = []
this.categoryName = ''
this.categoryId = ''
this.professionalCategoryId = ''
this.professionalId = ''
},
//
finsh() {
if (this.showCategory) {
this.acceptForm.categoryId = this.categoryId
this.acceptForm.professionalCategoryId = this.professionalCategoryId
this.acceptForm.professionalId = this.professionalId
this.acceptForm.categoryName = this.categoryName
}
this.$emit("finsh", this.acceptForm);
this.$emit("input", false);
},
@ -184,6 +295,14 @@ export default {
//
reset() {
this.acceptForm = {}
this.categoryId = ''
this.professionalCategoryId = ''
this.professionalId = ''
this.categoryName = ''
this.$nextTick(() => {
this.$emit("finsh", this.acceptForm);
this.$emit("input", false);
})
},
},
};
@ -221,6 +340,17 @@ export default {
}
.select-scroll {
}
.category-wrap {
display: flex;
align-items: center;
margin-top: 10rpx;
.icon {
margin-left: 10rpx;
}
}
.category {
font-size: 28rpx;
}
.select-main {
padding: 0 32rpx;
.select-item {

@ -1,28 +0,0 @@
<template>
<!-- '<audio/>' 组件不再维护建议使用能力更强的 'uni.createInnerAudioContext' 接口 有时间再改-->
<!--增加audio标签支持-->
<audio
:id="node.attr.id"
:class="node.classStr"
:style="node.styleStr"
:src="node.attr.src"
:loop="node.attr.loop"
:poster="node.attr.poster"
:name="node.attr.name"
:author="node.attr.author"
controls></audio>
</template>
<script>
export default {
name: 'wxParseAudio',
props: {
node: {
type: Object,
default() {
return {};
},
},
},
};
</script>

@ -1,94 +0,0 @@
<template>
<image
:mode="node.attr.mode"
:lazy-load="node.attr.lazyLoad"
:class="node.classStr"
:style="newStyleStr || node.styleStr"
:data-src="node.attr.src"
:src="node.attr.src"
@tap="wxParseImgTap"
@load="wxParseImgLoad"
/>
</template>
<script>
export default {
name: 'wxParseImg',
data() {
return {
newStyleStr: '',
preview: true
};
},
inject: ['parseWidth'],
mounted() {},
props: {
node: {
type: Object,
default() {
return {};
}
}
},
methods: {
wxParseImgTap(e) {
if (!this.preview) return;
const { src } = e.currentTarget.dataset;
if (!src) return;
let parent = this.$parent;
while (!parent.preview || typeof parent.preview !== 'function') {
// TODO
parent = parent.$parent;
}
parent.preview(src, e);
},
//
wxParseImgLoad(e) {
const { src } = e.currentTarget.dataset;
if (!src) return;
let { width, height } = e.mp.detail;
const recal = this.wxAutoImageCal(width, height);
const { imageheight, imageWidth } = recal;
const { padding, mode } = this.node.attr;//padding
// const { mode } = this.node.attr;
const { styleStr } = this.node;
const imageHeightStyle = mode === 'widthFix' ? '' : `height: ${imageheight}px;`;
this.newStyleStr = `${styleStr}; ${imageHeightStyle}; width: ${imageWidth}px; padding: 0 ${+padding}px;`;//padding
// this.newStyleStr = `${styleStr}; ${imageHeightStyle}; width: ${imageWidth}px;`;
},
//
wxAutoImageCal(originalWidth, originalHeight) {
//
const windowWidth = this.parseWidth.value;
const results = {};
if (originalWidth < 60 || originalHeight < 60) {
const { src } = this.node.attr;
let parent = this.$parent;
while (!parent.preview || typeof parent.preview !== 'function') {
parent = parent.$parent;
}
parent.removeImageUrl(src);
this.preview = false;
}
//
if (originalWidth > windowWidth) {
// widthwidth
results.imageWidth = windowWidth;
results.imageheight = windowWidth * (originalHeight / originalWidth);
} else {
//
results.imageWidth = originalWidth;
results.imageheight = originalHeight;
}
return results;
}
}
};
</script>

@ -1,55 +0,0 @@
<template>
<div class='tablebox'>
<rich-text :nodes="nodes" :class="node.classStr" :style="'user-select:' + parseSelect"></rich-text>
</div>
</template>
<script>
export default {
name: 'wxParseTable',
props: {
node: {
type: Object,
default() {
return {};
},
},
},
inject: ['parseSelect'],
data() {
return {
nodes:[]
};
},
mounted() {
this.nodes=this.loadNode([this.node]);
},
methods: {
loadNode(node) {
let obj = [];
for (let children of node) {
if (children.node=='element') {
let t = {
name:children.tag,
attrs: {
class: children.classStr,
// style: children.styleStr,
},
children: children.nodes?this.loadNode(children.nodes):[]
}
obj.push(t)
} else if(children.node=='text'){
obj.push({
type: 'text',
text: children.text
})
}
}
return obj
}
}
};
</script>
<style>
@import url("../parse.css");
</style>

@ -1,98 +0,0 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<!--button类型-->
<button v-if="node.tag == 'button'" type="default" size="mini" :class="node.classStr" :style="node.styleStr">
<wx-parse-template :node="node" />
</button>
<!--a类型-->
<view v-else-if="node.tag == 'a'" @click="wxParseATap(node.attr,$event)" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--li类型-->
<view v-else-if="node.tag == 'li'" :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--table类型-->
<wx-parse-table v-else-if="node.tag == 'table'" :class="node.classStr" :style="node.styleStr" :node="node" />
<!--br类型-->
<!-- #ifndef H5 -->
<text v-else-if="node.tag == 'br'">\n</text>
<!-- #endif -->
<!-- #ifdef H5 -->
<br v-else-if="node.tag == 'br'">
<!-- #endif -->
<!--video类型-->
<wx-parse-video :node="node" v-else-if="node.tag == 'video'"/>
<!--audio类型-->
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'"/>
<!--img类型-->
<wx-parse-img :node="node" v-else-if="node.tag == 'img'" :style="node.styleStr"/>
<!--其他标签-->
<view v-else :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node"/>
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text'">{{node.text}}</block>
</template>
<script>
// #ifdef APP-PLUS | H5
import wxParseTemplate from './wxParseTemplate0';
// #endif
// #ifdef MP
import wxParseTemplate from './wxParseTemplate1';
// #endif
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
import wxParseAudio from './wxParseAudio';
import wxParseTable from './wxParseTable';
export default {
// #ifdef APP-PLUS | H5
name: 'wxParseTemplate',
// #endif
// #ifdef MP
name: 'wxParseTemplate0',
// #endif
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
wxParseAudio,
wxParseTable
},
methods: {
wxParseATap(attr,e) {
const {
href
} = e.currentTarget.dataset;// TODO currentTargetdataset
if (!href) return;
let parent = this.$parent;
while(!parent.preview || typeof parent.preview !== 'function') {// TODO
parent = parent.$parent;
}
parent.navigate(href, e, attr);
}
}
};
</script>

@ -1,88 +0,0 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<!--button类型-->
<button v-if="node.tag == 'button'" type="default" size="mini" :class="node.classStr" :style="node.styleStr">
<wx-parse-template :node="node" />
</button>
<!--a类型-->
<view v-else-if="node.tag == 'a'" @click="wxParseATap(node.attr,$event)" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--li类型-->
<view v-else-if="node.tag == 'li'" :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--table类型-->
<wx-parse-table v-else-if="node.tag == 'table'" :class="node.classStr" :style="node.styleStr" :node="node" />
<!--br类型-->
<!-- #ifndef H5 -->
<text v-else-if="node.tag == 'br'">\n</text>
<!-- #endif -->
<!-- #ifdef H5 -->
<br v-else-if="node.tag == 'br'">
<!-- #endif -->
<!--video类型-->
<wx-parse-video :node="node" v-else-if="node.tag == 'video'"/>
<!--audio类型-->
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'"/>
<!--img类型-->
<wx-parse-img :node="node" v-else-if="node.tag == 'img'" :style="node.styleStr"/>
<!--其他标签-->
<view v-else :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text'">{{node.text}}</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate2';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
import wxParseAudio from './wxParseAudio';
import wxParseTable from './wxParseTable';
export default {
name: 'wxParseTemplate1',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
wxParseAudio,
wxParseTable
},
methods: {
wxParseATap(attr,e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
let parent = this.$parent;
while(!parent.preview || typeof parent.preview !== 'function') {
parent = parent.$parent;
}
parent.navigate(href, e, attr);
}
}
};
</script>

@ -1,88 +0,0 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<!--button类型-->
<button v-if="node.tag == 'button'" type="default" size="mini" :class="node.classStr" :style="node.styleStr">
<wx-parse-template :node="node" />
</button>
<!--a类型-->
<view v-else-if="node.tag == 'a'" @click="wxParseATap(node.attr,$event)" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--li类型-->
<view v-else-if="node.tag == 'li'" :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--table类型-->
<wx-parse-table v-else-if="node.tag == 'table'" :class="node.classStr" :style="node.styleStr" :node="node" />
<!--br类型-->
<!-- #ifndef H5 -->
<text v-else-if="node.tag == 'br'">\n</text>
<!-- #endif -->
<!-- #ifdef H5 -->
<br v-else-if="node.tag == 'br'">
<!-- #endif -->
<!--video类型-->
<wx-parse-video :node="node" v-else-if="node.tag == 'video'"/>
<!--audio类型-->
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'"/>
<!--img类型-->
<wx-parse-img :node="node" v-else-if="node.tag == 'img'" :style="node.styleStr"/>
<!--其他标签-->
<view v-else :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text' ">{{node.text}}</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate11';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
import wxParseAudio from './wxParseAudio';
import wxParseTable from './wxParseTable';
export default {
name: 'wxParseTemplate10',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
wxParseAudio,
wxParseTable
},
methods: {
wxParseATap(attr,e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
let parent = this.$parent;
while(!parent.preview || typeof parent.preview !== 'function') {
parent = parent.$parent;
}
parent.navigate(href, e, attr);
}
}
};
</script>

@ -1,86 +0,0 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<!--button类型-->
<button v-if="node.tag == 'button'" type="default" size="mini" :class="node.classStr" :style="node.styleStr">
<rich-text :nodes="node" :class="node.classStr" :style="'user-select:' + parseSelect"></rich-text>
</button>
<!--a类型-->
<view v-else-if="node.tag == 'a'" @click="wxParseATap(node.attr,$event)" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<rich-text :nodes="node" :class="node.classStr" :style="'user-select:' + parseSelect"></rich-text>
</block>
</view>
<!--li类型-->
<view v-else-if="node.tag == 'li'" :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<rich-text :nodes="node" :class="node.classStr" :style="'user-select:' + parseSelect"></rich-text>
</block>
</view>
<!--table类型-->
<wx-parse-table v-else-if="node.tag == 'table'" :class="node.classStr" :style="node.styleStr" :node="node" />
<!--br类型-->
<!-- #ifndef H5 -->
<text v-else-if="node.tag == 'br'">\n</text>
<!-- #endif -->
<!-- #ifdef H5 -->
<br v-else-if="node.tag == 'br'">
<!-- #endif -->
<!--video类型-->
<wx-parse-video :node="node" v-else-if="node.tag == 'video'"/>
<!--audio类型-->
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'"/>
<!--img类型-->
<wx-parse-img :node="node" v-else-if="node.tag == 'img'"/>
<!--其他标签-->
<view v-else :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<rich-text :nodes="node" :class="node.classStr" :style="'user-select:' + parseSelect"></rich-text>
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text' ">{{node.text}}</block>
</template>
<script>
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
import wxParseAudio from './wxParseAudio';
import wxParseTable from './wxParseTable';
export default {
name: 'wxParseTemplate11',
props: {
node: {},
},
components: {
wxParseImg,
wxParseVideo,
wxParseAudio,
wxParseTable
},
methods: {
wxParseATap(attr,e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
let parent = this.$parent;
while(!parent.preview || typeof parent.preview !== 'function') {
parent = parent.$parent;
}
parent.navigate(href, e, attr);
}
}
};
</script>

@ -1,88 +0,0 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<!--button类型-->
<button v-if="node.tag == 'button'" type="default" size="mini" :class="node.classStr" :style="node.styleStr">
<wx-parse-template :node="node" />
</button>
<!--a类型-->
<view v-else-if="node.tag == 'a'" @click="wxParseATap(node.attr,$event)" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--li类型-->
<view v-else-if="node.tag == 'li'" :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--table类型-->
<wx-parse-table v-else-if="node.tag == 'table'" :class="node.classStr" :style="node.styleStr" :node="node" />
<!--br类型-->
<!-- #ifndef H5 -->
<text v-else-if="node.tag == 'br'">\n</text>
<!-- #endif -->
<!-- #ifdef H5 -->
<br v-else-if="node.tag == 'br'">
<!-- #endif -->
<!--video类型-->
<wx-parse-video :node="node" v-else-if="node.tag == 'video'"/>
<!--audio类型-->
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'"/>
<!--img类型-->
<wx-parse-img :node="node" v-else-if="node.tag == 'img'" :style="node.styleStr"/>
<!--其他标签-->
<view v-else :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text'">{{node.text}}</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate3';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
import wxParseAudio from './wxParseAudio';
import wxParseTable from './wxParseTable';
export default {
name: 'wxParseTemplate2',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
wxParseAudio,
wxParseTable
},
methods: {
wxParseATap(attr,e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
let parent = this.$parent;
while(!parent.preview || typeof parent.preview !== 'function') {
parent = parent.$parent;
}
parent.navigate(href, e, attr);
}
}
};
</script>

@ -1,88 +0,0 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<!--button类型-->
<button v-if="node.tag == 'button'" type="default" size="mini" :class="node.classStr" :style="node.styleStr">
<wx-parse-template :node="node" />
</button>
<!--a类型-->
<view v-else-if="node.tag == 'a'" @click="wxParseATap(node.attr,$event)" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--li类型-->
<view v-else-if="node.tag == 'li'" :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--table类型-->
<wx-parse-table v-else-if="node.tag == 'table'" :class="node.classStr" :style="node.styleStr" :node="node" />
<!--br类型-->
<!-- #ifndef H5 -->
<text v-else-if="node.tag == 'br'">\n</text>
<!-- #endif -->
<!-- #ifdef H5 -->
<br v-else-if="node.tag == 'br'">
<!-- #endif -->
<!--video类型-->
<wx-parse-video :node="node" v-else-if="node.tag == 'video'"/>
<!--audio类型-->
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'"/>
<!--img类型-->
<wx-parse-img :node="node" v-else-if="node.tag == 'img'" :style="node.styleStr"/>
<!--其他标签-->
<view v-else :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text' ">{{node.text}}</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate4';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
import wxParseAudio from './wxParseAudio';
import wxParseTable from './wxParseTable';
export default {
name: 'wxParseTemplate3',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
wxParseAudio,
wxParseTable
},
methods: {
wxParseATap(attr,e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
let parent = this.$parent;
while(!parent.preview || typeof parent.preview !== 'function') {
parent = parent.$parent;
}
parent.navigate(href, e, attr);
}
}
};
</script>

@ -1,88 +0,0 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<!--button类型-->
<button v-if="node.tag == 'button'" type="default" size="mini" :class="node.classStr" :style="node.styleStr">
<wx-parse-template :node="node" />
</button>
<!--a类型-->
<view v-else-if="node.tag == 'a'" @click="wxParseATap(node.attr,$event)" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--li类型-->
<view v-else-if="node.tag == 'li'" :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--table类型-->
<wx-parse-table v-else-if="node.tag == 'table'" :class="node.classStr" :style="node.styleStr" :node="node" />
<!--br类型-->
<!-- #ifndef H5 -->
<text v-else-if="node.tag == 'br'">\n</text>
<!-- #endif -->
<!-- #ifdef H5 -->
<br v-else-if="node.tag == 'br'">
<!-- #endif -->
<!--video类型-->
<wx-parse-video :node="node" v-else-if="node.tag == 'video'"/>
<!--audio类型-->
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'"/>
<!--img类型-->
<wx-parse-img :node="node" v-else-if="node.tag == 'img'" :style="node.styleStr"/>
<!--其他标签-->
<view v-else :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text' ">{{node.text}}</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate5';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
import wxParseAudio from './wxParseAudio';
import wxParseTable from './wxParseTable';
export default {
name: 'wxParseTemplate4',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
wxParseAudio,
wxParseTable
},
methods: {
wxParseATap(attr,e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
let parent = this.$parent;
while(!parent.preview || typeof parent.preview !== 'function') {
parent = parent.$parent;
}
parent.navigate(href, e, attr);
}
}
};
</script>

@ -1,88 +0,0 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<!--button类型-->
<button v-if="node.tag == 'button'" type="default" size="mini" :class="node.classStr" :style="node.styleStr">
<wx-parse-template :node="node" />
</button>
<!--a类型-->
<view v-else-if="node.tag == 'a'" @click="wxParseATap(node.attr,$event)" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--li类型-->
<view v-else-if="node.tag == 'li'" :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--table类型-->
<wx-parse-table v-else-if="node.tag == 'table'" :class="node.classStr" :style="node.styleStr" :node="node" />
<!--br类型-->
<!-- #ifndef H5 -->
<text v-else-if="node.tag == 'br'">\n</text>
<!-- #endif -->
<!-- #ifdef H5 -->
<br v-else-if="node.tag == 'br'">
<!-- #endif -->
<!--video类型-->
<wx-parse-video :node="node" v-else-if="node.tag == 'video'"/>
<!--audio类型-->
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'"/>
<!--img类型-->
<wx-parse-img :node="node" v-else-if="node.tag == 'img'" :style="node.styleStr"/>
<!--其他标签-->
<view v-else :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text' ">{{node.text}}</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate6';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
import wxParseAudio from './wxParseAudio';
import wxParseTable from './wxParseTable';
export default {
name: 'wxParseTemplate5',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
wxParseAudio,
wxParseTable
},
methods: {
wxParseATap(attr,e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
let parent = this.$parent;
while(!parent.preview || typeof parent.preview !== 'function') {
parent = parent.$parent;
}
parent.navigate(href, e, attr);
}
}
};
</script>

@ -1,88 +0,0 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<!--button类型-->
<button v-if="node.tag == 'button'" type="default" size="mini" :class="node.classStr" :style="node.styleStr">
<wx-parse-template :node="node" />
</button>
<!--a类型-->
<view v-else-if="node.tag == 'a'" @click="wxParseATap(node.attr,$event)" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--li类型-->
<view v-else-if="node.tag == 'li'" :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--table类型-->
<wx-parse-table v-else-if="node.tag == 'table'" :class="node.classStr" :style="node.styleStr" :node="node" />
<!--br类型-->
<!-- #ifndef H5 -->
<text v-else-if="node.tag == 'br'">\n</text>
<!-- #endif -->
<!-- #ifdef H5 -->
<br v-else-if="node.tag == 'br'">
<!-- #endif -->
<!--video类型-->
<wx-parse-video :node="node" v-else-if="node.tag == 'video'"/>
<!--audio类型-->
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'"/>
<!--img类型-->
<wx-parse-img :node="node" v-else-if="node.tag == 'img'" :style="node.styleStr"/>
<!--其他标签-->
<view v-else :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text' ">{{node.text}}</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate7';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
import wxParseAudio from './wxParseAudio';
import wxParseTable from './wxParseTable';
export default {
name: 'wxParseTemplate6',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
wxParseAudio,
wxParseTable
},
methods: {
wxParseATap(attr,e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
let parent = this.$parent;
while(!parent.preview || typeof parent.preview !== 'function') {
parent = parent.$parent;
}
parent.navigate(href, e, attr);
}
}
};
</script>

@ -1,88 +0,0 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<!--button类型-->
<button v-if="node.tag == 'button'" type="default" size="mini" :class="node.classStr" :style="node.styleStr">
<wx-parse-template :node="node" />
</button>
<!--a类型-->
<view v-else-if="node.tag == 'a'" @click="wxParseATap(node.attr,$event)" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--li类型-->
<view v-else-if="node.tag == 'li'" :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--table类型-->
<wx-parse-table v-else-if="node.tag == 'table'" :class="node.classStr" :style="node.styleStr" :node="node" />
<!--br类型-->
<!-- #ifndef H5 -->
<text v-else-if="node.tag == 'br'">\n</text>
<!-- #endif -->
<!-- #ifdef H5 -->
<br v-else-if="node.tag == 'br'">
<!-- #endif -->
<!--video类型-->
<wx-parse-video :node="node" v-else-if="node.tag == 'video'"/>
<!--audio类型-->
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'"/>
<!--img类型-->
<wx-parse-img :node="node" v-else-if="node.tag == 'img'" :style="node.styleStr"/>
<!--其他标签-->
<view v-else :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text' ">{{node.text}}</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate8';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
import wxParseAudio from './wxParseAudio';
import wxParseTable from './wxParseTable';
export default {
name: 'wxParseTemplate7',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
wxParseAudio,
wxParseTable
},
methods: {
wxParseATap(attr,e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
let parent = this.$parent;
while(!parent.preview || typeof parent.preview !== 'function') {
parent = parent.$parent;
}
parent.navigate(href, e, attr);
}
}
};
</script>

@ -1,88 +0,0 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<!--button类型-->
<button v-if="node.tag == 'button'" type="default" size="mini" :class="node.classStr" :style="node.styleStr">
<wx-parse-template :node="node" />
</button>
<!--a类型-->
<view v-else-if="node.tag == 'a'" @click="wxParseATap(node.attr,$event)" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--li类型-->
<view v-else-if="node.tag == 'li'" :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--table类型-->
<wx-parse-table v-else-if="node.tag == 'table'" :class="node.classStr" :style="node.styleStr" :node="node" />
<!--br类型-->
<!-- #ifndef H5 -->
<text v-else-if="node.tag == 'br'">\n</text>
<!-- #endif -->
<!-- #ifdef H5 -->
<br v-else-if="node.tag == 'br'">
<!-- #endif -->
<!--video类型-->
<wx-parse-video :node="node" v-else-if="node.tag == 'video'"/>
<!--audio类型-->
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'"/>
<!--img类型-->
<wx-parse-img :node="node" v-else-if="node.tag == 'img'" :style="node.styleStr"/>
<!--其他标签-->
<view v-else :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text' ">{{node.text}}</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate9';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
import wxParseAudio from './wxParseAudio';
import wxParseTable from './wxParseTable';
export default {
name: 'wxParseTemplate8',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
wxParseAudio,
wxParseTable
},
methods: {
wxParseATap(attr,e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
let parent = this.$parent;
while(!parent.preview || typeof parent.preview !== 'function') {
parent = parent.$parent;
}
parent.navigate(href, e, attr);
}
}
};
</script>

@ -1,88 +0,0 @@
<template>
<!--判断是否是标签节点-->
<block v-if="node.node == 'element'">
<!--button类型-->
<button v-if="node.tag == 'button'" type="default" size="mini" :class="node.classStr" :style="node.styleStr">
<wx-parse-template :node="node" />
</button>
<!--a类型-->
<view v-else-if="node.tag == 'a'" @click="wxParseATap(node.attr,$event)" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--li类型-->
<view v-else-if="node.tag == 'li'" :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
<!--table类型-->
<wx-parse-table v-else-if="node.tag == 'table'" :class="node.classStr" :style="node.styleStr" :node="node" />
<!--br类型-->
<!-- #ifndef H5 -->
<text v-else-if="node.tag == 'br'">\n</text>
<!-- #endif -->
<!-- #ifdef H5 -->
<br v-else-if="node.tag == 'br'">
<!-- #endif -->
<!--video类型-->
<wx-parse-video :node="node" v-else-if="node.tag == 'video'"/>
<!--audio类型-->
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'"/>
<!--img类型-->
<wx-parse-img :node="node" v-else-if="node.tag == 'img'" :style="node.styleStr"/>
<!--其他标签-->
<view v-else :class="node.classStr" :style="node.styleStr">
<block v-for="(node, index) of node.nodes" :key="index">
<wx-parse-template :node="node" />
</block>
</view>
</block>
<!--判断是否是文本节点-->
<block v-else-if="node.node == 'text' ">{{node.text}}</block>
</template>
<script>
import wxParseTemplate from './wxParseTemplate10';
import wxParseImg from './wxParseImg';
import wxParseVideo from './wxParseVideo';
import wxParseAudio from './wxParseAudio';
import wxParseTable from './wxParseTable';
export default {
name: 'wxParseTemplate9',
props: {
node: {},
},
components: {
wxParseTemplate,
wxParseImg,
wxParseVideo,
wxParseAudio,
wxParseTable
},
methods: {
wxParseATap(attr,e) {
const {
href
} = e.currentTarget.dataset;
if (!href) return;
let parent = this.$parent;
while(!parent.preview || typeof parent.preview !== 'function') {
parent = parent.$parent;
}
parent.navigate(href, e, attr);
}
}
};
</script>

@ -1,15 +0,0 @@
<template>
<!--增加video标签支持并循环添加-->
<view :class="node.classStr" :style="node.styleStr">
<video :class="node.classStr" :style="node.styleStr" class="video-video" :src="node.attr.src"></video>
</view>
</template>
<script>
export default {
name: 'wxParseVideo',
props: {
node: {},
},
};
</script>

@ -1,261 +0,0 @@
/**
* html2Json 改造来自: https://github.com/Jxck/html2json
*
*
* author: Di (微信小程序开发工程师)
* organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
* 垂直微信小程序开发交流社区
*
* github地址: https://github.com/icindy/wxParse
*
* for: 微信小程序富文本解析
* detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
*/
import wxDiscode from './wxDiscode';
import HTMLParser from './htmlparser';
function makeMap(str) {
const obj = {};
const items = str.split(',');
for (let i = 0; i < items.length; i += 1) obj[items[i]] = true;
return obj;
}
// Block Elements - HTML 5
const block = makeMap('br,code,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video');
// Inline Elements - HTML 5
const inline = makeMap('a,abbr,acronym,applet,b,basefont,bdo,big,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var');
// Elements that you can, intentionally, leave open
// (and which close themselves)
const closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr');
function removeDOCTYPE(html) {
const isDocument = /<body.*>([^]*)<\/body>/.test(html);
return isDocument ? RegExp.$1 : html;
}
function trimHtml(html) {
return html
.replace(/<!--.*?-->/gi, '')
.replace(/\/\*.*?\*\//gi, '')
.replace(/[ ]+</gi, '<')
.replace(/<script[^]*<\/script>/gi, '')
.replace(/<style[^]*<\/style>/gi, '');
}
function getScreenInfo() {
const screen = {};
wx.getSystemInfo({
success: (res) => {
screen.width = res.windowWidth;
screen.height = res.windowHeight;
},
});
return screen;
}
function html2json(html, customHandler, imageProp, host) {
// 处理字符串
html = removeDOCTYPE(html);
html = trimHtml(html);
html = wxDiscode.strDiscode(html);
// 生成node节点
const bufArray = [];
const results = {
nodes: [],
imageUrls: [],
};
const screen = getScreenInfo();
function Node(tag) {
this.node = 'element';
this.tag = tag;
this.$screen = screen;
}
HTMLParser(html, {
start(tag, attrs, unary) {
// node for this element
const node = new Node(tag);
if (bufArray.length !== 0) {
const parent = bufArray[0];
if (parent.nodes === undefined) {
parent.nodes = [];
}
}
if (block[tag]) {
node.tagType = 'block';
} else if (inline[tag]) {
node.tagType = 'inline';
} else if (closeSelf[tag]) {
node.tagType = 'closeSelf';
}
node.attr = attrs.reduce((pre, attr) => {
const { name } = attr;
let { value } = attr;
if (name === 'class') {
node.classStr = value;
}
// has multi attibutes
// make it array of attribute
if (name === 'style') {
node.styleStr = value;
}
if (value.match(/ /)) {
value = value.split(' ');
}
// if attr already exists
// merge it
if (pre[name]) {
if (Array.isArray(pre[name])) {
// already array, push to last
pre[name].push(value);
} else {
// single value, make it array
pre[name] = [pre[name], value];
}
} else {
// not exist, put it
pre[name] = value;
}
return pre;
}, {});
// 优化样式相关属性
if (node.classStr) {
node.classStr += ` ${node.tag}`;
} else {
node.classStr = node.tag;
}
if (node.tagType === 'inline') {
node.classStr += ' inline';
}
// 对img添加额外数据
if (node.tag === 'img') {
let imgUrl = node.attr.src;
imgUrl = wxDiscode.urlToHttpUrl(imgUrl, imageProp.domain);
Object.assign(node.attr, imageProp, {
src: imgUrl || '',
});
if (imgUrl) {
results.imageUrls.push(imgUrl);
}
}
// 处理a标签属性
if (node.tag === 'a') {
node.attr.href = node.attr.href || '';
}
// 处理font标签样式属性
if (node.tag === 'font') {
const fontSize = [
'x-small',
'small',
'medium',
'large',
'x-large',
'xx-large',
'-webkit-xxx-large',
];
const styleAttrs = {
color: 'color',
face: 'font-family',
size: 'font-size',
};
if (!node.styleStr) node.styleStr = '';
Object.keys(styleAttrs).forEach((key) => {
if (node.attr[key]) {
const value = key === 'size' ? fontSize[node.attr[key] - 1] : node.attr[key];
node.styleStr += `${styleAttrs[key]}: ${value};`;
}
});
}
// 临时记录source资源
if (node.tag === 'source') {
results.source = node.attr.src;
}
if (customHandler.start) {
customHandler.start(node, results);
}
if (unary) {
// if this tag doesn't have end tag
// like <img src="hoge.png"/>
// add to parents
const parent = bufArray[0] || results;
if (parent.nodes === undefined) {
parent.nodes = [];
}
parent.nodes.push(node);
} else {
bufArray.unshift(node);
}
},
end(tag) {
// merge into parent tag
const node = bufArray.shift();
if (node.tag !== tag) {
console.error('invalid state: mismatch end tag');
}
// 当有缓存source资源时于于video补上src资源
if (node.tag === 'video' && results.source) {
node.attr.src = results.source;
delete results.source;
}
if (customHandler.end) {
customHandler.end(node, results);
}
if (bufArray.length === 0) {
results.nodes.push(node);
} else {
const parent = bufArray[0];
if (!parent.nodes) {
parent.nodes = [];
}
parent.nodes.push(node);
}
},
chars(text) {
if (!text.trim()) return;
const node = {
node: 'text',
text,
};
if (customHandler.chars) {
customHandler.chars(node, results);
}
if (bufArray.length === 0) {
results.nodes.push(node);
} else {
const parent = bufArray[0];
if (parent.nodes === undefined) {
parent.nodes = [];
}
parent.nodes.push(node);
}
},
});
return results;
}
export default html2json;

@ -1,156 +0,0 @@
/**
*
* htmlParser改造自: https://github.com/blowsie/Pure-JavaScript-HTML5-Parser
*
* author: Di (微信小程序开发工程师)
* organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
* 垂直微信小程序开发交流社区
*
* github地址: https://github.com/icindy/wxParse
*
* for: 微信小程序富文本解析
* detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
*/
// Regular Expressions for parsing tags and attributes
const startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z0-9_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
const endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/;
const attr = /([a-zA-Z0-9_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;
function makeMap(str) {
const obj = {};
const items = str.split(',');
for (let i = 0; i < items.length; i += 1) obj[items[i]] = true;
return obj;
}
// Empty Elements - HTML 5
const empty = makeMap('area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr');
// Block Elements - HTML 5
const block = makeMap('address,code,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video');
// Inline Elements - HTML 5
const inline = makeMap('a,abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var');
// Elements that you can, intentionally, leave open
// (and which close themselves)
const closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr');
// Attributes that have their values filled in disabled="disabled"
const fillAttrs = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected');
function HTMLParser(html, handler) {
let index;
let chars;
let match;
let last = html;
const stack = [];
stack.last = () => stack[stack.length - 1];
function parseEndTag(tag, tagName) {
// If no tag name is provided, clean shop
let pos;
if (!tagName) {
pos = 0;
} else {
// Find the closest opened tag of the same type
tagName = tagName.toLowerCase();
for (pos = stack.length - 1; pos >= 0; pos -= 1) {
if (stack[pos] === tagName) break;
}
}
if (pos >= 0) {
// Close all the open elements, up the stack
for (let i = stack.length - 1; i >= pos; i -= 1) {
if (handler.end) handler.end(stack[i]);
}
// Remove the open elements from the stack
stack.length = pos;
}
}
function parseStartTag(tag, tagName, rest, unary) {
tagName = tagName.toLowerCase();
if (block[tagName]) {
while (stack.last() && inline[stack.last()]) {
parseEndTag('', stack.last());
}
}
if (closeSelf[tagName] && stack.last() === tagName) {
parseEndTag('', tagName);
}
unary = empty[tagName] || !!unary;
if (!unary) stack.push(tagName);
if (handler.start) {
const attrs = [];
rest.replace(attr, function genAttr(matches, name) {
const value = arguments[2] || arguments[3] || arguments[4] || (fillAttrs[name] ? name : '');
attrs.push({
name,
value,
escaped: value.replace(/(^|[^\\])"/g, '$1\\"'), // "
});
});
if (handler.start) {
handler.start(tagName, attrs, unary);
}
}
}
while (html) {
chars = true;
if (html.indexOf('</') === 0) {
match = html.match(endTag);
if (match) {
html = html.substring(match[0].length);
match[0].replace(endTag, parseEndTag);
chars = false;
}
// start tag
} else if (html.indexOf('<') === 0) {
match = html.match(startTag);
if (match) {
html = html.substring(match[0].length);
match[0].replace(startTag, parseStartTag);
chars = false;
}
}
if (chars) {
index = html.indexOf('<');
let text = '';
while (index === 0) {
text += '<';
html = html.substring(1);
index = html.indexOf('<');
}
text += index < 0 ? html : html.substring(0, index);
html = index < 0 ? '' : html.substring(index);
if (handler.chars) handler.chars(text);
}
if (html === last) throw new Error(`Parse Error: ${html}`);
last = html;
}
// Clean up any remaining tags
parseEndTag();
}
export default HTMLParser;

@ -1,209 +0,0 @@
// HTML 支持的数学符号
function strNumDiscode(str) {
str = str.replace(/&forall;|&#8704;|&#x2200;/g, '∀');
str = str.replace(/&part;|&#8706;|&#x2202;/g, '∂');
str = str.replace(/&exist;|&#8707;|&#x2203;/g, '∃');
str = str.replace(/&empty;|&#8709;|&#x2205;/g, '∅');
str = str.replace(/&nabla;|&#8711;|&#x2207;/g, '∇');
str = str.replace(/&isin;|&#8712;|&#x2208;/g, '∈');
str = str.replace(/&notin;|&#8713;|&#x2209;/g, '∉');
str = str.replace(/&ni;|&#8715;|&#x220b;/g, '∋');
str = str.replace(/&prod;|&#8719;|&#x220f;/g, '∏');
str = str.replace(/&sum;|&#8721;|&#x2211;/g, '∑');
str = str.replace(/&minus;|&#8722;|&#x2212;/g, '−');
str = str.replace(/&lowast;|&#8727;|&#x2217;/g, '∗');
str = str.replace(/&radic;|&#8730;|&#x221a;/g, '√');
str = str.replace(/&prop;|&#8733;|&#x221d;/g, '∝');
str = str.replace(/&infin;|&#8734;|&#x221e;/g, '∞');
str = str.replace(/&ang;|&#8736;|&#x2220;/g, '∠');
str = str.replace(/&and;|&#8743;|&#x2227;/g, '∧');
str = str.replace(/&or;|&#8744;|&#x2228;/g, '∨');
str = str.replace(/&cap;|&#8745;|&#x2229;/g, '∩');
str = str.replace(/&cup;|&#8746;|&#x222a;/g, '∪');
str = str.replace(/&int;|&#8747;|&#x222b;/g, '∫');
str = str.replace(/&there4;|&#8756;|&#x2234;/g, '∴');
str = str.replace(/&sim;|&#8764;|&#x223c;/g, '∼');
str = str.replace(/&cong;|&#8773;|&#x2245;/g, '≅');
str = str.replace(/&asymp;|&#8776;|&#x2248;/g, '≈');
str = str.replace(/&ne;|&#8800;|&#x2260;/g, '≠');
str = str.replace(/&le;|&#8804;|&#x2264;/g, '≤');
str = str.replace(/&ge;|&#8805;|&#x2265;/g, '≥');
str = str.replace(/&sub;|&#8834;|&#x2282;/g, '⊂');
str = str.replace(/&sup;|&#8835;|&#x2283;/g, '⊃');
str = str.replace(/&nsub;|&#8836;|&#x2284;/g, '⊄');
str = str.replace(/&sube;|&#8838;|&#x2286;/g, '⊆');
str = str.replace(/&supe;|&#8839;|&#x2287;/g, '⊇');
str = str.replace(/&oplus;|&#8853;|&#x2295;/g, '⊕');
str = str.replace(/&otimes;|&#8855;|&#x2297;/g, '⊗');
str = str.replace(/&perp;|&#8869;|&#x22a5;/g, '⊥');
str = str.replace(/&sdot;|&#8901;|&#x22c5;/g, '⋅');
return str;
}
// HTML 支持的希腊字母
function strGreeceDiscode(str) {
str = str.replace(/&Alpha;|&#913;|&#x391;/g, 'Α');
str = str.replace(/&Beta;|&#914;|&#x392;/g, 'Β');
str = str.replace(/&Gamma;|&#915;|&#x393;/g, 'Γ');
str = str.replace(/&Delta;|&#916;|&#x394;/g, 'Δ');
str = str.replace(/&Epsilon;|&#917;|&#x395;/g, 'Ε');
str = str.replace(/&Zeta;|&#918;|&#x396;/g, 'Ζ');
str = str.replace(/&Eta;|&#919;|&#x397;/g, 'Η');
str = str.replace(/&Theta;|&#920;|&#x398;/g, 'Θ');
str = str.replace(/&Iota;|&#921;|&#x399;/g, 'Ι');
str = str.replace(/&Kappa;|&#922;|&#x39a;/g, 'Κ');
str = str.replace(/&Lambda;|&#923;|&#x39b;/g, 'Λ');
str = str.replace(/&Mu;|&#924;|&#x39c;/g, 'Μ');
str = str.replace(/&Nu;|&#925;|&#x39d;/g, 'Ν');
str = str.replace(/&Xi;|&#925;|&#x39d;/g, 'Ν');
str = str.replace(/&Omicron;|&#927;|&#x39f;/g, 'Ο');
str = str.replace(/&Pi;|&#928;|&#x3a0;/g, 'Π');
str = str.replace(/&Rho;|&#929;|&#x3a1;/g, 'Ρ');
str = str.replace(/&Sigma;|&#931;|&#x3a3;/g, 'Σ');
str = str.replace(/&Tau;|&#932;|&#x3a4;/g, 'Τ');
str = str.replace(/&Upsilon;|&#933;|&#x3a5;/g, 'Υ');
str = str.replace(/&Phi;|&#934;|&#x3a6;/g, 'Φ');
str = str.replace(/&Chi;|&#935;|&#x3a7;/g, 'Χ');
str = str.replace(/&Psi;|&#936;|&#x3a8;/g, 'Ψ');
str = str.replace(/&Omega;|&#937;|&#x3a9;/g, 'Ω');
str = str.replace(/&alpha;|&#945;|&#x3b1;/g, 'α');
str = str.replace(/&beta;|&#946;|&#x3b2;/g, 'β');
str = str.replace(/&gamma;|&#947;|&#x3b3;/g, 'γ');
str = str.replace(/&delta;|&#948;|&#x3b4;/g, 'δ');
str = str.replace(/&epsilon;|&#949;|&#x3b5;/g, 'ε');
str = str.replace(/&zeta;|&#950;|&#x3b6;/g, 'ζ');
str = str.replace(/&eta;|&#951;|&#x3b7;/g, 'η');
str = str.replace(/&theta;|&#952;|&#x3b8;/g, 'θ');
str = str.replace(/&iota;|&#953;|&#x3b9;/g, 'ι');
str = str.replace(/&kappa;|&#954;|&#x3ba;/g, 'κ');
str = str.replace(/&lambda;|&#955;|&#x3bb;/g, 'λ');
str = str.replace(/&mu;|&#956;|&#x3bc;/g, 'μ');
str = str.replace(/&nu;|&#957;|&#x3bd;/g, 'ν');
str = str.replace(/&xi;|&#958;|&#x3be;/g, 'ξ');
str = str.replace(/&omicron;|&#959;|&#x3bf;/g, 'ο');
str = str.replace(/&pi;|&#960;|&#x3c0;/g, 'π');
str = str.replace(/&rho;|&#961;|&#x3c1;/g, 'ρ');
str = str.replace(/&sigmaf;|&#962;|&#x3c2;/g, 'ς');
str = str.replace(/&sigma;|&#963;|&#x3c3;/g, 'σ');
str = str.replace(/&tau;|&#964;|&#x3c4;/g, 'τ');
str = str.replace(/&upsilon;|&#965;|&#x3c5;/g, 'υ');
str = str.replace(/&phi;|&#966;|&#x3c6;/g, 'φ');
str = str.replace(/&chi;|&#967;|&#x3c7;/g, 'χ');
str = str.replace(/&psi;|&#968;|&#x3c8;/g, 'ψ');
str = str.replace(/&omega;|&#969;|&#x3c9;/g, 'ω');
str = str.replace(/&thetasym;|&#977;|&#x3d1;/g, 'ϑ');
str = str.replace(/&upsih;|&#978;|&#x3d2;/g, 'ϒ');
str = str.replace(/&piv;|&#982;|&#x3d6;/g, 'ϖ');
str = str.replace(/&middot;|&#183;|&#xb7;/g, '·');
return str;
}
function strcharacterDiscode(str) {
// 加入常用解析
// str = str.replace(/&nbsp;|&#32;|&#x20;/g, "&nbsp;");
// str = str.replace(/&ensp;|&#8194;|&#x2002;/g, '&ensp;');
// str = str.replace(/&#12288;|&#x3000;/g, '<span class=\'spaceshow\'> </span>');
// str = str.replace(/&emsp;|&#8195;|&#x2003;/g, '&emsp;');
// str = str.replace(/&quot;|&#34;|&#x22;/g, "\"");
// str = str.replace(/&apos;|&#39;|&#x27;/g, "&apos;");
// str = str.replace(/&acute;|&#180;|&#xB4;/g, "´");
// str = str.replace(/&times;|&#215;|&#xD7;/g, "×");
// str = str.replace(/&divide;|&#247;|&#xF7;/g, "÷");
// str = str.replace(/&amp;|&#38;|&#x26;/g, '&amp;');
// str = str.replace(/&lt;|&#60;|&#x3c;/g, '&lt;');
// str = str.replace(/&gt;|&#62;|&#x3e;/g, '&gt;');
str = str.replace(/&nbsp;|&#32;|&#x20;/g, "<span class='spaceshow'> </span>");
str = str.replace(/&ensp;|&#8194;|&#x2002;/g, '<span class=\'spaceshow\'></span>');
str = str.replace(/&#12288;|&#x3000;/g, '<span class=\'spaceshow\'> </span>');
str = str.replace(/&emsp;|&#8195;|&#x2003;/g, '<span class=\'spaceshow\'></span>');
str = str.replace(/&quot;|&#34;|&#x22;/g, "\"");
str = str.replace(/&quot;|&#39;|&#x27;/g, "'");
str = str.replace(/&acute;|&#180;|&#xB4;/g, "´");
str = str.replace(/&times;|&#215;|&#xD7;/g, "×");
str = str.replace(/&divide;|&#247;|&#xF7;/g, "÷");
str = str.replace(/&amp;|&#38;|&#x26;/g, '&');
str = str.replace(/&lt;|&#60;|&#x3c;/g, '<');
str = str.replace(/&gt;|&#62;|&#x3e;/g, '>');
return str;
}
// HTML 支持的其他实体
function strOtherDiscode(str) {
str = str.replace(/&OElig;|&#338;|&#x152;/g, 'Œ');
str = str.replace(/&oelig;|&#339;|&#x153;/g, 'œ');
str = str.replace(/&Scaron;|&#352;|&#x160;/g, 'Š');
str = str.replace(/&scaron;|&#353;|&#x161;/g, 'š');
str = str.replace(/&Yuml;|&#376;|&#x178;/g, 'Ÿ');
str = str.replace(/&fnof;|&#402;|&#x192;/g, 'ƒ');
str = str.replace(/&circ;|&#710;|&#x2c6;/g, 'ˆ');
str = str.replace(/&tilde;|&#732;|&#x2dc;/g, '˜');
str = str.replace(/&thinsp;|$#8201;|&#x2009;/g, '<span class=\'spaceshow\'></span>');
str = str.replace(/&zwnj;|&#8204;|&#x200C;/g, '<span class=\'spaceshow\'></span>');
str = str.replace(/&zwj;|$#8205;|&#x200D;/g, '<span class=\'spaceshow\'></span>');
str = str.replace(/&lrm;|$#8206;|&#x200E;/g, '<span class=\'spaceshow\'></span>');
str = str.replace(/&rlm;|&#8207;|&#x200F;/g, '<span class=\'spaceshow\'></span>');
str = str.replace(/&ndash;|&#8211;|&#x2013;/g, '–');
str = str.replace(/&mdash;|&#8212;|&#x2014;/g, '—');
str = str.replace(/&lsquo;|&#8216;|&#x2018;/g, '‘');
str = str.replace(/&rsquo;|&#8217;|&#x2019;/g, '’');
str = str.replace(/&sbquo;|&#8218;|&#x201a;/g, '‚');
str = str.replace(/&ldquo;|&#8220;|&#x201c;/g, '“');
str = str.replace(/&rdquo;|&#8221;|&#x201d;/g, '”');
str = str.replace(/&bdquo;|&#8222;|&#x201e;/g, '„');
str = str.replace(/&dagger;|&#8224;|&#x2020;/g, '†');
str = str.replace(/&Dagger;|&#8225;|&#x2021;/g, '‡');
str = str.replace(/&bull;|&#8226;|&#x2022;/g, '•');
str = str.replace(/&hellip;|&#8230;|&#x2026;/g, '…');
str = str.replace(/&permil;|&#8240;|&#x2030;/g, '‰');
str = str.replace(/&prime;|&#8242;|&#x2032;/g, '′');
str = str.replace(/&Prime;|&#8243;|&#x2033;/g, '″');
str = str.replace(/&lsaquo;|&#8249;|&#x2039;/g, '‹');
str = str.replace(/&rsaquo;|&#8250;|&#x203a;/g, '›');
str = str.replace(/&oline;|&#8254;|&#x203e;/g, '‾');
str = str.replace(/&euro;|&#8364;|&#x20ac;/g, '€');
str = str.replace(/&trade;|&#8482;|&#x2122;/g, '™');
str = str.replace(/&larr;|&#8592;|&#x2190;/g, '←');
str = str.replace(/&uarr;|&#8593;|&#x2191;/g, '↑');
str = str.replace(/&rarr;|&#8594;|&#x2192;/g, '→');
str = str.replace(/&darr;|&#8595;|&#x2193;/g, '↓');
str = str.replace(/&harr;|&#8596;|&#x2194;/g, '↔');
str = str.replace(/&crarr;|&#8629;|&#x21b5;/g, '↵');
str = str.replace(/&lceil;|&#8968;|&#x2308;/g, '⌈');
str = str.replace(/&rceil;|&#8969;|&#x2309;/g, '⌉');
str = str.replace(/&lfloor;|&#8970;|&#x230a;/g, '⌊');
str = str.replace(/&rfloor;|&#8971;|&#x230b;/g, '⌋');
str = str.replace(/&loz;|&#9674;|&#x25ca;/g, '◊');
str = str.replace(/&spades;|&#9824;|&#x2660;/g, '♠');
str = str.replace(/&clubs;|&#9827;|&#x2663;/g, '♣');
str = str.replace(/&hearts;|&#9829;|&#x2665;/g, '♥');
str = str.replace(/&diams;|&#9830;|&#x2666;/g, '♦');
return str;
}
function strDiscode(str) {
str = strNumDiscode(str);
str = strGreeceDiscode(str);
str = strcharacterDiscode(str);
str = strOtherDiscode(str);
return str;
}
function urlToHttpUrl(url, domain) {
if (/^\/\//.test(url)) {
return `https:${url}`;
} else if (/^\//.test(url)) {
return `https://${domain}${url}`;
}
return url;
}
export default {
strDiscode,
urlToHttpUrl,
};

@ -1,258 +0,0 @@
/**
* author: Di (微信小程序开发工程师)
* organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
* 垂直微信小程序开发交流社区
*
* github地址: https://github.com/icindy/wxParse
*
* for: 微信小程序富文本解析
* detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
*/
/**
* 请在全局下引入该文件@import '/static/wxParse.css';
*/
.wxParse {
user-select:none;
width: 100%;
font-family: Helvetica, "PingFangSC", 'Microsoft Yahei', '微软雅黑', Arial, sans-serif;
color: #333;
line-height: 1.5;
font-size: 1em;
text-align:justify;/* //左右两端对齐 */
}
.wxParse view ,.wxParse uni-view{
word-break: break-word;
}
.wxParse .p {
padding-bottom: 0.5em;
clear: both;
/* letter-spacing: 0;//字间距 */
}
.wxParse .inline {
display: inline;
margin: 0;
padding: 0;
}
.wxParse .div {
margin: 0;
padding: 0;
display: block;
}
.wxParse .h1{
font-size: 2em;
line-height: 1.2em;
margin: 0.67em 0;
}
.wxParse .h2{
font-size: 1.5em;
margin: 0.83em 0;
}
.wxParse .h3{
font-size: 1.17em;
margin: 1em 0;
}
.wxParse .h4{
margin: 1.33em 0;
}
.wxParse .h5{
font-size: 0.83em;
margin: 1.67em 0;
}
.wxParse .h6{
font-size: 0.83em;
margin: 1.67em 0;
}
.wxParse .h1,
.wxParse .h2,
.wxParse .h3,
.wxParse .h4,
.wxParse .h5,
.wxParse .h6,
.wxParse .b,
.wxParse .strong{
font-weight: bolder;
}
.wxParse .i,
.wxParse .cite,
.wxParse .em,
.wxParse .var,
.wxParse .address {
font-style: italic;
}
.wxParse .spaceshow{
white-space: pre;
}
.wxParse .pre,
.wxParse .tt,
.wxParse .code,
.wxParse .kbd,
.wxParse .samp {
font-family: monospace;
}
.wxParse .pre {
overflow: auto;
background: #f5f5f5;
padding: 16upx;
white-space: pre;
margin: 1em 0upx;
font-size: 24upx;
}
.wxParse .code {
overflow: auto;
padding: 16upx;
white-space: pre;
margin: 1em 0upx;
background: #f5f5f5;
font-size: 24upx;
}
.wxParse .big {
font-size: 1.17em;
}
.wxParse .small,
.wxParse .sub,
.wxParse .sup {
font-size: 0.83em;
}
.wxParse .sub {
vertical-align: sub;
}
.wxParse .sup {
vertical-align: super;
}
.wxParse .s,
.wxParse .strike,
.wxParse .del {
text-decoration: line-through;
}
.wxParse .strong,
.wxParse .text,
.wxParse .span,
.wxParse .s {
display: inline;
}
.wxParse .a {
color: deepskyblue;
}
.wxParse .video {
text-align: center;
margin: 22upx 0;
}
.wxParse .video-video {
width: 100%;
}
.wxParse .uni-image{
max-width: 100%;
}
.wxParse .img {
display: block;
max-width: 100%;
margin-bottom: 0em;/* //与p标签底部padding同时修改 */
overflow: hidden;
}
.wxParse .blockquote {
margin: 10upx 0;
padding: 22upx 0 22upx 22upx;
font-family: Courier, Calibri, "宋体";
background: #f5f5f5;
border-left: 6upx solid #dbdbdb;
}
.wxParse .blockquote .p {
margin: 0;
}
.wxParse .ul, .wxParse .ol {
display: block;
margin: 1em 0;
padding-left: 2em;
}
.wxParse .ol {
list-style-type: disc;
}
.wxParse .ol {
list-style-type: decimal;
}
.wxParse .ol>weixin-parse-template,.wxParse .ul>weixin-parse-template {
display: list-item;
align-items: baseline;
text-align: match-parent;
}
.wxParse .ol>.li,.wxParse .ul>.li {
display: list-item;
align-items: baseline;
text-align: match-parent;
}
.wxParse .ul .ul, .wxParse .ol .ul {
list-style-type: circle;
}
.wxParse .ol .ol .ul, .wxParse .ol .ul .ul, .wxParse .ul .ol .ul, .wxParse .ul .ul .ul {
list-style-type: square;
}
.wxParse .u {
text-decoration: underline;
}
.wxParse .hide {
display: none;
}
.wxParse .del {
display: inline;
}
.wxParse .figure {
overflow: hidden;
}
.wxParse .tablebox{
overflow: auto;
background-color: #f5f5f5;
background: #f5f5f5;
font-size: 13px;
padding: 8px;
}
.wxParse .table .table,.wxParse .table{
border-collapse:collapse;
box-sizing: border-box;
/* 内边框 */
/* width: 100%; */
overflow: auto;
white-space: pre;
}
.wxParse .tbody{
border-collapse:collapse;
box-sizing: border-box;
/* 内边框 */
border: 1px solid #dadada;
}
.wxParse .table .thead, .wxParse .table .tfoot, .wxParse .table .th{
border-collapse:collapse;
box-sizing: border-box;
background: #ececec;
font-weight: 40;
}
.wxParse .table .tr {
border-collapse:collapse;
box-sizing: border-box;
/* border: 2px solid #F0AD4E; */
overflow:auto;
}
.wxParse .table .th,
.wxParse .table .td{
border-collapse:collapse;
box-sizing: border-box;
border: 2upx solid #dadada;
overflow:auto;
}
.wxParse .audio, .wxParse .uni-audio-default{
display: block;
}

@ -1,228 +0,0 @@
<!--**
* forked fromhttps://github.com/F-loat/mpvue-wxParse
*
* github地址: https://github.com/dcloudio/uParse
*
* for: uni-app框架下 富文本解析
*
* 优化 by gaoyia@qq.com https://github.com/gaoyia/parse
*/-->
<template>
<!--基础元素-->
<div class="wxParse" :class="className" :style="'user-select:' + userSelect">
<block v-for="(node, index) of nodes" :key="index" v-if="!loading">
<wxParseTemplate :node="node" />
</block>
</div>
</template>
<script>
import HtmlToJson from './libs/html2json';
import wxParseTemplate from './components/wxParseTemplate0';
export default {
name: 'wxParse',
props: {
// user-select:none;
userSelect: {
type: String,
default: 'text' //none |text| all | element
},
imgOptions: {
type: [Object, Boolean],
default: function() {
return {
loop: false,
indicator: 'number',
longPressActions: false
// longPressActions: {
// itemList: ['', '', ''],
// success: function (res) {
// console.log('' + (res.tapIndex + 1) + '');
// },
// fail: function (res) {
// console.log(res.errMsg);
// }
// }
// }
}
}
},
loading: {
type: Boolean,
default: false
},
className: {
type: String,
default: ''
},
content: {
type: String,
default: ''
},
noData: {
type: String,
default: '<div style="color: red;">数据不能为空</div>'
},
startHandler: {
type: Function,
default () {
return node => {
node.attr.class = null;
node.attr.style = null;
};
}
},
endHandler: {
type: Function,
default: null
},
charsHandler: {
type: Function,
default: null
},
imageProp: {
type: Object,
default () {
return {
mode: 'aspectFit',
padding: 0,
lazyLoad: false,
domain: ''
};
}
}
},
components: {
wxParseTemplate
},
data() {
return {
nodes: {},
imageUrls: [],
wxParseWidth: {
value: 0
}
};
},
computed: {},
mounted() {
this.setHtml()
},
methods: {
setHtml() {
this.getWidth().then((data) => {
this.wxParseWidth.value = data;
})
let {
content,
noData,
imageProp,
startHandler,
endHandler,
charsHandler
} = this;
let parseData = content || noData;
let customHandler = {
start: startHandler,
end: endHandler,
chars: charsHandler
};
let results = HtmlToJson(parseData, customHandler, imageProp, this);
this.imageUrls = results.imageUrls;
// this.nodes = results.nodes;
this.nodes = [];
results.nodes.forEach((item) => {
setTimeout(() => {
this.nodes.push(item)
}, 0);
})
},
getWidth() {
return new Promise((res, rej) => {
// #ifndef MP-ALIPAY || MP-BAIDU
uni.createSelectorQuery()
.in(this)
.select('.wxParse')
.fields({
size: true,
scrollOffset: true
},
data => {
res(data.width);
}
).exec();
// #endif
// #ifdef MP-BAIDU
const query = swan.createSelectorQuery();
query.select('.wxParse').boundingClientRect();
query.exec(obj => {
const rect = obj[0]
if (rect) {
res(rect.width);
}
});
// #endif
// #ifdef MP-ALIPAY
my.createSelectorQuery()
.select('.wxParse')
.boundingClientRect().exec((ret) => {
res(ret[0].width);
});
// #endif
});
},
navigate(href, $event, attr) {
console.log(href, attr);
this.$emit('navigate', href, $event);
},
preview(src, $event) {
if (!this.imageUrls.length || typeof this.imgOptions === 'boolean') {
} else {
uni.previewImage({
current: src,
urls: this.imageUrls,
loop: this.imgOptions.loop,
indicator: this.imgOptions.indicator,
longPressActions: this.imgOptions.longPressActions
});
}
this.$emit('preview', src, $event);
},
removeImageUrl(src) {
const {
imageUrls
} = this;
imageUrls.splice(imageUrls.indexOf(src), 1);
}
},
//
provide() {
return {
parseWidth: this.wxParseWidth,
parseSelect: this.userSelect
// provide inject
};
},
watch: {
content(){
this.setHtml()
}
// content: {
// handler: function(newVal, oldVal) {
// if (newVal !== oldVal) {
//
// }
// },
// deep: true
// }
}
};
</script>

@ -0,0 +1,26 @@
<template>
<view class="per-mask">
<view class="mask"></view>
<view class="texts">
<view class="text">权限审核中可联系下方平台运营加快审核进度</view>
<image class="qrcode" :src="src" mode="widthFix"></image>
</view>
</view>
</template>
<script>
export default {
data() {
return {
src: uni.getSystemInfoSync().uniPlatform === 'mp-toutiao' ? 'https://occupationlab.com/images/dyQrcode.jpg' : 'https://occupationlab.com/images/customer.png'
}
},
methods: {
}
}
</script>
<style scoped lang="scss">
</style>

@ -1,140 +0,0 @@
<template>
<view class="uni-section">
<view class="uni-section-header" nvue>
<view v-if="type" class="uni-section__head">
<view :class="type" class="uni-section__head-tag"/>
</view>
<view class="uni-section__content">
<text :class="{'distraction':!subTitle}" :style="{color:color}" class="uni-section__content-title">{{ title }}</text>
<text v-if="subTitle" class="uni-section__content-sub">{{ subTitle }}</text>
</view>
</view>
<view :style="{padding: padding ? '10px' : ''}">
<slot/>
</view>
</view>
</template>
<script>
/**
* Section 标题栏
* @description 标题栏
* @property {String} type = [line|circle] 标题装饰类型
* @value line 竖线
* @value circle 圆形
* @property {String} title 主标题
* @property {String} subTitle 副标题
*/
export default {
name: 'UniSection',
emits:['click'],
props: {
type: {
type: String,
default: ''
},
title: {
type: String,
default: ''
},
color:{
type: String,
default: '#333'
},
subTitle: {
type: String,
default: ''
},
padding: {
type: Boolean,
default: false
}
},
data() {
return {}
},
watch: {
title(newVal) {
if (uni.report && newVal !== '') {
uni.report('title', newVal)
}
}
},
methods: {
onClick() {
this.$emit('click')
}
}
}
</script>
<style lang="scss" >
$uni-primary: #2979ff !default;
.uni-section {
background-color: #fff;
// overflow: hidden;
margin-top: 10px;
}
.uni-section-header {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
padding: 12px 10px;
// height: 50px;
font-weight: normal;
}
.uni-section__head {
flex-direction: row;
justify-content: center;
align-items: center;
margin-right: 10px;
}
.line {
height: 12px;
background-color: $uni-primary;
border-radius: 10px;
width: 4px;
}
.circle {
width: 8px;
height: 8px;
border-top-right-radius: 50px;
border-top-left-radius: 50px;
border-bottom-left-radius: 50px;
border-bottom-right-radius: 50px;
background-color: $uni-primary;
}
.uni-section__content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
flex: 1;
color: #333;
}
.uni-section__content-title {
font-size: 14px;
color: $uni-primary;
}
.distraction {
flex-direction: row;
align-items: center;
}
.uni-section__content-sub {
font-size: 12px;
color: #999;
line-height: 16px;
margin-top: 2px;
}
</style>

@ -5,9 +5,9 @@
*/
export default {
// baseURL: 'https://huorantech.cn/',
// baseURL: 'http://192.168.31.117:9000/',
baseURL: 'http://121.37.12.51/',
baseURL: 'https://www.occupationlab.com/',
// baseURL: 'http://192.168.31.51:9000/',
// baseURL: 'http://121.37.12.51/',
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},

@ -1,16 +0,0 @@
/**
* @description 鉴权指令
* 当传入的权限当前用户没有时会移除该组件
* 用例<Tag v-auth>text</Tag> <Tag v-auth="'user:'">text</Tag>
* */
export default {
inserted(el, binding, vnode) {
const btnText = el.innerText
const btnPermissions = uni.getStorageSync('auth')
if (btnText && btnPermissions && btnPermissions.length) {
const isPermission = btnPermissions.includes(btnText)
// 如果按钮集合里没有该权限,就把该按钮给去除
!isPermission && el.parentNode && el.parentNode.removeChild(el)
}
},
};

@ -1,12 +0,0 @@
/**
* 插件
* */
import auth from './auth'
export default {
async install(Vue, options) {
// 指令
Vue.directive('auth', auth)
}
};

@ -0,0 +1,135 @@
export const Base64 = {
// private property
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
// public method for encoding
encode : function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = Base64._utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
}
return output;
},
// public method for decoding
decode : function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (i < input.length) {
enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
output = Base64._utf8_decode(output);
return output;
},
// private method for UTF-8 encoding
_utf8_encode : function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
},
// private method for UTF-8 decoding
_utf8_decode : function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
}

@ -0,0 +1,117 @@
var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
let Crypto = {};
var util = Crypto.util = {
rotl: function (n, b) {
return (n << b) | (n >>> (32 - b));
},
rotr: function (n, b) {
return (n << (32 - b)) | (n >>> b);
},
endian: function (n) {
if (n.constructor == Number) {
return util.rotl(n, 8) & 0x00FF00FF |
util.rotl(n, 24) & 0xFF00FF00;
}
for (var i = 0; i < n.length; i++)
n[i] = util.endian(n[i]);
return n;
},
randomBytes: function (n) {
for (var bytes = []; n > 0; n--)
bytes.push(Math.floor(Math.random() * 256));
return bytes;
},
stringToBytes: function (str) {
var bytes = [];
for (var i = 0; i < str.length; i++)
bytes.push(str.charCodeAt(i));
return bytes;
},
bytesToString: function (bytes) {
var str = [];
for (var i = 0; i < bytes.length; i++)
str.push(String.fromCharCode(bytes[i]));
return str.join("");
},
stringToWords: function (str) {
var words = [];
for (var c = 0, b = 0; c < str.length; c++, b += 8)
words[b >>> 5] |= str.charCodeAt(c) << (24 - b % 32);
return words;
},
bytesToWords: function (bytes) {
var words = [];
for (var i = 0, b = 0; i < bytes.length; i++, b += 8)
words[b >>> 5] |= bytes[i] << (24 - b % 32);
return words;
},
wordsToBytes: function (words) {
var bytes = [];
for (var b = 0; b < words.length * 32; b += 8)
bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
return bytes;
},
bytesToHex: function (bytes) {
var hex = [];
for (var i = 0; i < bytes.length; i++) {
hex.push((bytes[i] >>> 4).toString(16));
hex.push((bytes[i] & 0xF).toString(16));
}
return hex.join("");
},
hexToBytes: function (hex) {
var bytes = [];
for (var c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
},
bytesToBase64: function (bytes) {
if (typeof btoa == "function") return btoa(util.bytesToString(bytes));
var base64 = [],
overflow;
for (var i = 0; i < bytes.length; i++) {
switch (i % 3) {
case 0:
base64.push(base64map.charAt(bytes[i] >>> 2));
overflow = (bytes[i] & 0x3) << 4;
break;
case 1:
base64.push(base64map.charAt(overflow | (bytes[i] >>> 4)));
overflow = (bytes[i] & 0xF) << 2;
break;
case 2:
base64.push(base64map.charAt(overflow | (bytes[i] >>> 6)));
base64.push(base64map.charAt(bytes[i] & 0x3F));
overflow = -1;
}
}
if (overflow != undefined && overflow != -1)
base64.push(base64map.charAt(overflow));
while (base64.length % 4 != 0) base64.push("=");
return base64.join("");
},
base64ToBytes: function (base64) {
if (typeof atob == "function") return util.stringToBytes(atob(base64));
base64 = base64.replace(/[^A-Z0-9+\/]/ig, "");
var bytes = [];
for (var i = 0; i < base64.length; i++) {
switch (i % 4) {
case 1:
bytes.push((base64map.indexOf(base64.charAt(i - 1)) << 2) |
(base64map.indexOf(base64.charAt(i)) >>> 4));
break;
case 2:
bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & 0xF) << 4) |
(base64map.indexOf(base64.charAt(i)) >>> 2));
break;
case 3:
bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & 0x3) << 6) |
(base64map.indexOf(base64.charAt(i))));
break;
}
}
return bytes;
}
};
Crypto.mode = {};
export default Crypto;

@ -0,0 +1,37 @@
import Crypto from './crypto.js';
/*!
* Crypto-JS v1.1.0
* http://code.google.com/p/crypto-js/
* Copyright (c) 2009, Jeff Mott. All rights reserved.
* http://code.google.com/p/crypto-js/wiki/License
*/
(function(){
// Shortcut
var util = Crypto.util;
Crypto.HMAC = function (hasher, message, key, options) {
// Allow arbitrary length keys
key = key.length > hasher._blocksize * 4 ?
hasher(key, { asBytes: true }) :
util.stringToBytes(key);
// XOR keys with pad constants
var okey = key,
ikey = key.slice(0);
for (var i = 0; i < hasher._blocksize * 4; i++) {
okey[i] ^= 0x5C;
ikey[i] ^= 0x36;
}
var hmacbytes = hasher(util.bytesToString(okey) +
hasher(util.bytesToString(ikey) + message, { asString: true }),
{ asBytes: true });
return options && options.asBytes ? hmacbytes :
options && options.asString ? util.bytesToString(hmacbytes) :
util.bytesToHex(hmacbytes);
};
})();

@ -0,0 +1,82 @@
import Crypto from './crypto.js';
/*!
* Crypto-JS v1.1.0
* http://code.google.com/p/crypto-js/
* Copyright (c) 2009, Jeff Mott. All rights reserved.
* http://code.google.com/p/crypto-js/wiki/License
*/
(function(){
// Shortcut
var util = Crypto.util;
// Public API
var SHA1 = Crypto.SHA1 = function (message, options) {
var digestbytes = util.wordsToBytes(SHA1._sha1(message));
return options && options.asBytes ? digestbytes :
options && options.asString ? util.bytesToString(digestbytes) :
util.bytesToHex(digestbytes);
};
// The core
SHA1._sha1 = function (message) {
var m = util.stringToWords(message),
l = message.length * 8,
w = [],
H0 = 1732584193,
H1 = -271733879,
H2 = -1732584194,
H3 = 271733878,
H4 = -1009589776;
// Padding
m[l >> 5] |= 0x80 << (24 - l % 32);
m[((l + 64 >>> 9) << 4) + 15] = l;
for (var i = 0; i < m.length; i += 16) {
var a = H0,
b = H1,
c = H2,
d = H3,
e = H4;
for (var j = 0; j < 80; j++) {
if (j < 16) w[j] = m[i + j];
else {
var n = w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16];
w[j] = (n << 1) | (n >>> 31);
}
var t = ((H0 << 5) | (H0 >>> 27)) + H4 + (w[j] >>> 0) + (
j < 20 ? (H1 & H2 | ~H1 & H3) + 1518500249 :
j < 40 ? (H1 ^ H2 ^ H3) + 1859775393 :
j < 60 ? (H1 & H2 | H1 & H3 | H2 & H3) - 1894007588 :
(H1 ^ H2 ^ H3) - 899497514);
H4 = H3;
H3 = H2;
H2 = (H1 << 30) | (H1 >>> 2);
H1 = H0;
H0 = t;
}
H0 += a;
H1 += b;
H2 += c;
H3 += d;
H4 += e;
}
return [H0, H1, H2, H3, H4];
};
// Package private blocksize
SHA1._blocksize = 16;
})();

@ -0,0 +1,71 @@
import Crypto from './crypto.js';
import './hmac.js';
import './sha1.js';
import Util from '@/libs/util'
import {Base64} from './base64.js';
let date=new Date()
date=date.setHours(date.getHours() + 24)
let extime=""+new Date(date).toISOString()
console.log(33, extime)
var policyText = {
"expiration": extime, //设置该Policy的失效时间,超过这个失效时间之后,就没有办法通过这个policy上传文件了
"conditions": [
["content-length-range", 0, 1024*1024*100] // 设置上传文件的大小限制
]
};
var config={
accessid:'LTAI4FzqQHnk4rozqLZ8jCNj',
accesskey:'mveW7B1OyFoKUkHm8WsxmrjHmkJWHq',
osshost:'https://huoran.oss-cn-shenzhen.aliyuncs.com',
policyBase64:Base64.encode(JSON.stringify(policyText))
}
var message = config.policyBase64;
var bytes = Crypto.HMAC(Crypto.SHA1, message, config.accesskey, { asBytes: true }) ;
var signature = Crypto.util.bytesToBase64(bytes);
var timetamp = new Date().getTime();
function random_string(len) {
  len = len || 32;
  var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
  var maxPos = chars.length;
  var pwd = '';
  for (let i = 0; i < len; i++) {
  pwd += chars.charAt(Math.floor(Math.random() * maxPos));
}
return pwd;
}
var OSS={
name:'aliyun',
host:config.osshost,
accessid:config.accessid,
signature:signature,
policyBase64:config.policyBase64,
}
export default function(tempFilePaths, callback) {
const ext = Util.getFileExt(tempFilePaths)
const fileName = Date.now() + '.' + ext
uni.uploadFile({
   url: OSS.host,
   filePath: tempFilePaths,
fileType: '',
name: 'file',
formData: {
name: fileName,
key: fileName,//文件名
  policy: OSS.policyBase64, // 输入你获取的的policy
OSSAccessKeyId: OSS.accessid, // 输入你的AccessKeyId
success_action_status: '200', // 让服务端返回200,不然,默认会返回204
signature: OSS.signature, // 输入你获取的的signature
},
success: (res) => {
callback({
name: fileName,
url: OSS.host + '/' + fileName,
ext
})
},
fail: (res) => {
console.log(res);
}
})
};

@ -0,0 +1,39 @@
/**
* @file 百度移动统计配置文件
*/
module.exports = {
/**
* 从百度移动统计获取的AppKey
* @type {string}
*/
appKey: 'ce2fa79380',
/**
* 是否使用了插件
* @type {boolean}
*/
hasPlugin: false,
/**
* 是否获取当前的地理位置和速度信息
* @type {boolean}
*/
getLocation: false,
/**
* 是否获取组件滚动信息
* @type {boolean}
*/
getComponentScroll: false,
/**
* 是否开启了A/B 测试
* @type {boolean}
*/
hasABTest: false,
/**
* 是否开启热力图功能
* @type {boolean}
*/
hasHeatmap: false,
};

File diff suppressed because one or more lines are too long

@ -0,0 +1,36 @@
export default{
// 监听用户点击右上角菜单的「转发」按钮时触发的事件
onShareAppMessage() {
// 设置转发的参数
return {
title: "职站商城",
// path: '',
imageUrl: "",
success: function(res) {
if (res.errMsg == 'shareAppMessage:ok') {
console.log("成功", res)
}
},
fail: function(res) {
console.log("失败", res)
}
}
},
// 分享到朋友圈
onShareTimeline:function(res){
return {
title: '职站商城',
// imageUrl:'/static/image/phone.png',
query:''
}
},
// 收藏
onAddToFavorites:function(res) {
return {
title: '职站商城',
// imageUrl:'/static/image/phone.png',
query: '',
}
}
}

@ -0,0 +1,18 @@
import uma from 'umtrack-wx';
uma.init({
appKey: '64cc98d5a1a164591b62da3e', // 由友盟分配的APP_KEY
useOpenid: true,
// 使用Openid进行统计,此项为false时将使用友盟+uuid进行用户统计。
// 使用Openid来统计微信小程序的用户,会使统计的指标更为准确,对系统准确性要求高的应用推荐使用Openid
autoGetOpenid: true,
// 使用openid进行统计时,是否授权友盟自动获取Openid,
// 如若需要,请到友盟后台"设置管理-应用信息"(https://mp.umeng.com/setting/appset)中设置appId及secret
debug: true,// 是否打开调试模式
uploadUserInfo: true, // 自动上传用户信息,设为false取消上传,默认为false
enableVerify: true
});
uma.install = function(Vue) {
Vue.prototype.$uma = uma;
}
export default uma;

@ -1,11 +1,11 @@
import Product from '@/config/product'
const files = [
'https://huorantech.cn/%E7%94%A8%E6%88%B7%E6%9C%8D%E5%8A%A1%E5%8D%8F%E8%AE%AE.docx', // 用户服务协议
'https://huorantech.cn/%E7%94%A8%E6%88%B7%E9%9A%90%E7%A7%81%E5%8D%8F%E8%AE%AE.docx', // 用户隐私协议
'https://huorantech.cn/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD%E5%AE%9E%E9%AA%8C%E5%AE%A4%E5%BB%BA%E8%AE%BE%E6%96%B9%E6%A1%88-2020.1.docx', // 人工智能
'https://huorantech.cn/%E5%A4%A7%E6%95%B0%E6%8D%AE%E7%AE%A1%E7%90%86%E4%B8%8E%E5%BA%94%E7%94%A8%E4%B8%93%E4%B8%9A%E5%BB%BA%E8%AE%BE%E6%96%B9%E6%A1%88.docx', // 大数据
'https://huorantech.cn/%E9%87%91%E8%9E%8D%E7%A7%91%E6%8A%80%E5%AE%9E%E9%AA%8C%E5%AE%A4%E5%BB%BA%E8%AE%BE%E6%96%B9%E6%A1%88V2.0.docx', // 金融科技
'https://huoran.oss-cn-shenzhen.aliyuncs.com/用户服务协议.docx', // 用户服务协议
'https://huoran.oss-cn-shenzhen.aliyuncs.com/用户隐私协议.docx', // 用户隐私协议
'https://huoran.oss-cn-shenzhen.aliyuncs.com/1709798668435.docx', // 人工智能
'https://huoran.oss-cn-shenzhen.aliyuncs.com/1709798621083.docx', // 大数据
'https://huoran.oss-cn-shenzhen.aliyuncs.com/1709798646462.docx', // 金融科技
]
const docExts = ['doc', 'xls', 'ppt', 'pdf', 'docx', 'xlsx', 'pptx']
export default {
@ -32,7 +32,7 @@ export default {
},
// 如果非数字,则返回0
handleNaN(val) {
return isNaN(val) ? 0 : val
return isNaN(val) || val == 0 ? '' : val
},
// 小于10,返回0+传入值
preZero(val) {
@ -68,9 +68,9 @@ export default {
getBmName(val) {
return uni.getStorageSync('team').partnerClassificationName
},
// 返回图标。如果有图标,则直接返回,否则判断是否是数据产品,即productType=2,如果是,则取数据图标,否则则显示通用图标,这两个图标都在config/product.js里有配置
// 返回图标。如果有图标,则直接返回
getIcon(e) {
return e.miniProgramPictureAddress || (e.productType === 2 ? Product.dataIcon : Product.normalIcon)
return e.appletIcon || Product.normalIcon
},
// 判断文件类型是否能够通过uni.openDocument打开(doc, xls, ppt, pdf, docx, xlsx, pptx)
isDoc(ext) {
@ -86,6 +86,7 @@ export default {
uni.downloadFile({
url: files[id],
success: function(res) {
console.log(11, res)
uni.hideLoading();
uni.showLoading({
title: '正在打开',
@ -94,7 +95,7 @@ export default {
// 新开页面打开文档,支持格式:doc, xls, ppt, pdf, docx, xlsx, pptx。
uni.openDocument({
filePath: res.tempFilePath,
fileType: 'docx', // 文件类型,指定文件类型打开文件,有效值 doc, xls, ppt, pdf, docx, xlsx, pptx
fileType: 'pdf', // 文件类型,指定文件类型打开文件,有效值 doc, xls, ppt, pdf, docx, xlsx, pptx
showMenu: true, // 允许出现分享功能
success: res => {
uni.hideLoading()
@ -108,5 +109,21 @@ export default {
uni.hideLoading()
}
})
}
},
// 产品管理的产品分类(classificationId)有6个,订单管理的产品分类(authority)有5个,后者是由前者决定的,但是id不一样。把产品管理的分类id传入这个函数,即可返回订单的分类id
getOrderType(id) {
if (id == 1 || id == 2) return 1
if (id == 3) return 2
if (id == 4) return 3
if (id == 5) return 0
if (id == 6) return 4
},
// 去掉html标签
removeTag(str) {
return str.replace(/(<[^>]+>)|((&nbsp;)+)/g , '')
},
// 传入文件名获取文件后缀
getFileExt(fileName) {
return fileName.substring(fileName.lastIndexOf(".") + 1);
},
}

@ -3,11 +3,14 @@
import Vue from 'vue'
import App from './App'
import util from '@/libs/util'
import plugins from '@/directives'
import uma from './libs/uma'
import share from './libs/share'
import mtjWxSdk from './libs/mtj-wx-sdk'
Vue.config.productionTip = false
Vue.prototype.$util = util
Vue.use(plugins)
Vue.use(uma)
Vue.mixin(share)
App.mpType = 'app'
@ -22,7 +25,8 @@ Vue.prototype.auth = function(text){
}
const app = new Vue({
...App
...App,
share
})
app.$mount()
// #endif

@ -1,5 +1,5 @@
{
"name" : "或然合伙人运营管理平台",
"name" : "职站商城",
"appid" : "__UNI__2E89BA6",
"description" : "",
"versionName" : "1.0.0",
@ -45,6 +45,7 @@
}
},
/* SDK */
"sdkConfigs" : {},
"quickapp" : {},
/* */
"mp-weixin" : {
@ -57,7 +58,16 @@
"usingComponents" : true,
"optimization" : {
"subPackages" : true
},
"uniStatistics" : {
"enable" : false
}
},
"vueVersion" : "2"
"vueVersion" : "2",
"uniStatistics" : {
"version" : "2"
},
"mp-toutiao" : {
"appid" : "tt2192572fbea04fe601"
}
}

@ -4,15 +4,21 @@
<uni-search-bar class="search" radius="5" placeholder="请输入产品名称" clearButton="auto" cancelButton="none" v-model="keyword" />
</uni-card>
<ul class="tab">
<li v-for="(tab, i) in tabs" :class="{active: curTab === tab.id}" @click="tabChange(tab)">{{ tab.name }}</li>
<ul class="tab-wrap">
<view class="tab">
<li :class="{active: curTab === ''}" @click="tabChange('')">全部</li>
</view>
<scroll-view scroll-x :scroll-left="scrollLeft" class="tab tab-scroll">
<li v-for="(tab, i) in tabs" :key="i" :class="{active: curTab === tab.id}" @click="tabChange(tab.id)">{{ tab.name }}</li>
</scroll-view>
</ul>
<ul class="list">
<li v-for="(item, i) in list">
<li v-for="(item, i) in list" :key="i">
<uni-data-checkbox v-if="item.check" class="check" multiple :value="[1]" :localdata="item.checkData" @change="e => checkChange(e, i)"></uni-data-checkbox>
<uni-data-checkbox v-else class="check" multiple v-model="item.check" :localdata="item.checkData" @change="e => checkChange(e, i)"></uni-data-checkbox>
<image class="icon" :src="$util.getIcon(item)" mode="widthFix"></image>
<image class="icon" :src="$util.getIcon(item)"></image>
{{ item.productName }}
</li>
</ul>
@ -26,32 +32,19 @@
</template>
<script>
import { AppletsDataProductList } from '@/apis/modules/product.js'
import { renew } from '@/apis/modules/order.js'
import { productTypeList, listOfGoods } from '@/apis/modules/product.js'
import { renew, queryCitySettlementPrice } from '@/apis/modules/order.js'
export default {
data() {
return {
// authority: 01234
orderType: 1,
customerId: '',
provinceId: '',
cityId: '',
curTab: '',
tabs: [
{
name: '全部',
id: ''
},
{
name: '实训课程',
id: 1
},
{
name: '理论课程',
id: 0
},
{
name: '数据产品',
id: 2
}
],
tabs: [],
scrollLeft: 0,
reachBottom: 0, // 0->,1->,-1->
status: 'more', // more|loading|noMore
searchTimer: null,
@ -74,7 +67,8 @@
value: 1
}],
checked: uni.getStorageSync('courses') || [], //
courses: uni.getStorageSync('courses') || []
courses: uni.getStorageSync('courses') || [],
submiting: false,
}
},
watch: {
@ -105,22 +99,37 @@
const { options } = pages[pages.length - 1]
this.orderType = options.orderType
this.customerId = options.customerId
this.provinceId = options.provinceId
this.cityId = options.cityId
this.getTypes()
this.getList()
},
methods: {
//
getTypes() {
productTypeList().then(res => {
res.typeList.forEach(e => {
e.id = e.typeId
e.name = e.typeName
})
this.tabs.push(...res.typeList)
}).catch(e => {})
},
//
getList() {
uni.showLoading({
title: '加载中'
})
AppletsDataProductList({
sort: 'desc',
keywords: this.keyword,
productType: this.curTab,
listOfGoods({
pageNum: this.page,
pageSize: this.pageSize
}).then(({ data }) => {
const { records } = data
pageSize: this.pageSize,
sort: 0,
isShelves: 0,
hotTag: 1,
productName: this.keyword,
productType: this.curTab,
}).then(({ page }) => {
const { records } = page
const list = this.courses
const all = this.checkAll.length //
const pageChange = this.reachBottom > 0 //
@ -131,9 +140,9 @@
text: '',
value: 1
}
e.check = (all && pageChange) || checked.find(n => n.id === e.id && n.productType === e.productType) ? 1 : 0
e.check = (all && pageChange) || checked.find(n => n.mallId === e.mallId) ? 1 : 0
//
if (list.find(n => n.dataOrCourseId == e.id && n.productType == e.productType)) {
if (list.find(n => n.mallId == e.mallId)) {
//
checkData.disable = true
e.check = 1
@ -144,7 +153,7 @@
// list
this.list = pageChange ? [...this.list, ...records] : records
this.page++ // page+1
const noMore = this.list.length === data.total //
const noMore = this.list.length === page.total //
this.status = noMore ? 'noMore' : 'more' // noMore
this.reachBottom = noMore ? -1 : 0 // -1
uni.hideLoading()
@ -158,16 +167,16 @@
this.getList()
},
// tab
tabChange(tab) {
this.curTab = tab.id
tabChange(id) {
this.curTab = id
this.initList()
},
//
checkChange(e, i) {
const { checked } = this
const item = this.list[i]
const { id, productType } = item
const include = checked.findIndex(e => e.id === id && e.productType === productType)
const { mallId } = item
const include = checked.findIndex(e => e.mallId === mallId)
// pushpush
if (e.detail.value.length) {
include === -1 && checked.push(item)
@ -185,8 +194,8 @@
const { checked, list } = this
list.map(e => {
e.check = isCheck ? 1 : 0
const { id, productType } = e
const include = checked.findIndex(n => n.id === id && n.productType === productType)
const { mallId } = e
const include = checked.findIndex(n => n.mallId === mallId)
// pushpush
if (isCheck) {
include === -1 && checked.push(e)
@ -197,34 +206,36 @@
})
},
//
createParam(e) {
createParam(e, authority) {
const { orderType } = this
const trial = orderType == 2 //
return {
dataOrCourseId: e.id, // id
dataOrCourseId: e.associatedProduct, // id
mallId: e.mallId,
productName: e.productName, //
periodOfUse: '', // 使
periodOfUse: trial ? 1 : '', // 使
startTime: this.$util.formatDate(new Date(), 'yyyy-MM-dd'), //
endTime: '', //
remainingPeriod: '', //
marketValue: '', //
marketPrice: e.marketPrice, //
marketPrice: e.marketUnitPrice, //
finalPrice: trial ? 0 : '', //
finalValue: trial ? 0 : '', //
discountRate: trial ? '0%' : '', //
accountNum: e.productType === 2 ? '' : 1, //
accountNum: authority ? 1 : '', //
totalAmount: '', //
isEnable: 1, // 10
isEnable: 0, // 10
ship: 0, // 01
authority: e.productType === 2 ? 0 : 1, // 01
productType: e.productType, // (0-> 1- 2 )
options: 2,
miniProgramPictureAddress: e.miniProgramPictureAddress, //
authority, // 01
options: trial ? 1 : 2,
miniProgramPictureAddress: e.appletIcon || '', //
settlementPrice: trial ? 0 : '', //
settlementMethod: e.settlementMethod, // 01
settlementPriceUnit: e.settlementPrice, //
businessProportion: e.businessProportion, //
serviceFee: 0 //
settlementPriceUnit: e.settlementPrice || 0, //
serviceFee: 0, //
mallNonAssociatedLinks: e.mallNonAssociatedLinks, //
typeId: e.typeId,
typeName: e.typeName,
classificationId: e.classificationId,
}
},
//
@ -251,31 +262,77 @@
submit() {
const list = this.checked //
if (list.length) {
if (this.submiting) return false
this.submiting = true
uni.showLoading({
title: '加载中'
})
const result = this.courses
const courseIds = []
const dataIds = []
const list1 = [] //
const list0 = [] //
const list2 = [] //
const list3 = [] //
const list4 = [] //
const { customerId } = this
list.map(e => {
// id
if (!result.find(n => (n.dataOrCourseId == e.id || n.dataOrCourseId == e.dataOrCourseId) && ((n.authority && e.productType != 2) || (!n.authority && e.productType == 2)))) {
e.productType === 2 ? dataIds.push(e.id) : courseIds.push(e.id)
result.push(this.createParam(e))
const listPromise = []
list.forEach(async e => {
listPromise.push(new Promise(async (resolve, reject) => {
// id
if (!result.find(n => (n.dataOrCourseId == e.associatedProduct || n.dataOrCourseId == e.dataOrCourseId) && n.authority == e.authority)) {
//
if (this.provinceId) {
const res = await queryCitySettlementPrice(e.mallId, this.provinceId, this.cityId)
if (res.mallPrice) e.settlementPrice = res.mallPrice.discountRate
}
const classId = e.classificationId
const pid = +e.associatedProduct
const { mallId } = e
if (classId == 1 || classId == 2) {
list1.push(mallId)
} else if (classId == 3) {
list2.push(mallId)
} else if (classId == 4) {
list3.push(mallId)
} else if (classId == 5) {
list0.push(mallId)
} else if (classId == 6) {
list4.push(mallId)
}
result.push(this.createParam(e, this.$util.getOrderType(classId)))
resolve()
} else {
resolve()
}
}))
})
Promise.all(listPromise).then(_ => {
const promises = []
//
dataIds.length && promises.push(new Promise((resolve, reject) => {
this.handleRenew(0, customerId, dataIds, result, resolve, reject)
// 5authorityrenew
list0.length && promises.push(new Promise((resolve, reject) => {
this.handleRenew(0, customerId, list0, result, resolve, reject)
}))
list1.length && promises.push(new Promise((resolve, reject) => {
this.handleRenew(1, customerId, list1, result, resolve, reject)
}))
list2.length && promises.push(new Promise((resolve, reject) => {
this.handleRenew(2, customerId, list2, result, resolve, reject)
}))
courseIds.length && promises.push(new Promise((resolve, reject) => {
this.handleRenew(1, customerId, courseIds, result, resolve, reject)
list3.length && promises.push(new Promise((resolve, reject) => {
this.handleRenew(3, customerId, list3, result, resolve, reject)
}))
list4.length && promises.push(new Promise((resolve, reject) => {
this.handleRenew(4, customerId, list4, result, resolve, reject)
}))
Promise.all(promises).then(_ => {
console.log(33, result)
uni.setStorageSync('courses', result) //
uni.redirectTo({
url: `../editCourse/editCourse?customerId=${customerId}&orderType=${this.orderType}`
})
})
})
} else {
this.$util.errMsg('请选择产品!')
}
@ -288,6 +345,16 @@
.page {
padding-bottom: 130rpx;
}
.tab-wrap {
display: flex;
.tab-scroll {
width: calc(100% - 100rpx);
white-space: nowrap;
li {
display: inline-block;
}
}
}
.list {
li {
display: flex;
@ -301,7 +368,10 @@
}
.icon {
width: 80rpx;
min-width: 80rpx;
height: 80rpx;
margin: 0 20rpx;
border-radius: 4px;
}
}
/deep/.check {

@ -107,6 +107,8 @@
return {
isDetail: false,
customerId: '',
shopCart: false,
fromOrder: false,
//
customerTypeList: [{
name: '正式',
@ -132,8 +134,8 @@
countries: '中国',
customerId: '',
customerName: '',
industryClassId: '',
industryId: '',
industryClassId: 16,
industryId: 83,
provinceId: '',
provinceName: '',
account: '',
@ -164,8 +166,10 @@
const { options } = pages[pages.length - 1]
this.customerId = options.customerId
this.isDetail = !!options.show
this.shopCart = options.shopCart //
this.fromOrder = options.order //
options.customerId && this.getInfo()
options.customerId ? this.getInfo() : this.getIndustry()
//
if (!this.isDetail) {
this.getSchool()
@ -315,6 +319,12 @@
} else {
addCustomer(form).then(({ customerId }) => {
uni.hideLoading()
//
if (this.fromOrder) {
uni.redirectTo({
url: `/order/orderDetail/orderDetail?customerId=${customerId}${this.shopCart ? '&shopCart=1' : ''}`
})
} else {
const that = this
uni.showModal({
title: '提示',
@ -323,13 +333,14 @@
if (res.confirm) {
//
uni.redirectTo({
url: `/order/orderDetail/orderDetail?customerId=${customerId}`
url: `/order/orderDetail/orderDetail?customerId=${customerId}${that.shopCart ? '&shopCart=1' : ''}`
})
} else if (res.cancel) {
uni.navigateBack()
}
}
})
}
}).catch(res => {})
}
},

@ -1,5 +1,6 @@
<template>
<view class="page">
<view>
<view :class="['page', {'not-auth': !per}]">
<view class="filter">
<uni-search-bar class="search" radius="30" placeholder="请输入客户名称" v-model="keyword" clearButton="auto" cancelButton="none" />
<uni-icons class="icon" custom-prefix="iconfont" type="icon-filter" size="22" color="#007eff" @click="popup = true"></uni-icons>
@ -44,6 +45,9 @@
<uni-icons class="plus" type="plus-filled" size="60" color="#007eff" @click="$util.to('../clientDetail/clientDetail')"></uni-icons>
<filter-popup :data="filterData" :form.sync="filterForm" v-model="popup" title="全部筛选" height="1104rpx" @finsh="subFinsh"></filter-popup>
</view>
<notAuth v-if="!per"></notAuth>
</view>
</template>
<script>
@ -51,6 +55,7 @@
export default {
data() {
return {
per: true, //
popup: false,
//
filterData: [
@ -115,6 +120,7 @@
}
},
onShow() {
this.per = true
this.initRole()
},
methods: {
@ -122,21 +128,51 @@
initRole() {
this.tabs = []
const auth = uni.getStorageSync('auth')
auth.includes('首页:客户:我的客户') && this.tabs.push({
auth.includes('工作台:客户:我的客户') && this.tabs.push({
name: '我的客户',
id: 0
})
auth.includes('首页:客户:团队全部客户') && this.tabs.push({
auth.includes('工作台:客户:团队全部客户') && this.tabs.push({
name: '团队全部客户',
id: 1
})
const len = this.tabs.length
if (len) {
// tab
if (len === 1) {
this.curTab = this.tabs[0].id
this.tabs = []
}
this.initList()
} else {
this.list = [
{
orderContact: '智信云',
account: '智信云师资培训班',
businessManagerName: 'python实训系统',
expireDate: '2023-08-08'
},
{
orderContact: '智信云智信云',
account: '智信云师资培训班智信云师资培训班',
businessManagerName: 'python实训系统',
expireDate: '2023-08-08'
},
{
orderContact: '智信云智信云',
account: '智信云师资培训班智信云师资培训班',
businessManagerName: 'python实训系统实训系统',
expireDate: '2023-08-08'
},
{
orderContact: '智信云智信云',
account: '智信云师资培训班智信云师资培训班',
businessManagerName: 'python实训系统',
expireDate: '2023-08-08'
},
]
this.per = false //
}
},
//
getList() {

@ -132,6 +132,11 @@
const { options } = pages[pages.length - 1]
this.customerId = options.customerId
this.customerName = options.name
//
try {
uni.removeStorageSync('orderForm')
uni.removeStorageSync('courses')
} catch (e) {}
this.initList()
},
methods: {
@ -211,8 +216,10 @@
margin-top: 20rpx;
background-color: #fff;
.item {
width: 100%;
padding: 20rpx 40rpx;
border-bottom: 1px solid #f1f1f1;
box-sizing: border-box;
}
.c-name {
font-size: 30rpx;

@ -1,11 +1,19 @@
<template>
<view class="page">
<template v-for="c in courses">
<view v-if="c.list.length" class="block">
<view v-if="c.list.length && c.list.filter(e => !e.edited).length" class="block">
<view class="type-wrap">
<view class="l-title">{{ c.name }}</view>
<view class="batch">
<input class="deadline" type="number" v-model="c.deadline" placeholder="批量输入" @change="batchDeadlineChange(c)">
<view :class="['unit', {placeholder: c.unit === ''}]" @click="batchUnitChange(c)">{{ c.unit !== '' ? units.find(e => e.id === c.unit).text : '请选择' }}</view>
</view>
<uni-icons class="arrow" type="top" size="20" color="#007EFF" @click="toggle(c)"></uni-icons>
</view>
<view v-show="!c.shrink">
<view v-for="(item, i) in c.list">
<template v-for="(item, i) in c.list">
<view v-if="!item.edited" :key="i">
<view class="pro-name">
<view class="left">
<image class="icon" :src="$util.getIcon(item)" mode="widthFix"></image>
@ -16,11 +24,11 @@
<view class="form-list">
<view class="line">
<view class="name">产品类型</view>
<view class="val">{{ productTypes.find(e => e.id === item.productType).name }}</view>
<view class="val">{{ item.typeName }}</view>
</view>
<view :class="['line req', {err: err === 'periodOfUse' + item.dataOrCourseId + item.authority}]">
<view class="name">使用期限</view>
<input class="period" type="number" v-model="item.periodOfUse" placeholder="请输入" @input="calcDate(item, !item.authority)" @change="handleErr(item, 'periodOfUse')">
<input class="period" type="number" v-model="item.periodOfUse" placeholder="请输入" @input="dateChange(item, !item.authority)" @change="handleErr(item, 'periodOfUse')">
<view class="val unit" @click="selectUnit(item)">
<text>{{ units.find(e => e.id === item.options).text }}</text>
<image class="icon" src="@/static/image/arrow-down.png" mode="widthFix"></image>
@ -28,7 +36,7 @@
</view>
<view :class="['line req', {err: err === 'startTime' + item.dataOrCourseId + item.authority}]">
<view class="name">起止日期</view>
<uni-datetime-picker type="date" v-model="item.startTime" :border="false" @change="calcDate(item)">
<uni-datetime-picker type="date" v-model="item.startTime" :border="false" @change="dateChange(item)">
<view :class="['ph', {val: item.startTime}]">
{{ item.endTime ? item.startTime + ' - ' + item.endTime : item.startTime}}
</view>
@ -45,7 +53,7 @@
</view>
<view class="line">
<view class="name">结算价</view>
<view class="val">{{ item.settlementPrice }}</view>
<view class="val">{{ item.settlementPrice && item.settlementPrice + '元' }}</view>
</view>
<view class="line">
<view class="name">折扣率</view>
@ -64,6 +72,7 @@
</view>
</view>
</view>
</template>
</view>
</view>
</template>
@ -74,14 +83,17 @@
</template>
<script>
import { getOrderOtherTime } from '@/apis/modules/order.js'
import { getOrderOtherTime, queryCitySettlementPrice, renew } from '@/apis/modules/order.js'
import { getPartnerTeamRates } from '@/apis/modules/parner.js'
import { productTypeList } from '@/apis/modules/product.js'
export default {
data() {
return {
orderType: 1,
customerId: '',
action: '',
provinceId: '',
cityId: '',
timer: null,
units: [{
text: '日',
@ -94,25 +106,12 @@
id: 2
}],
unitText: ['日', '月', '年'],
productTypes: [
{
name: '实训课程',
id: 1
},
{
name: '理论课程',
id: 0
},
{
name: '数据产品',
id: 2
}
],
courses: {} , //
orderRepeat: [],
repeatMsg: '',
err: '',
rate: ''
rate: '',
submiting: false,
}
},
onShow() {
@ -121,54 +120,94 @@
this.orderType = options.orderType
this.customerId = options.customerId
this.action = options.action
this.provinceId = options.provinceId
this.cityId = options.cityId
this.handleProduct()
this.getRate()
},
methods: {
//
handleProduct() {
async handleProduct() {
const list = uni.getStorageSync('courses')
const courses = {
practice: {
let courses = {}
//
productTypeList().then(res => {
res.typeList.forEach(e => {
courses['list' + e.typeId] = {
shrink: false,
name: '实训课程产品',
name: e.typeName,
deadline: '',
unit: '',
list: []
}
})
const { provinceId, cityId } = this
const isTrial = this.orderType == 2
list.map(async e => {
//
if (provinceId) {
const res = await queryCitySettlementPrice(e.mallId, provinceId, cityId)
if (res.mallPrice) e.settlementPriceUnit = res.mallPrice.discountRate || 0
}
//
const res = await renew({
authority: e.authority,
customerId: this.customerId,
productId: [e.mallId]
})
const item = res.orderOthers
if (item && item.length) {
let date = new Date(item[0].endTime)
date = new Date(date.setDate(date.getDate() + 1))
e.startTime = this.$util.formatDate(date, 'yyyy-MM-dd')
}
// 1
if (isTrial) {
this.calcDate(e, !e.authority)
}
courses['list' + e.typeId].list.push(e)
})
this.courses = courses
}).catch(e => {})
},
theory: {
shrink: false,
name: '理论课程产品',
list: []
//
batchDeadlineChange (c) {
c.list.map(e => {
e.periodOfUse = c.deadline
this.calcDate(e, !e.authority)
})
},
data: {
shrink: false,
name: '数据产品',
list: []
//
batchUnitChange(c) {
const that = this
uni.showActionSheet({
title: '标题',
itemList: that.unitText,
success: ({ tapIndex }) => {
if (tapIndex !== '') {
c.unit = tapIndex
c.list.map(e => {
e.options = tapIndex
that.calcDate(e, !e.authority)
})
}
}
// 3push(0-> 1- 2 )
list.map(e => {
const type = e.productType
!type ?
courses.theory.list.push(e) :
type === 1 ?
courses.practice.list.push(e) :
courses.data.list.push(e)
})
this.courses = courses
try {
uni.removeStorageSync('courses')
} catch (e) {}
},
//
selectUnit(item) {
const that = this
uni.showActionSheet({
title: '标题',
itemList: that.unitText,
success: ({ tapIndex }) => {
if (tapIndex !== '') {
item.options = tapIndex
that.calcDate(item)
}
}
})
},
showUnit(i) {
@ -188,12 +227,15 @@
}
})
},
// 使
calcDate(row, fromData) {
console.log('row=>',row)
console.log('fromData=>',fromData)
// 使
dateChange(row, fromData) {
clearTimeout(this.timer)
this.timer = setTimeout(() => {
this.calcDate(row, fromData)
}, 500)
},
// 使
calcDate(row, fromData) {
const { periodOfUse, options } = row
let optionsData = 0
if (periodOfUse) {
@ -207,7 +249,6 @@
}
let time = new Date(row.startTime).getTime()
let endTime = time + optionsData
row.endTime = time + optionsData
let dt = new Date(endTime)
row.endTime = (dt.getFullYear()) + "-" + (dt.getMonth() + 1) + "-" + (dt.getDate())
let endYear = endTime - time
@ -230,12 +271,13 @@
const date = new Date(row.startTime)
const orderRepeat = this.orderRepeat
getOrderOtherTime({
authority: row.authority,
customerId: this.customerId,
id: cId,
startTime: this.$util.formatDate(date, 'yyyy-MM-dd'),
endTime: row.endTime
}).then(res => {
orderRepeat.includes(cId) && orderRepeat.splice(orderRepeat.findIndex(e => e === cId), 1)
orderRepeat.includes(cId) && orderRepeat.splice(orderRepeat.findIndex(e => e == cId), 1)
if (res.endTime) {
let time = new Date(res.endTime)
time = new Date(time.setDate(time.getDate() + 1))
@ -248,20 +290,17 @@
}
//
this.calcDiscount(row)
}, 500)
},
//
dealSettlePrice(row) {
// 0
console.log('row=>', row)
if (this.orderType == 2) {
// 0
if (this.orderType != 1) {
row.settlementPrice = 0
row.serviceFee = 0
} else {
const unit = row.options // 使
const useUnit = row.periodOfUse // 使
let sPrice = ''
if (row.settlementMethod == 0) {
// **/**(1)
const priceUnit = row.settlementPriceUnit
sPrice = ((!unit ?
@ -271,12 +310,8 @@
priceUnit * useUnit) * (row.authority ?
1 :
row.accountNum)).toFixed((2))
} else {
// *
sPrice = (row.finalPrice * row.businessProportion / 100).toFixed((2))
}
row.settlementPrice = this.$util.handleNaN(sPrice)
// *10%
//
if (row.settlementPrice) {
row.serviceFee = (row.finalPrice * (this.rate / 100)).toFixed(2)
}
@ -287,7 +322,6 @@
getPartnerTeamRates({
teamId: uni.getStorageSync('team').teamId
}).then(({ teamRates }) => {
console.log('teamRates=>',teamRates)
this.rate = teamRates.annualMarketingFee || 0
}).catch(res => {})
},
@ -341,14 +375,14 @@
},
//
submit() {
const courses = this.courses
if (this.submiting) return false
const { courses } = this
const list = []
let msg = ''
// push便
for (const i in courses) {
list.push(...courses[i].list)
}
console.log(11, list)
//
for (const i in list) {
const e = list[i]
@ -358,6 +392,11 @@
msg = '请输入使用期限!'
break
}
if (e.options === '') {
this.err = 'accountNum' + suf
msg = '请选择期限!'
break
}
if (!e.startTime) {
this.err = 'startTime' + suf
msg = '请选择起止日期!'
@ -374,11 +413,19 @@
break
}
}
console.log(33, this.err)
if (msg) return this.$util.errMsg(msg)
if (this.orderRepeat.length) return this.$util.errMsg(this.repeatMsg) //
this.submiting = true
uni.showLoading({
title: '加载中'
})
list.forEach(e => {
e.edited = 1 //
})
uni.setStorageSync('courses', this.courses)
uni.navigateBack()
uni.redirectTo({
url: `../orderDetail/orderDetail?edited=1`
})
},
}
}
@ -395,11 +442,30 @@
.l-title {
margin: 0 24rpx;
}
.type-wrap {
display: flex;
justify-content: space-between;
align-items: center;
}
.batch {
display: inline-flex;
align-items: center;
.deadline, .unit {
font-size: 28rpx;
color: #333;
}
.deadline {
width: 130rpx;
}
.unit {
min-width: 80rpx;
text-align: center;
&.placeholder {
color: #797979;
}
}
}
.arrow {
position: absolute;
top: 30rpx;
right: 30rpx;
}
.pro-name {
display: flex;

File diff suppressed because it is too large Load Diff

@ -5,8 +5,10 @@
<uni-icons class="icon" custom-prefix="iconfont" type="icon-filter" size="22" color="#007eff" @click="popup = true"></uni-icons>
</view>
<ul class="tab">
<ul class="tab-wrap">
<scroll-view scroll-x :scroll-left="scrollLeft" class="tab">
<li v-for="(tab, i) in tabs" :class="{active: curTab === tab.id}" @click="tabChange(tab)">{{ tab.name }}</li>
</scroll-view>
</ul>
<ul v-if="list.length" class="list">
@ -37,6 +39,7 @@
</template>
<script>
import { productCategoryList } from '@/apis/modules/product.js'
import { getProductsSubscribedByCustomers } from '@/apis/modules/client.js'
import product from '@/config/product.js'
export default {
@ -89,22 +92,6 @@
name: '全部',
id: ''
},
{
name: '实训课程',
id: 1
},
{
name: '理论课程',
id: 0
},
{
name: '数据产品',
id: 3
},
{
name: '职站增值模块',
id: 4
}
],
searchTimer: null,
orderStatus: '',
@ -134,6 +121,7 @@
onShow() {
const pages = getCurrentPages()
this.customerId = pages[pages.length - 1].options.customerId
this.getTypes()
this.getList()
},
methods: {
@ -209,6 +197,16 @@
uni.hideLoading()
})
},
//
getTypes() {
productCategoryList().then(res => {
res.classificationList.forEach(e => {
e.id = e.classificationId
e.name = e.classificationName
})
this.tabs.push(...res.classificationList)
}).catch(e => {})
},
//
subFinsh(val) {
const { orderStatus, productStatus } = val
@ -239,6 +237,15 @@
.filter {
margin-bottom: 10px;
}
.tab-wrap {
.tab {
width: 100%;
white-space: nowrap;
li {
display: inline-block;
}
}
}
.list {
li {
padding: 0 24rpx;

@ -0,0 +1,107 @@
<template>
<view class="wrap">
<view class="title">用户隐私协议</view>
<view class="text">
我们非常重视对用户隐私的保护您在使用我们的服务时我们可能会收集和使用您的相关信息我们希望通过本用户隐私条款向您说明在使用我们的服务时我们如何收集使用披露存储这些信息本用户隐私条款系本平台保护用户个人隐私的承诺与您所使用的服务息息相关希望您仔细阅读
个人资料的收集
您在注册账户或使用我们的服务时向我们提供的相关个人信息例如电话号码电子邮件等您通过我们的服务向其他方提供的共享信息以及您使用我们的服务时所储存的信息我们收集数据是根据您与我们的互动和您所做出的选择包括您的隐私设置以及您使用的产品和功能我们收集的数据可能包括SDK/API/JS代码版本浏览器互联网服务提供商IP地址平台时间戳应用标识符应用程序版本应用分发渠道独立设备标识符iOS广告标识符IDFA)安卓广告主标识符网卡MAC地址国际移动设备识别码IMEI设备型号终端制造厂商终端设备操作系统版本会话启动/停止时间语言所在地时区和网络状态WiFi等硬盘CPU和电池使用情况等
个人资料的获取
您使用服务时我们可能收集如下信息
1日志信息指您使用我们的服务时系统可能通过cookieswebbeacon或其他方式自动采集的技术信息包括
1设备或软件信息例如您的移动设备网页浏览器或用于接入我们服务的其他程序所提供的配置信息您的IP地址和移动设备所用的版本和设备识别码等在使用我们服务时搜索或浏览的信息例如您使用的网页搜索词语访问的社交媒体页面url地址以及您在使用我们服务时浏览或要求提供的其他信息和内容详情
2有关您曾使用的移动应用APP和其他软件的信息以及您曾经使用该等移动应用和软件的信息
3您通过我们的服务进行通讯的信息例如曾通讯的账号以及通讯时间数据和时长
4您通过我们的服务分享的内容所包含的信息元数据例如拍摄或上传的共享照片或录像的日期时间或地点等
2位置信息指您开启设备定位功能并使用我们基于位置提供的相关服务时收集的有关您位置的信息包括
1您通过具有定位功能的移动设备使用我们的服务时通过GPS或WiFi等方式收集的您的地理位置信息
2您或其他用户提供的包含您所处地理位置的实时信息例如您提供的账户信息中包含的您所在地区信息
3您可以通过关闭定位功能停止对您的地理位置信息的收集
4我们的产品集成友盟+SDK友盟+SDK需要收集您的设备Mac地址唯一设备识别码IMEI/androidID/IDFA/OPENUDID/GUIDSIM卡IMSI信息以提供统计分析服务
APP涉及用户信息使用的SDK相关情况逐项列举详情如下
1华为推送/小米推送/vivo推送/oppo推送:
SDK类型推送通知
SDK描述用于实现消息推送(或其他推送)功能SDK
使用业务场景向用户推荐活动和提醒
收集个人信息的类型设备信息地理位置网络信息
设备信息设备标识符(IMEIIDFAAndroidIDMACOAID等相关信息)应用信息(应用崩溃信息通知开关状态软件列表等相关信息)设备参数及系统信息(设备类型设备型号操作系统及硬件相关信息)
网络信息IP地址WiFi信息基站信息等相关信息
使用目的/理由向用户推荐活动和提醒
2微信开放平台
SDK类型社交
SDK描述微信分享功能
SDK使用业务场景微信分享
SDK所需用户信息字段软件安装列表设备型号MAC地址IMEI号IMSI系统版本手机型号
使用目的/理由APP分享音频视频图片活动至微信客户端
3友盟分享
SDK类型社交
SDK描述分享功能
SDK使用业务场景分享到微信
SDK所需用户信息字段设备型号系统版本号手机型号分享信息
使用目的/理由APP分享图片活动至微信客户端
4友盟统计
SDK类型数据统计
SDK描述提供数据统计数据收集数据分析服务
SDK使用业务场景日活路径分析
SDK所需用户信息字段设备型号系统版本号手机型号发布渠道页面code数据
使用目的/理由数据收集进行数据分析提升产品体验
5Bugly
SDK类型性能监测
SDK描述提供移动端应用运行时崩溃卡顿监控服务
SDK使用业务场景对APP进行性能监控提升产品使用体验
SDK所需用户信息字段设备型号MAC地址IMEI号系统版本手机型号
使用目的/理由监控app使用过程中的奔溃信息分析提升用户体验
个人资料的披露
我们将采取合理的安全手段保护用户提供的个人及单位信息在未得到用户许可之前本平台不会擅自将用户信息披露给任何无关的第三方但涉及下列情形之一的除外
1法律强制规定或司法行政机关依照法定程序要求提供
2为保护用户的生命财产安全或为公共安全之需要
3为了保护本平台其他用户的合法权益或财产
4您出现违反中国有关法律法规或者本平台相关协议规则的情况需要向第三方披露
5其他特殊或紧急情况
由于用户对自身信息保密不当从而导致用户资料的泄露或由于网络线路黑客攻击计算机病毒等原因造成的资料泄露丢失被盗用或被篡改等本平台不承担任何责任
Cookies技术的使用
我们收集信息是为了向您提供更好更优更个性化的服务本公司将以合法的方式收集必要的用户个人资料本平台有可能收集的个人资料包括用户姓名身份证号地址电话号码电子邮件等信息用户在本平台注册时须依注册内容之提示提供用户本人及单位的真实准确完整信息并保证个人及单位资料的及时更新因用户提供个人及单位信息不准确不完整或未及时更新而可能遭受的任何损害本公司不承担任何责任
个人资料的存储
我们收集的有关您的信息和资料将保存在我们及其关联公司的服务器上
个人资料的保护
为保障您的信息安全我们将采取各种合理的安全措施来保护您的信息使您的信息不会被泄漏毁损或者丢失我们对可能接触到您的信息的员工也采取了严格管理包括但不限于根据岗位的不同采取不同的权限控制与他们签署保密协议监控他们的操作情况等措施我们会按现有技术提供相应的安全措施来保护您的信息提供合理的安全保障尽力做到使您的信息不被泄漏毁损或丢失您的账户均有安全保护功能请妥善保管您的账户及密码信息我们将通过向其它服务器备份对用户密码进行加密等安全措施确保您的信息不丢失不被滥用和变造
未成年人保护
我们重视未成年人的个人信息保护如您为未成年人建议您请您的监护人阅读本隐私权条款并在征得您的监护人同意的前提下使用我们的服务或向我们提供信息
联系我们
您可通过发送邮件至service@huorantech.cn与我们沟通我们将在15天内回复您的请求
</view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
</script>
<style scoped lang="scss">
.wrap {
padding: 30rpx;
.title {
margin-bottom: 30rpx;
font-size: 40rpx;
text-align: center;
}
.text {
font-size: 30rpx;
line-height: 1.6;
white-space: pre-wrap;
}
}
</style>

@ -0,0 +1,487 @@
<template>
<view class="wrap">
<view class="banner-wrap bg-wh">
<view class="pic-wrap">
<image class="pic" :src="form.mall.coverDrawing" mode="widthFix"></image>
<view class="pro-title">{{ form.mall.productName }}</view>
</view>
<view class="fields">
<view class="field">
<image class="icon" src="@/static/image/product/1.png"></image>
市场建议价{{ form.mall.marketUnitPrice || '' }}/
</view>
<view class="field">
<image class="icon" src="@/static/image/product/2.png"></image>
产品类型{{ form.goodsRes.typeName || '' }}
</view>
</view>
</view>
<view class="detail">
<ul class="tabs">
<li :class="{active: curTab === 0}" @click="tabChange(0)">详情介绍</li>
<li :class="{active: curTab === 1, disabled: !form.interfaceDiagram}" @click="tabChange(1)">界面图</li>
<li :class="{active: curTab === 2, disabled: !form.mallAnnex || !form.mallAnnex.length}" @click="tabChange(2)">参数</li>
</ul>
<view class="title">
<image class="icon" src="@/static/image/product/3.png"></image>
产品详情
</view>
<view class="texts">
<view class="line">
<text class="name">产品简介</text>
<text class="val">{{ form.mall.productIntroduction }}</text>
</view>
<view class="line">
<text class="name">适用专业</text>
<text class="val">{{ form.goodsRes.professionalName }}</text>
</view>
<view v-if="form.mall.courseHours" class="line">
<text class="name">预计课时</text>
<text class="val">{{ form.mall.courseHours }}</text>
</view>
<view v-if="form.mall.matchingCourse" class="line">
<text class="name">匹配课程</text>
<text class="val">{{ form.mall.matchingCourse }}</text>
</view>
<view v-if="form.mall.applicationScenario" class="line">
<text class="name">适用场景</text>
<text class="val">{{ form.mall.applicationScenario }}</text>
</view>
<view class="line">
<text class="name">详情介绍</text>
<mp-html class="des-html" :tag-style="mpStyle" :content="form.mall.detailedIntroduction"/>
</view>
</view>
</view>
<view v-if="form.interfaceDiagram" class="detail" id="pics">
<view class="title mb">
<image class="icon" src="@/static/image/product/4.png"></image>
产品界面图
</view>
<uni-swiper-dot :info="form.interfaceDiagram.length > 1 ? form.interfaceDiagram : 0" field="content" mode="round" :dotsStyles="dotsStyles">
<swiper class="swiper-box" autoplay>
<swiper-item v-for="(pic, i) in form.interfaceDiagram" :key="i">
<image class="pic" mode="widthFix" :src="pic"></image>
</swiper-item>
</swiper>
</uni-swiper-dot>
</view>
<view v-if="form.mallAnnex && form.mallAnnex.length" class="detail" id="annex">
<view class="title-wrap">
<view class="title">
<image class="icon" src="@/static/image/product/5.png"></image>
产品参数
</view>
<view v-if="auth('产品:下载')" class="download" @click="downloadAll">
下载全部
<image class="icon" src="@/static/image/product/6.png"></image>
</view>
</view>
<view v-if="form.mallAnnex" class="files">
<view v-for="(file, i) in form.mallAnnex" :key="i" class="file">
<view class="text">
<image class="icon" src="@/static/image/product/ppt.png"></image>
{{ file.fileName }}
</view>
<view v-if="auth('产品:下载')" class="download" @click="download(file)">下载</view>
</view>
</view>
</view>
<view class="footer">
<view v-if="auth('产品:购物车')" class="shop" @click="$util.to('../shopCart/shopCart')">
<uni-badge size="small" :text="shopCartTotal" absolute="topRight" type="error">
<image class="icon" src="@/static/image/product/shop.png" mode="widthFix"></image>
</uni-badge>
<view>购物车</view>
</view>
<view class="btns">
<view v-if="auth('产品:加入购物车')" class="btn" @click="addShop">加入购物车</view>
<view v-if="auth('产品:下单')" class="btn order" @click="order">下单</view>
</view>
</view>
</view>
</template>
<script>
import { detailsOfGoods, addToShoppingCart, shoppingCartList } from '@/apis/modules/product.js'
export default {
data() {
return {
id: '',
curTab: 0,
tabs: [
{
name: '详情介绍',
id: 0
},
{
name: '界面图',
id: 1
},
{
name: '参数',
id: 2
}
],
form: {
classificationIds: [],
interfaceDiagram: [],
mall: {
coverDrawing: ''
},
goodsRes: {},
mallAnnex: []
},
shopCartTotal: 0,
dotsStyles: {
backgroundColor: 'rgba(83, 200, 249,0.3)',
border: '1px rgba(83, 200, 249,0.3) solid',
color: '#fff',
selectedBackgroundColor: 'rgba(83, 200, 249,0.9)',
selectedBorder: '1px rgba(83, 200, 249,0.9) solid'
},
mpStyle: {
p: 'font-size: 25rpx !important;font-family: Microsoft Yahei !important;font-weight: 400 !important;color: #333 !important;',
span: 'font-size: 25rpx !important;font-family: Microsoft Yahei !important;font-weight: 400 !important;color: #333 !important;'
}
}
},
onShow() {
const pages = getCurrentPages()
const { options } = pages[pages.length - 1]
this.id = options.id
this.getInfo()
this.getShopCart()
//
try {
uni.removeStorageSync('orderForm')
uni.removeStorageSync('courses')
} catch (e) {}
},
methods: {
//
getInfo() {
uni.showLoading({
title: '加载中'
})
detailsOfGoods(this.id).then(res => {
const e = res.orderDetails
e.mall.productIntroduction = this.$util.removeTag(e.mall.productIntroduction)
// e.mall.detailedIntroduction = this.$util.removeTag(e.mall.detailedIntroduction)
this.form = e
const pics = this.form.mall.interfaceDiagram
if (pics) {
this.form.interfaceDiagram = pics.split(',')
// this.tabs.push({
// name: '',
// id: 1
// })
}
// this.form.mallAnnex && this.form.mallAnnex.length && this.tabs.push({
// name: '',
// id: 2
// })
uni.hideLoading()
}).catch(e => {
uni.hideLoading()
})
},
//
getShopCart() {
shoppingCartList({
pageNum: 1,
pageSize: 1000,
}).then(({ data }) => {
this.shopCartTotal = data.total
}).catch(e => {})
},
// tab
tabChange(id) {
if ((id === 1 && !this.form.interfaceDiagram) || (id === 2 && (!form.mallAnnex || !form.mallAnnex.length))) return false
this.curTab = id
id == 1 && uni.pageScrollTo({
selector: '#pics',
})
id == 2 && uni.pageScrollTo({
selector: '#annex',
})
},
//
downloadAll() {
const fileName = []
const urls = []
this.form.mallAnnex.forEach(e => {
fileName.push(e.fileName)
urls.push(e.filePath)
})
uni.setStorageSync('files', {
copyWriting: this.form.mall.productName,
fileName,
urls
})
this.$util.to(`/team/send/send`)
},
//
download(item) {
uni.setStorageSync('files', {
copyWriting: this.form.mall.productName,
fileName: [item.fileName],
urls: [item.filePath]
})
this.$util.to(`/team/send/send`)
},
//
addShop() {
uni.showLoading({
title: '加载中'
})
addToShoppingCart({
mallId: this.id
}).then(res => {
this.$util.sucMsg('加购成功')
uni.hideLoading()
this.getShopCart()
}).catch(e => {
uni.hideLoading()
})
},
//
order() {
const { mall, typeIds } = this.form
const classificationId = this.form.classificationIds[0]
const authority = this.$util.getOrderType(classificationId)
//
uni.setStorageSync('courses', [{
dataOrCourseId: mall.associatedProduct, // id
mallId: mall.mallId,
productName: mall.productName, //
periodOfUse: '', // 使
startTime: this.$util.formatDate(new Date(), 'yyyy-MM-dd'), //
endTime: '', //
remainingPeriod: '', //
marketValue: '', //
marketPrice: mall.marketUnitPrice, //
finalPrice: 0, //
finalValue: 0, //
discountRate: '0%', //
accountNum: 1, //
totalAmount: '', //
isEnable: 0, // 10
ship: 0, // 01
authority, //
options: 2,
miniProgramPictureAddress: mall.appletIcon || '', //
settlementPrice: 0, //
settlementPriceUnit: 0, //
serviceFee: 0, //
typeId: typeIds && typeIds.length ? typeIds[0] : '',
classificationId,
}])
this.$util.to(`../orderDetail/orderDetail?shopCart=1`)
}
}
}
</script>
<style scoped lang="scss">
.wrap {
padding-bottom: 140rpx;
}
.banner-wrap {
width: 100%;
border-radius: 0px 0px 20px 20px;
.pic-wrap {
padding: 20rpx 32rpx;
border-bottom: 1px solid #E2E2E2;
}
.pic {
width: 100%;
}
.pro-title {
margin-top: 22rpx;
font-size: 30rpx;
font-weight: 600;
color: #333;
}
.fields {
padding: 26rpx 32rpx;
}
.field {
display: flex;
align-items: center;
font-size: 28rpx;
color: #333;
&:first-child {
margin-bottom: 22rpx;
}
.icon {
width: 36rpx;
height: 36rpx;
margin-right: 12rpx ;
}
}
}
.tabs {
display: flex;
margin-bottom: 32rpx;
li {
width: 33.33%;
text-align: center;
font-size: 28rpx;
color: #333;
white-space: nowrap;
}
.active {
color: #007EFF;
&:after {
content: '';
display: block;
width: 40rpx;
height: 8rpx;
margin: 18rpx auto 0;
border-radius: 4px;
background-color: #007EFF;
}
}
.disabled {
color: #b3b3b3;
}
}
.detail {
padding: 34rpx 32rpx;
margin: 16rpx 0;
border-radius: 20px;
background-color: #fff;
.title-wrap {
display: flex;
justify-content: space-between;
align-items: center;
.download {
display: inline-flex;
align-items: center;
padding: 7rpx 16rpx;
font-size: 24rpx;
color: #007EFF;
text-align: center;
background-color: #F2F8FF;
.icon {
width: 30rpx;
height: 30rpx;
margin-left: 4rpx;
}
}
}
.title {
display: flex;
align-items: center;
font-size: 30rpx;
font-weight: 600;
color: #333 ;
.icon {
width: 36rpx;
height: 36rpx;
margin-right: 11rpx;
}
&.mb {
margin-bottom: 32rpx;
}
}
.texts {
margin-top: 32rpx;
}
.line {
display: flex;
margin-bottom: 18rpx;
line-height: 40rpx;
text {
font-size: 26rpx;
color: #333;
}
.name {
font-weight: 600;
white-space: nowrap;
}
.des-html {
width: calc(100% - 140rpx);
font-size: 28rpx !important;
}
.rich-text-content span {
font-size: 28rpx;
color: #f00;
}
}
.swiper-box {
min-height: 250px;
}
.pic {
width: 100%;
}
.files {
margin-top: 34rpx;
.file {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24rpx;
.text {
display: inline-flex;
align-items: center;
font-size: 26rpx;
color: #333;
}
.icon {
width: 36rpx;
height: 36rpx;
margin-right: 14rpx;
}
.download {
font-size: 26rpx;
color: #007EFF;
}
}
}
}
.footer {
position: fixed;
bottom: 0;
left: 0;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
padding: 24rpx 32rpx 24rpx 73rpx;
background-color: #fff;
box-sizing: border-box;
.shop {
text-align: center;
font-size: 24rpx;
color: #333;
.icon {
width: 56rpx;
}
}
.btns {
display: inline-flex;
.btn {
width: 229rpx;
line-height: 80rpx;
text-align: center;
font-size: 32rpx;
color: #333;
background-color: #E5EEF7;
border-radius: 100px 0px 0px 100px;
}
.order {
color: #fff;
background-color: #007EFF;
border-radius: 0px 100px 100px 0px;
}
}
}
</style>

@ -0,0 +1,399 @@
<template>
<view>
<view class="filter">
<uni-search-bar class="search" radius="30" placeholder="请输入产品名称" v-model="keyword" clearButton="auto" cancelButton="none" />
<uni-icons class="icon" custom-prefix="iconfont" type="icon-filter" size="22" color="#007eff" @click="popup = true"></uni-icons>
</view>
<ul class="tab-wrap">
<view class="tab">
<li :class="{active: curTab === ''}" @click="tabChange('')">全部</li>
</view>
<scroll-view scroll-x :scroll-left="scrollLeft" class="tab tab-scroll">
<li v-for="(tab, i) in tabs" :key="i" :class="{active: curTab === tab.value}" @click="tabChange(tab.value)">{{ tab.title }}</li>
</scroll-view>
</ul>
<view class="tags">
<view v-if="categoryName" class="tag" @click="delCategory">
{{ categoryName }}
<uni-icons class="icon" type="closeempty" size="15" color="#007EFF"></uni-icons>
</view>
<view v-if="productTypeName" class="tag" @click="delProductType">
{{ productTypeName }}
<uni-icons class="icon" type="closeempty" size="15" color="#007EFF"></uni-icons>
</view>
<view v-if="form.selection" class="tag" @click="delSelection">
官方精选
<uni-icons class="icon" type="closeempty" size="15" color="#007EFF"></uni-icons>
</view>
<view v-if="tagName" class="tag" @click="delTag">
{{ tagName }}
<uni-icons class="icon" type="closeempty" size="15" color="#007EFF"></uni-icons>
</view>
</view>
<ul class="list">
<li v-for="(item, i) in list" :key="i" @click="toDetail(item)">
<view class="pro-name">
<image class="icon" :src="$util.getIcon(item)"></image>
{{ item.productName }}
</view>
<view class="info">
<view class="line">
<text class="name">产品简介</text>
<view class="val ell-wrap">
<view class="ell">{{ item.productIntroduction }}</view>
</view>
</view>
<view class="line">
<text class="name">产品类型</text>
<text class="val">{{ item.typeName }}</text>
</view>
<view class="line">
<text class="name">适用专业</text>
<text class="val">{{ item.professionalName }}</text>
</view>
<view class="line">
<text class="name">市场建议单价</text>
<text class="val">{{ item.marketUnitPrice }}/</text>
</view>
</view>
</li>
</ul>
<view v-if="auth('产品:购物车')" class="plus">
<uni-badge size="small" :text="total" absolute="topRight" type="error">
<image class="icon" src="@/static/image/product/shop-blue.png" mode="widthFix" @click="$util.to('../shopCart/shopCart')"></image>
</uni-badge>
</view>
<filter-popup ref="filter" showCategory :data="filters" :form.sync="filterForm" v-model="popup" title="全部筛选" height="1104rpx" @finsh="subFinsh"></filter-popup>
</view>
</template>
<script>
import { tagsList, listOfGoods, productTypeList, shoppingCartList } from '@/apis/modules/product.js'
export default {
data() {
return {
popup: false,
//
filters: [
{
children: false,//
title: "产品类型",
key: "productType", //
keyValue: "value", //
isRadio: true, //
data: [],
},
{
children: false,//
title: "官方精选",
key: "selection", //
keyValue: "value", //
data: [
{
value: 1,
title: '官方精选'
}
],
},
{
children: false,//
title: "产品标签",
key: "tagId", //
keyValue: "value", //
isRadio: true, //
data: [],
},
],
filterForm: {
productType: [],
selection: [],
tagId: []
},
form: {
categoryId: '',
professionalCategoryId: '',
professionalId: '',
productType: '',
selection: '',
tagId: ''
},
tagId: '',
curTab: '',
tabs: [],
scrollLeft: 0,
reachBottom: 0, // 0->,1->,-1->
status: 'more', // more|loading|noMore
searchTimer: null,
sort: 0,
keyword: '',
list: [],
page: 1,
pageSize: 10,
total: 0,
cartNum: '',
productTypeName: '',
tagName: '',
categoryName: '',
}
},
watch: {
keyword () {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.initList()
}, 500)
}
},
//
onPullDownRefresh() {
this.initList()
setTimeout(() => {
uni.stopPullDownRefresh()
}, 1500)
},
//
onReachBottom() {
if (this.reachBottom >= 0) {
this.reachBottom = 1
this.status = 'loading'
this.getList()
}
},
onShow() {
const pages = getCurrentPages()
const { options } = pages[pages.length - 1]
const { tagId, tagsName } = options
this.form.tagId = +tagId || ''
if (tagId) {
this.filterForm.tagId = [+tagId]
// this.tagName = tagsName
}
this.keyword = options.keyword || ''
this.page = 1
this.getList()
this.getFilter()
this.getShopCart()
},
methods: {
getList() {
listOfGoods({
pageNum: this.page,
pageSize: this.pageSize,
sort: 0,
isShelves: 0,
hotTag: this.form.tagId ? 2 : 1,
...this.form,
productName: this.keyword,
productType: this.curTab
}).then(({ page }) => {
// list
const list = page.records
list.map(e => {
e.productIntroduction = this.$util.removeTag(e.productIntroduction)
})
this.list = this.reachBottom > 0 ? [...this.list, ...list] : list
this.page++ // page+1
const noMore = this.list.length === page.total //
this.status = noMore ? 'noMore' : 'more' // noMore
this.reachBottom = noMore ? -1 : 0 // -1
}).catch(e => {})
},
initList() {
this.page = 1
this.reachBottom = 0
this.getList()
},
//
getShopCart() {
shoppingCartList({
pageNum: 1,
pageSize: 1000,
}).then(({ data }) => {
this.total = data.total
}).catch(e => {})
},
//
getFilter() {
//
productTypeList().then(res => {
res.typeList.forEach(e => {
e.value = e.typeId
e.title = e.typeName
})
this.tabs = res.typeList
this.filters[0].data = res.typeList
}).catch(e => {})
//
tagsList().then(res => {
res.tagsList.forEach(e => {
e.value = e.tagsId
e.title = e.tagsName
})
this.filters[2].data = res.tagsList
}).catch(e => {})
},
//
subFinsh(val) {
const { productType, selection, tagId, categoryId, professionalCategoryId, professionalId, categoryName } = val
this.form = {
categoryId: categoryId || '',
professionalCategoryId: professionalCategoryId || '',
professionalId: professionalId || '',
productType: productType.length ? productType[0] : '',
selection: selection.length ? selection[0] : '',
tagId: tagId.length ? tagId[0] : ''
}
this.categoryName = categoryName || ''
this.productTypeName = this.form.productType ? this.filters[0].data.find(e => e.value == this.form.productType).title : ''
this.tagName = this.form.tagId ? this.filters[2].data.find(e => e.value == this.form.tagId).title : ''
this.initList()
},
//
delCategory() {
this.$refs.filter.category = []
this.$refs.filter.categoryName = ''
this.$refs.filter.categoryId = ''
this.$refs.filter.professionalCategoryId = ''
this.$refs.filter.professionalId = ''
this.form.categoryId = ''
this.form.professionalCategoryId = ''
this.form.professionalId = ''
this.categoryName = ''
this.initList()
},
//
delProductType() {
this.filterForm.productType = []
this.form.productType = ''
this.productTypeName = ''
this.initList()
},
//
delSelection() {
this.filterForm.selection = []
this.form.selection = ''
this.initList()
},
//
delTag() {
this.filterForm.tagId = []
this.form.tagId = ''
this.tagName = ''
this.initList()
},
// tab
tabChange(id) {
this.curTab = id
this.initList()
},
//
toDetail(item) {
console.log(44, item)
this.$util.to(`../productDetail/productDetail?id=${item.mallId}`)
},
}
}
</script>
<style scoped lang="scss">
.tab-wrap {
display: flex;
.tab-scroll {
width: calc(100% - 100rpx);
white-space: nowrap;
li {
display: inline-block;
}
}
}
.tags {
display: flex;
align-items: center;
flex-wrap: wrap;
padding: 0 24rpx;
.tag {
display: inline-flex;
align-items: center;
padding: 10rpx 14rpx;
margin: 0 20rpx 16rpx 0;
font-size: 28rpx;
color: #007EFF;
background-color: #fff;
border-radius: 4px;
}
.icon {
margin-left: 6rpx;
}
}
.list {
li {
padding: 0 24rpx;
margin: 16rpx 24rpx;
background-color: #fff;
border-radius: 16rpx;
}
.pro-name {
display: flex;
align-items: center;
padding: 18rpx 0;
font-size: 30rpx;
font-weight: 600;
color: #333;
border-bottom: 1px solid #E6E8ED;
.icon {
width: 58rpx;
min-width: 58rpx;
height: 58rpx;
margin-right: 20rpx;
border-radius: 4px;
}
}
.info {
padding: 12rpx 0;
}
.line {
display: flex;
padding: 12rpx 0;
}
.name {
margin-right: 10rpx;
font-size: 28rpx;
color: #999;
}
.val {
max-width: 70%;
font-size: 28rpx;
color: #333;
}
.ell-wrap {
display: inline-flex;
align-items: center;
}
.ell {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.toggle {
margin-left: 10rpx;
white-space: nowrap;
font-size: 24rpx;
color: #0e92ef;
}
}
.plus {
bottom: 140rpx;
right: 60rpx;
.icon {
width: 102rpx;
}
}
</style>

@ -0,0 +1,88 @@
<template>
<view class="wrap">
<view class="title">服务协议</view>
<view class="text">我们提醒您在使用本平台的各项服务之前请您务必仔细阅读并透彻理解本声明如果您使用本平台服务的您的使用行为将被视为对本声明全部内容的认可若您不同意本声明中的全部或部分内容您应立即停止使用本平台服务</view>
<view class="text">知识产权声明</view>
<view class="text">1本平台内的所有产品技术软件程序数据及其他信息包括但不限于文字图像图片照片音频视频图表色彩版面设计电子文档的所有权利包括但不限于域名版权商标权专利权商业秘密及其他所有相关权利均归我们公司或其关联公司所有未经我司的许可任何人不得擅自使用</view>
<view class="text">2本平台的Logo等文字图形及其组合以及其他标识徵记产品和服务名称均为我司及其关联公司的注册商标未经我们的书面授权任何人不得以任何方式使用或作其他处理也不得向他人表明您有权使用或作其他处理</view>
<view class="text">3如果本平台内容无权利声明并不代表本平台对其不享有权利也不意味着本平台不主张权利您应根据诚信原则尊重该等内容的合法权益并进行合法使用您不得以任何方式修改复制公开展示公布或分发这些材料或者以其他方式把它们用于任何公开或商业目的禁止以任何目的把这些材料用于其他任何网站或其他平面媒体或网络计算机环境</view>
<view class="text">服务声明</view>
<view class="text">1我们向用户提供的所有产品或新增加的服务功能均适用本声明条款之规范</view>
<view class="text">2本平台所有信息软件均为按现状提供不带有任何明示或暗示的担保或条件包括但不限于准确性及时性和非侵权的默示担保或保证</view>
<view class="text">3本平台有权根据业务需要修订本服务声明并以平台公告的形式进行更新不再单独通知予您经修订的服务声明一经本平台公布即产生效力如您不同意相关修订请您立即停止使用本平台服务如您继续使用服务则将视为您已接受经修订的条款当您与本平台发生争议时应以最新的条款为准</view>
<view class="text">平台的使用</view>
<view class="text">1除法定许可或征得本公司同意本平台的信息及其任何组成部分不得被重新编辑复制抄袭或为任何未经本公司允许的商业目的所使用如果本公司确定用户行为违法或有损本平台和本公司的合法权益本公司将采取相关法律措施包括但不限于拒绝提供服务冻结或删除用户账号等</view>
<view class="text">2如果您从本站下载软件在使用软件时要遵守该软件附带的软件许可协议中所有的许可条款在您阅读并接受软件许可协议的各项条款之前不得下载或安装这一软件如果在适用的许可条款或协议中已经禁止复制或再分发这些软件您须遵照执行</view>
<view class="text">信息发布条款</view>
<view class="text">平台信息发布</view>
<view class="text">本平台所发布的信息由所有权人及其关联公司遵循真实原则发布发布人对平台信息不作任何保证或其它担保包括适销性适合于特定目的没有计算机病毒或不侵犯知识产权的保证</view>
<view class="text">用户信息发布</view>
<view class="text">1平台用户有权在本平台允许用户发布信息的版块发布信息用户在本平台发表或投递的信息回复必须遵守中华人民共和国各项法律法规条例不发布或链接有关政治破坏系统淫秽色情封建迷信人身攻击等违法信息不侵犯他人知识产权等</view>
<view class="text">2我们作为服务提供平台用户在使用时应当了解明白平台上所有信息均为用户自由发布用户应依法对其提供的任何信息承担全部责任我们会对信息进行必要的核查筛选但最终对信息的合法性准确性真实性不承担任何法律责任如用户发现某些信息中含有虚假违法内容请及时联系我们 待核实之后我们将根据中国法律法规和政府规范性文件采取措施移除相关内容或屏蔽相关链接我们不对用户所发布的信息之删除或储存失败负责若因用户发布内容引起任何刑事或民事纠纷发布者须自行承担该刑事民事或者经济法律责任同时本平台有权就发布者上述违法行为给予平台造成的任何损失要求赔偿</view>
<view class="text">隐私权政策</view>
<view class="text">我们非常重视对用户隐私的保护您在使用我们的服务时我们可能会收集和使用您的相关信息我们希望通过本用户隐私条款向您说明在使用我们的服务时我们如何收集使用披露存储这些信息本用户隐私条款系本平台保护用户个人隐私的承诺与您所使用的服务息息相关希望您仔细阅读</view>
<view class="text">个人资料的收集</view>
<view class="text">我们收集信息是为了向您提供更好更优更个性化的服务本公司将以合法的方式收集必要的用户个人资料本平台有可能收集的个人资料包括用户姓名身份证号地址电话号码电子邮件等信息用户在本平台注册时须依注册内容之提示提供用户本人及单位的真实准确完整信息并保证个人及单位资料的及时更新因用户提供个人及单位信息不准确不完整或未及时更新而可能遭受的任何损害本公司不承担任何责任</view>
<view class="text">个人资料的使用</view>
<view class="text">本公司有权为内部经营管理统计等目的使用您提供的个人及单位资料包括但不限于日常管理本公司提供给用户的服务及产品监控本平台的安全使用内部调研对来访数据进行统计和研究促进更新供用户享用的服务和产品确认核对联络名单为宣传推广目的为解决争议排除纠纷和执行本法律声明目的等</view>
<view class="text">个人资料的披露</view>
<view class="text">我们将采取合理的安全手段保护用户提供的个人及单位信息在未得到用户许可之前本平台不会擅自将用户信息披露给任何无关的第三方但涉及下列情形之一的除外</view>
<view class="text">1法律强制规定或司法行政机关依照法定程序要求提供</view>
<view class="text">2为保护用户的生命财产安全或为公共安全之需要</view>
<view class="text">3为了保护本平台其他用户的合法权益或财产</view>
<view class="text">4您出现违反中国有关法律法规或者本平台相关协议规则的情况需要向第三方披露</view>
<view class="text">5其他特殊或紧急情况</view>
<view class="text">由于用户对自身信息保密不当从而导致用户资料的泄露或由于网络线路黑客攻击计算机病毒等原因造成的资料泄露丢失被盗用或被篡改等本平台不承担任何责任</view>
<view class="text">Cookies技术的使用</view>
<view class="text">当用户访问设有Cookies装置的本平台时本平台服务器会自动发送Cookies至用户浏览器中同时储存进用户的电脑硬盘内此Cookies便负责记录日后用户访问本平台时的种种操作浏览习惯信用记录等运用Cookies技术我们能够为您提供更加周到的个性化服务我们将运用Cookies技术向用户提供其感兴趣的信息资料或为其储存密码</view>
<view class="text">个人资料的存储</view>
<view class="text">我们收集的有关您的信息和资料将保存在本公司及其关联公司的服务器上</view>
<view class="text">个人资料的保护</view>
<view class="text">为保障您的信息安全我们将采取各种合理的安全措施来保护您的信息使您的信息不会被泄漏毁损或者丢失我们对可能接触到您的信息的员工也采取了严格管理包括但不限于根据岗位的不同采取不同的权限控制与他们签署保密协议监控他们的操作情况等措施我们会按现有技术提供相应的安全措施来保护您的信息提供合理的安全保障尽力做到使您的信息不被泄漏毁损或丢失您的账户均有安全保护功能请妥善保管您的账户及密码信息我们将通过向其它服务器备份对用户密码进行加密等安全措施确保您的信息不丢失不被滥用和变造</view>
<view class="text">未成年人保护</view>
<view class="text">我们重视未成年人的个人信息保护如您为未成年人建议您请您的监护人阅读本隐私权条款并在征得您的监护人同意的前提下使用我们的服务或向我们提供信息</view>
<view class="text">免责条款</view>
<view class="text">1平台用户通过平台获取信息服务的过程中需务必遵守中国的相关法律法规平台不对用户达成协议过程中的任意纠纷承担法律责任</view>
<view class="text">2如买卖双方在交易过程中发生纠纷在当事人自愿平等的前提下买卖双方可提出要求平台协助调解平台会在查明事实分清是非的基础上严格遵守国家法律法规来给出建议不得因未经调解或者调解不成而阻止对方当事人向人民法院起诉经调解达成的协议具有法律效力但平台对此协议内容不承担任何法律责任</view>
<view class="text">3平台在此声明对您使用本平台与本平台相关的任何内容服务或其它链接至本平台的站点内容均不作直接间接法定约定的保证本平台对UGC用户原创内容的真实性不作保证也不承担因其非真实而造成的任何责任</view>
<view class="text">4本站到第三方平台的链接仅作为一种方便服务提供给您如果使用这些链接您将离开本站平台没有审查过任何第三方平台对这些平台及其内容不进行控制也不负任何责任如果您决定访问任何与本站链接的第三方平台其可能带来的结果和风险全部由您自己承担</view>
<view class="text">5用户应对使用平台得到的信息结果自行承担风险我们仅作为服务平台对本平台的使用即表明同意承担浏览本平台的全部风险本平台对任何使用或提供本网站信息的商业活动及其风险不承担任何责任用户自行发布的资源信息我们不对信息内容的安全性准确性真实性合法性负责也不承担任何法律责任</view>
<view class="text">6本平台如因线路硬件故障系统维护系统升级或其它不可抗力而导致暂停服务于暂停服务期间造成的一切不便与损失本平台不承担任何责任</view>
<view class="text">7本平台由于计算机黑客攻击计算机病毒侵入硬件设施损坏或因政府行为司法强制要求而造成个人资料泄露丢失被盗用或被篡改等本平台不承担任何责任</view>
<view class="text">8因不可抗力因素或第三方支付平台的系统漏洞故障造成交易环节中支付服务暂停或中断不稳定的本平台不承担任何责任</view>
<view class="text">9本平台上所有的增值服务或外包服务是为了方便用户更好地使用本平台而提供用户可自行选择接受与否您应在接受增值服务或外包服务之前阅读相关协议并按照您的需求和判断作出接受或不接受的意思表示若您选择接受增值服务及外包服务的视为您已经阅读相关协议并自行承担接受增值服务或外包服务的风险本平台不对任何提供给用户的增值服务及外包服务承担责任</view>
<view class="text">10任何单位或个人认为通过本平台网页内容可能涉嫌侵犯其知识产权应该及时向我们提出书面权利通知并提供身份证明权属证明及详细侵权情况证明我们收到上述法律文件后将会依法尽快处理</view>
<view class="text">法律管辖和适用</view>
<view class="text">任何有关本平台和本法律声明的争议纠纷均适用中华人民共和国法律任何有关本平台和本法律声明的争议应由有管辖权的人民法院管辖如中华人民共和国法律的修改使上述任何条款成为非法各方将同意由深圳智慧科技有限公司对上述条款作出修改</view>
<view class="text">本声明的解释权及对本平台及软件使用的解释权归结于本公司</view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
</script>
<style scoped lang="scss">
.wrap {
padding: 30rpx;
.title {
margin-bottom: 30rpx;
font-size: 40rpx;
text-align: center;
}
.text {
font-size: 30rpx;
line-height: 1.6;
white-space: pre-wrap;
}
}
</style>

@ -0,0 +1,317 @@
<template>
<view class="page">
<ul class="list">
<uni-swipe-action>
<uni-swipe-action-item
v-for="(item, i) in list"
:key="i"
:threshold="0"
:right-options="delOption"
@click="del(item)"
>
<li>
<uni-data-checkbox v-if="item.check" class="check" multiple :value="[1]" :localdata="item.checkData" @change="e => checkChange(e, i)"></uni-data-checkbox>
<uni-data-checkbox v-else class="check" multiple v-model="item.check" :localdata="item.checkData" @change="e => checkChange(e, i)"></uni-data-checkbox>
<image class="icon" :src="$util.getIcon(item)"></image>
<view class="texts">
<view class="name">{{ item.productName }}</view>
<view class="price">市场建议价{{ item.marketUnitPrice }}/</view>
</view>
</li>
</uni-swipe-action-item>
</uni-swipe-action>
</ul>
<uni-load-more :status="status" />
<view class="btn-wrap">
<uni-data-checkbox class="check" multiple v-model="checkAll" :localdata="checkAllData" @change="allChange"></uni-data-checkbox>
<view class="btns">
<view class="btn del" @click="batchDel">删除</view>
<view class="btn" @click="submit">生成订单</view>
</view>
</view>
</view>
</template>
<script>
import { shoppingCartList, delCart, detailsOfGoods } from '@/apis/modules/product.js'
export default {
data() {
return {
reachBottom: 0, // 0->,1->,-1->
status: 'more', // more|loading|noMore
searchTimer: null,
list: [],
page: 1,
pageSize: 10,
check: [1],
noCheck: [],
checkData: [{
text: '',
value: 1
}],
checkAll: [],
checkAllData: [{
text: '全部',
value: 1
}],
checked: [], //
delOption: [{
text: '删除',
style: {
backgroundColor: '#F56C6C'
}
}],
}
},
//
onPullDownRefresh() {
this.initList()
setTimeout(() => {
uni.stopPullDownRefresh()
}, 1500)
},
//
onReachBottom() {
if (this.reachBottom >= 0) {
this.reachBottom = 1
this.status = 'loading'
this.getList()
}
},
onShow() {
this.checked = []
//
try {
uni.removeStorageSync('orderForm')
uni.removeStorageSync('courses')
uni.removeStorageSync('orderEdited')
} catch (e) {}
this.initList()
},
methods: {
//
getList() {
uni.showLoading({
title: '加载中'
})
shoppingCartList({
pageNum: this.page,
pageSize: this.pageSize,
}).then(({ data }) => {
const { records } = data
const all = this.checkAll.length //
const pageChange = this.reachBottom > 0 //
//
records.forEach(e => {
e.check = 0
e.checkData = [{
text: '',
value: 1
}]
})
// list
this.list = pageChange ? [...this.list, ...records] : records
this.page++ // page+1
const noMore = this.list.length === data.total //
this.status = noMore ? 'noMore' : 'more' // noMore
this.reachBottom = noMore ? -1 : 0 // -1
uni.hideLoading()
}).catch(e => {
uni.hideLoading()
})
},
initList() {
this.page = 1
this.reachBottom = 0
this.getList()
},
//
checkChange(e, i) {
const { checked } = this
const item = this.list[i]
const { id } = item
const include = checked.findIndex(e => e.id === id)
// pushpush
if (e.detail.value.length) {
include === -1 && checked.push(item)
} else {
//
if (include !== -1) {
checked.splice(include, 1)
this.checkAll = []
}
}
console.log(11, checked)
},
//
allChange(e) {
const isCheck = !!e.detail.value.length //
const { list } = this
this.checked = isCheck ? JSON.parse(JSON.stringify(list)) : []
list.forEach(e => {
e.check = isCheck ? 1 : 0
})
},
//
createParam(e, authority, shopCartId) {
const { orderType } = this
const { mall, typeIds } = e
const trial = orderType == 2 //
return {
dataOrCourseId: mall.associatedProduct, // id
mallId: mall.mallId,
productName: mall.productName, //
periodOfUse: '', // 使
startTime: this.$util.formatDate(new Date(), 'yyyy-MM-dd'), //
endTime: '', //
remainingPeriod: '', //
marketValue: '', //
marketPrice: mall.marketUnitPrice, //
finalPrice: 0, //
finalValue: 0, //
discountRate: '0%', //
accountNum: 1, //
totalAmount: '', //
isEnable: 0, // 10
ship: 0, // 01
authority, // 01
options: 2,
miniProgramPictureAddress: mall.appletIcon || '', //
settlementPrice: trial ? 0 : '', //
settlementPriceUnit: 0, //
serviceFee: 0, //
shopCartId, // id
typeId: typeIds && typeIds.length ? typeIds[0] : '',
}
},
//
del(e) {
const that = this
uni.showModal({
title: '提示',
content: '确定要删除吗?',
success(res) {
if (res.confirm) {
delCart([e.id]).then(res => {
that.initList()
}).catch(e => {})
}
}
})
},
//
batchDel() {
const list = this.checked //
if (list.length) {
const that = this
uni.showModal({
title: '提示',
content: '确定要删除吗?',
success(res) {
if (res.confirm) {
delCart(list.map(e => e.id)).then(res => {
that.checkAll = []
that.checked = []
that.initList()
}).catch(e => {})
}
}
})
} else {
this.$util.errMsg('请选择产品!')
}
},
//
submit() {
const list = this.checked //
if (list.length) {
//
if (new Set(list.map(e => e.mallId)).size !== list.length) return this.$util.errMsg('所选产品存在重复,请重新选择')
const promises = []
let courses = []
list.forEach(e => {
promises.push(new Promise(async (resolve, reject) => {
//
const res = await detailsOfGoods(e.mallId)
const n = res.orderDetails
courses.push(this.createParam(n, this.$util.getOrderType(n.classificationIds[0]), e.id))
resolve()
}))
})
Promise.all(promises).then(_ => {
uni.setStorageSync('courses', courses)
this.$util.to(`../orderDetail/orderDetail?shopCart=1`)
})
} else {
this.$util.errMsg('请先添加产品!')
}
}
}
}
</script>
<style scoped lang="scss">
.page {
padding-bottom: 130rpx;
}
.list {
li {
display: flex;
align-items: center;
width: 100%;
padding: 30rpx 24rpx;
margin: 16rpx 24rpx;
background-color: #fff;
border-radius: 16rpx;
box-sizing: border-box;
}
.name {
margin-bottom: 10rpx;
font-size: 30rpx;
color: #333;
}
.price {
font-size: 26rpx;
color: #333;
}
.icon {
width: 100rpx;
min-width: 100rpx;
height: 100rpx;
margin: 0 20rpx;
border-radius: 4px;
}
}
/deep/.check {
.checklist-box {
margin: 0 !important;
}
.checkbox__inner {
width: 40rpx !important;
height: 40rpx !important;
border-radius: 50% !important;
}
.checkbox__inner-icon {
top: 8rpx !important;
left: 14rpx !important;
}
}
.btn-wrap {
position: fixed;
justify-content: space-between;
.btns {
display: inline-flex;
}
.btn {
width: auto;
padding: 0 50rpx;
}
.del {
margin-right: 20rpx;
background-color: #b5b5b5;
}
}
</style>

5
package-lock.json generated

@ -705,6 +705,11 @@
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
},
"umtrack-wx": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/umtrack-wx/-/umtrack-wx-2.8.0.tgz",
"integrity": "sha512-F5ul+Q7bDJ6MDrn9ysPAyB9nyP1vCxLGUBkSJ4uvknt8rjmX4tqy1IUnJuWKj9ZH2BtkjRFpldQXJSlLDOYfhQ=="
},
"unique-filename": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",

@ -10,6 +10,7 @@
"上拉筛选"
],
"dependencies": {
"copy-webpack-plugin": "^5.0.3"
"copy-webpack-plugin": "^5.0.3",
"umtrack-wx": "^2.8.0"
}
}

@ -1,50 +1,35 @@
{
"pages": [
{
"path" : "pages/login/login",
"style" :
{
"navigationBarTitleText": "登录",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/index/index",
"style" :
{
"navigationBarTitleText": "",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/clients/clients",
"style" :
{
"navigationBarTitleText": "客户列表",
"enablePullDownRefresh": true
}
},
{
"path" : "pages/products/products",
"path" : "pages/login/login",
"style" :
{
"navigationBarTitleText": "产品",
"enablePullDownRefresh": true
"navigationBarTitleText": "登录",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/clientDetail/clientDetail",
"path" : "pages/workbench/workbench",
"style" :
{
"navigationBarTitleText": "客户详情",
"navigationBarTitleText": "工作台",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/plans/plans",
"path": "pages/orders/orders",
"style" :
{
"navigationBarTitleText": "产品方案",
"navigationBarTitleText": "订单列表",
"enablePullDownRefresh": true
}
},
@ -53,35 +38,17 @@
"style" :
{
"navigationBarTitleText": "我的",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
}
,{
},
{
"path" : "pages/reg/reg",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
}
,{
"path" : "pages/study/study",
"style" :
{
"navigationBarTitleText": "学习",
"enablePullDownRefresh": true
}
}
,{
"path" : "pages/info/info",
"style" :
{
"navigationBarTitleText": "资讯",
"enablePullDownRefresh": true
}
}
],
"subPackages": [
@ -89,13 +56,21 @@
"root": "order",
"pages": [
{
"path": "orders/orders",
"path" : "clients/clients",
"style" :
{
"navigationBarTitleText": "订单列表",
"navigationBarTitleText": "客户列表",
"enablePullDownRefresh": true
}
},
{
"path" : "clientDetail/clientDetail",
"style" :
{
"navigationBarTitleText": "客户详情",
"enablePullDownRefresh": false
}
},
{
"path" : "addCourse/addCourse",
"style" :
@ -135,12 +110,82 @@
"navigationBarTitleText": "订单记录",
"enablePullDownRefresh": false
}
},
{
"path" : "productDetail/productDetail",
"style" :
{
"navigationBarTitleText": "产品详情",
"enablePullDownRefresh": false
}
}
,{
"path" : "products/products",
"style" :
{
"navigationBarTitleText": "产品",
"enablePullDownRefresh": true
}
}
,{
"path" : "shopCart/shopCart",
"style" :
{
"navigationBarTitleText": "购物车",
"enablePullDownRefresh": true
}
},
{
"path" : "serviceAgreement/serviceAgreement",
"style" :
{
"navigationBarTitleText" : "用户服务协议",
"enablePullDownRefresh" : false
}
},
{
"path" : "privacyAgreement/privacyAgreement",
"style" :
{
"navigationBarTitleText" : "用户隐私协议",
"enablePullDownRefresh" : false
}
}
]
},
{
"root": "team",
"pages": [
{
"path" : "study/study",
"style" :
{
"navigationBarTitleText": "学习",
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "#fff",
"enablePullDownRefresh": true
}
},
{
"path" : "plans/plans",
"style" :
{
"navigationBarTitleText": "产品方案",
"enablePullDownRefresh": true
}
}
,{
"path" : "info/info",
"style" :
{
"navigationBarTitleText": "资讯",
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "#fff",
"enablePullDownRefresh": true
}
},
{
"path" : "setting/setting",
"style" :
@ -209,7 +254,9 @@
"path" : "article/article",
"style" :
{
"navigationBarTitleText": "",
"navigationBarTitleText": "学习",
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "#fff",
"enablePullDownRefresh": false
}
}
@ -217,7 +264,7 @@
"path" : "scheme/scheme",
"style" :
{
"navigationBarTitleText": "",
"navigationBarTitleText": "方案详情",
"enablePullDownRefresh": false
}
},
@ -242,12 +289,12 @@
"current": 0, //list
"list": [{
"name": "test", //
"path": "pages/login/login" //
"path": "pages/index/index" //
}]
},
"globalStyle": {
"navigationBarTextStyle": "white",
"navigationBarTitleText": "或然合伙人运营管理平台",
"navigationBarTitleText": "职站商城",
"navigationBarBackgroundColor": "#007EFF",
"backgroundColor": "#f5f5f5",
"app-plus": {
@ -259,23 +306,23 @@
"selectedColor": "#007FFF",
"borderStyle": "white",
"backgroundColor": "#ffffff",
"fontSize": "16px",
"iconWidth": "30px",
"fontSize": "22px",
"iconWidth": "20px",
"list": [{
"pagePath": "pages/index/index",
"iconPath": "static/image/tab1.png",
"selectedIconPath": "static/image/tab1-1.png",
"text": "首页"
}, {
"pagePath": "pages/study/study",
"pagePath": "pages/workbench/workbench",
"iconPath": "static/image/tab2.png",
"selectedIconPath": "static/image/tab2-1.png",
"text": "学习"
"text": "工作台"
}, {
"pagePath": "pages/info/info",
"pagePath": "pages/orders/orders",
"iconPath": "static/image/tab3.png",
"selectedIconPath": "static/image/tab3-1.png",
"text": "资讯"
"text": "订单"
}, {
"pagePath": "pages/person/person",
"iconPath": "static/image/tab4.png",

@ -1,155 +1,120 @@
<template>
<view :class="['page', {oh: !per}]">
<image class="bg" src="@/static/image/index/index2.png" mode="widthFix"></image>
<view class="team">
<uni-data-picker class="picker-input" placeholder="切换团队" popup-title="切换团队" preload :clear-icon="false" :localdata="list" :map="{text: 'partnerClassificationName', value: 'teamId'}" v-model="teamId" @change="teamChange"></uni-data-picker>
</view>
<view :class="[{oh: !per}]">
<view class="banner">
<image class="img" src="@/static/image/index/index1.png" mode="widthFix"></image>
<view class="info">
<view class="title">城市合伙人招募中</view>
<view class="text">携手共创教育信息化新未来合伙共享产业互联领域新红利</view>
<image class="pic" src="@/static/image/index/banner.png" mode="widthFix"></image>
<image class="bg1" src="@/static/image/index/banner1.png"></image>
<view class="texts">
<view class="title">
<image class="logo" src="@/static/image/logo1.png" mode="widthFix"></image>
职站商城
</view>
<view class="text">您的一站式实验教学产品采购平台</view>
</view>
<ul class="entry">
<li v-if="auth('首页:客户')" @click="$util.to('../clients/clients')">
<image class="icon" src="@/static/image/index/index3.png" mode="widthFix"></image>
<view class="text">客户</view>
</li>
<li v-if="auth('首页:方案')" @click="$util.to('../plans/plans')">
<image class="icon" src="@/static/image/index/index4.png" mode="widthFix"></image>
<view class="text">方案</view>
</li>
<li v-if="auth('首页:订单')" @click="$util.to('/order/orders/orders')">
<image class="icon" src="@/static/image/index/index5.png" mode="widthFix"></image>
<view class="text">订单</view>
</li>
<li v-if="auth('首页:产品')" @click="$util.to('../products/products')">
<image class="icon" src="@/static/image/index/index6.png" mode="widthFix"></image>
<view class="text">产品</view>
</li>
</ul>
<view class="panel study-panel">
<view class="title" @click="toStudy">
<view class="left">
<image class="icon" src="@/static/image/index/index8.png" mode="widthFix"></image>
学习速递
</view>
<view class="right">
<text>全部</text>
<image class="arrow" src="@/static/image/index/index10.png" mode="widthFix"></image>
</view>
</view>
<view class="study">
<scroll-view class="scroll" scroll-x="true">
<view v-for="(item, i) in studies" :key="i" class="item" @click="toDetail(item)">
<image class="pic" :src="item.bannerImg"></image>
<view class="text">{{ item.title }}</view>
</view>
</scroll-view>
</view>
<view class="rect"></view>
</view>
<view class="panel">
<view class="title" @click="toPanel(1)">
<view class="left">
<image class="icon" src="@/static/image/index/index8.png" mode="widthFix"></image>
销售进展
</view>
<view class="right">
<image class="date" src="@/static/image/index/index7.png" mode="widthFix"></image>
<text>本月</text>
<image class="arrow" src="@/static/image/index/index10.png" mode="widthFix"></image>
<view class="page">
<view class="search-wrap">
<uni-search-bar class="search" radius="30" placeholder="请输入" v-model="keyword" clearButton="auto" cancelButton="none" @confirm="searchConfirm" />
<view>
<button class="all" type="primary" @click.stop="to('/order/products/products')">全部产品</button>
</view>
</view>
<view class="data first">
<view class="line">
<view class="item">
<view class="name">本月新增试用客户</view>
<view class="val">{{ sell.trialUser || 0 }}</view>
<view class="block" style="margin-top: 0">
<view class="title-wrap">
<view class="title">热门标签</view>
</view>
<view class="item">
<view class="name">本月成单客户</view>
<view class="val">{{ sell.regularUser || 0 }}</view>
<ul class="tags">
<li v-for="(tag, i) in tags" :key="i" @click="to(`/order/products/products?tagId=${tag.tagsId}&tagsName=${tag.tagsName}`)">
<view class="icon">
<image :src="require('@/static/image/index/' + (i + 1) + '.png')"></image>
</view>
<view class="text ell">{{ tag.tagsName }}</view>
</li>
</ul>
</view>
<view class="line">
<view class="item">
<view class="name">本月新增产品试用</view>
<view class="val">{{ sell.trialProduct || 0 }}</view>
<view class="block">
<view class="title-wrap">
<view class="title">热销产品</view>
</view>
<view class="item">
<view class="name">本月成交订单产品</view>
<view class="val">{{ sell.officialProduct || 0 }}</view>
<view class="list">
<view v-for="(item, i) in hotProducts" :key="i" class="item" @click="to(`/order/productDetail/productDetail?id=${item.mallId}`)">
<image class="pic" :src="$util.getIcon(item)"></image>
<view class="texts">
<view class="name ell">{{ item.productName }}</view>
<view class="des ell">{{ item.tagsName }}</view>
<view class="meta">{{ item.marketUnitPrice }}/</view>
</view>
</view>
</view>
</view>
<view class="panel">
<view class="title y-title" @click="toPanel(1)">
<view class="left">
<image class="icon" src="@/static/image/index/index9.png" mode="widthFix"></image>
年度经营分析
</view>
<image class="arrow" src="@/static/image/index/index10.png" mode="widthFix"></image>
<view class="block" style="margin-top: 40rpx">
<view class="title-wrap">
<view class="title">官方推荐</view>
</view>
<view class="data second">
<view class="line">
<view class="item item1">
<view class="val">{{ handleNum(analysis.finalPrice) }}</view>
<view class="name">总成交金额</view>
<view class="list">
<view v-for="(item, i) in offcialProducts" :key="i" class="item" @click="to(`/order/productDetail/productDetail?id=${item.mallId}`)">
<image class="pic" :src="$util.getIcon(item)"></image>
<view class="texts">
<view class="name ell">{{ item.productName }}</view>
<view class="des ell">{{ item.tagsName }}</view>
<view class="meta">{{ item.marketUnitPrice }}/</view>
</view>
<view class="item item2">
<view class="val">{{ handleNum(analysis.settlementPrice) }}</view>
<view class="name">总结算金额</view>
</view>
<view class="item equal">
<view class="val">{{ handleNum(analysis.marketingServiceCharge) }}</view>
<view class="name">市场服务费</view>
</view>
<view class="item">
<view class="val">{{ handleNum(analysis.projectBenefit) }}</view>
<view class="name">项目收益</view>
</view>
</view>
</view>
<view v-if="auth('产品:购物车')" class="plus">
<uni-badge size="small" :text="total" absolute="topRight" type="error" :custom-style="customStyle">
<image class="icon" src="@/static/image/product/shop-blue.png" mode="widthFix" @click="$util.to('/order/shopCart/shopCart')"></image>
</uni-badge>
</view>
<view v-if="!per" class="per-mask">功能升级中敬请期待...</view>
</view>
</template>
<script>
import { getUserRolesPermissionMenu } from '@/apis/modules/user.js'
import { getTeamsByAccountId, getTheBusinessManagerIdsUnderTheTeam } from '@/apis/modules/client.js'
import { treeList, salesProgress, annualOperatingAnalysis } from '@/apis/modules/parner.js'
import { partnerOperatingList } from '@/apis/modules/article.js'
import { tagsList, listOfGoods, shoppingCartList } from '@/apis/modules/product.js'
import { getTeamsByAccountId } from '@/apis/modules/client.js'
export default {
data() {
return {
per: true, //
teamId: uni.getStorageSync('teamId') || '',
list: [],
id: '',
teamList: [],
studies: [],
sell: {},
analysis: {
finalPrice: 0,
settlementPrice: 0,
marketingServiceCharge: 0,
projectBenefit: 0,
keyword: '',
tags: [],
hotProducts: [],
offcialProducts: [],
total: 0,
customStyle: {
width: '46rpx',
height: '46rpx',
lineHeight: '40rpx',
fontSize: '34rpx'
}
}
},
onShow() {
console.log(444, this.teamId)
this.keyword = ''
this.per = true
//
if (uni.getStorageSync('token')) {
this.getInfo()
this.getShopCart()
} else {
this.getTags()
this.getProducts()
}
},
methods: {
//
@ -157,13 +122,12 @@
if (!uni.getStorageSync('auth').includes('首页')) {
this.per = false
}
this.getStudy()
this.getSell()
this.getAnalysis()
this.getTags()
this.getProducts()
},
//
getAuth() {
uni.getStorageSync('token') && getUserRolesPermissionMenu({
getUserRolesPermissionMenu({
teamId: this.list.find(e => e.teamId == this.teamId).partnerClassificationId,
platformId: 4
}).then(({ permissionMenu }) => {
@ -214,8 +178,8 @@
// 退
uni.hideLoading()
uni.clearStorageSync()
uni.navigateTo({
url: '../login/login'
uni.redirectTo({
url: '../index/index'
})
}
@ -225,62 +189,60 @@
uni.hideLoading()
})
},
//
getStudy() {
partnerOperatingList({
topSort: 'desc',
//
getTags() {
tagsList().then(res => {
this.tags = res.tagsList.slice(0, 8)
}).catch(e => {})
},
//
getShopCart() {
shoppingCartList({
pageNum: 1,
pageSize: 1000,
}).then(({ data }) => {
this.total = data.total
}).catch(e => {})
},
//
getProducts() {
//
listOfGoods({
pageNum: 1,
pageSize: 5,
querySource: 4,
typeId: 1,
sort: 1,
isShelves: 0,
hotTag: 1
}).then(({ page }) => {
this.studies = page
page.records.forEach(e => {
e.productIntroduction = this.$util.removeTag(e.productIntroduction)
})
this.hotProducts = page.records
}).catch(e => {})
},
//
toStudy() {
uni.switchTab({
url: '/pages/study/study'
//
listOfGoods({
pageNum: 1,
pageSize: 5,
sort: 0,
isShelves: 0,
hotTag: 1,
selection: 1
}).then(({ page }) => {
page.records.forEach(e => {
e.productIntroduction = this.$util.removeTag(e.productIntroduction)
})
},
//
toDetail(item) {
this.$util.to(`/team/article/article?id=` + item.id)
},
//
getSell() {
salesProgress({
businessManagerId: uni.getStorageSync('team').partnerId,
teamId: this.teamId,
}).then(res => {
this.sell = res
this.offcialProducts = page.records
}).catch(e => {})
},
// 10000 + w
handleNum(num) {
// return num ? parseInt(num / 10000) + 'w' : 0
return num
//
searchConfirm(e) {
if (e.value) this.$util.to(uni.getStorageSync('token') ? `/order/products/products?keyword=${e.value}` : '../login/login')
},
//
getAnalysis() {
annualOperatingAnalysis({
businessManagerId: uni.getStorageSync('team').partnerId,
teamId: this.teamId,
}).then(({ data }) => {
if (data) this.analysis = data
}).catch(e => {})
},
//
teamChange() {
const { teamId } = this
const e = this.list.find(e => e.teamId == teamId)
uni.setStorageSync('team', e)
this.getAuth()
//
to(url) {
this.$util.to(uni.getStorageSync('token') ? url : '../login/login')
},
//
toPanel(i) {
this.$util.errMsg('功能暂未开放!')
}
}
}
</script>
@ -288,202 +250,182 @@
<style scoped lang="scss">
.page {
position: relative;
min-height: 100%;
padding: 30rpx 22rpx;
padding: 10rpx 22rpx;
margin-top: -61rpx;
box-sizing: border-box;
}
.bg {
z-index: -1;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.team {
width: 300rpx;
margin-bottom: 30rpx;
background-color: #fff;
border-top-left-radius: 16px;
border-top-right-radius: 16px;
}
.banner {
position: relative;
.img {
.pic {
width: 100%;
}
.info {
.bg1 {
position: absolute;
top: 80rpx;
left: 46rpx;
}
.title {
margin-bottom: 15rpx;
font-size: 36rpx;
font-weight: 600;
color: #001D67;
top: -120rpx;
left: -380rpx;
width: 100%;
transform: rotate(20deg);
}
.text {
font-size: 20rpx;
font-family: PingFangSC-Regular, PingFang SC;
color: #001D67;
.logo {
width: 70rpx;
margin-right: 14rpx;
}
.texts {
position: absolute;
top: 230rpx;
left: 0;
width: 100%;
text-align: center;
color: #fff;
}
.entry {
.title {
display: flex;
justify-content: space-around;
justify-content: center;
align-items: center;
margin: 10rpx 0 30rpx;
text-align: center;
.icon {
width: 78rpx;
margin-bottom: 22rpx;
font-size: 48rpx;
font-family: AlimamaShuHeiTi-Bold, AlimamaShuHeiTi;
font-weight: 600;
}
.text {
font-size: 28rpx;
color: #333;
font-size: 30rpx;
}
.rect {
position: absolute;
bottom: 90rpx;
left: -12rpx;
width: 55rpx;
height: 61rpx;
border-radius: 7px 10px 7px 10px;
opacity: 0.63;
border: 1px solid #FFFFFF;
transform: rotate(54deg);
}
.panel {
margin: 20rpx 10rpx;
background-color: #fff;
border-radius: 20rpx;
overflow: hidden;
&.study-panel {
background-color: transparent;
}
.title {
.search-wrap {
display: flex;
justify-content: space-between;
align-items: center;
padding: 17rpx 20rpx;
background: linear-gradient(90deg, #E5EFFF 0%, #FFFFFF 100%);
.search {
flex: 1;
}
.y-title {
background: linear-gradient(90deg, #FFF5E5 0%, #FFFFFF 100%);
}
.left {
display: flex;
align-items: center;
font-size: 30rpx;
color: #333;
.all {
font-size: 24rpx;
border-radius: 20px;
&::after {
border: none;
}
.right {
}
.block {
margin: 20rpx 0;
.title-wrap {
display: flex;
justify-content: space-between;
margin-bottom: 34rpx;
}
.title {
display: inline-flex;
align-items: center;
font-size: 28rpx;
font-weight: 600;
color: #333;
text {
margin: 0 15rpx 0 8rpx;
&:before {
content: '';
width: 10rpx;
height: 26rpx;
margin-right: 14rpx;
background: #007FFF;
border-radius: 5px;
}
}
.icon {
width: 36rpx;
margin-right: 10rpx;
}
.date {
width: 26rpx;
.tags {
display: flex;
flex-wrap: wrap;
li {
width: 25%;
margin-bottom: 24rpx;
text-align: center;
&:last-child {
image {
width: 50rpx;
height: 50rpx;
}
.arrow {
width: 16rpx;
}
.data {
padding: 33rpx 36rpx;
}
.line {
.icon {
display: flex;
justify-content: center;
align-items: center;
width: 90rpx;
height: 90rpx;
margin: 0 auto 18rpx;
background-color: rgb(228,239,255);
border-radius: 50%;
}
.first {
.item:first-child {
width: 65%;
image {
width: 60rpx;
height: 60rpx;
}
.name {
margin-bottom: 14rpx;
.text {
width: 165rpx;
margin: 0 auto;
font-size: 24rpx;
color: #999;
}
.val {
font-size: 30rpx;
color: #333;
}
.line:first-child {
margin-bottom: 32rpx;
}
}
.second {
padding: 38rpx 10rpx;
.list {
.item {
position: relative;
text-align: center;
&:after {
content: '';
position: absolute;
bottom: 14rpx;
right: -35rpx;
width: 22rpx;
height: 2px;
background-color: #ccc;
}
&.item1 {
margin-right: 53rpx;
}
&.item2 {
margin-right: 54rpx;
}
&.equal {
margin-right: 50rpx;
&:after {
bottom: 6rpx;
right: -39rpx;
height: 2px;
padding-bottom: 5px;
border-bottom: 2px solid #ccc;
background-clip:content-box;
box-sizing: content-box;
}
display: flex;
align-items: center;
margin-bottom: 28rpx;
}
&:last-child:after {
display: none;
.pic {
width: 100rpx;
height: 100rpx;
margin-right: 20rpx;
border-radius: 8px;
}
}
.val {
margin-bottom: 10rpx;
font-size: 30rpx;
color: #333;
.texts {
width: calc(100% - 156rpx);
}
.name {
font-size: 24rpx;
color: #999;
font-size: 28rpx;
font-weight: 600;
color: #333;
}
.des {
margin: 10rpx 0;
font-size: 22rpx;
color: #666;
}
.study {
width: 100%;
margin-top: 15rpx;
overflow: auto;
.item {
display: inline-block;
width: 280rpx;
margin-right: 20rpx;
background-color: #fff;
border-radius: 8px;
overflow: hidden;
.meta {
display: flex;
align-items: center;
font-size: 24rpx;
color: #2E2D31;
.icon {
width: 32rpx;
height: 32rpx;
margin-right: 12rpx;
}
.pic {
width: 100%;
height: 130rpx;
text {
width: 330rpx;
}
.text {
padding: 15rpx;
font-size: 28rpx;
color: #333;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.scroll {
width: 100%;
white-space: nowrap;
.plus {
bottom: 140rpx;
right: 60rpx;
.icon {
width: 106rpx;
}
.uni-badge {
font-size: 32rpx;
}
.oh {
overflow: hidden;
}
</style>

@ -1,18 +1,19 @@
<template>
<view class="page">
<view class="wrap">
<image class="logo" src="@/static/image/logo.png" mode=""></image>
<view class="hello">Hi城市合伙人请登录</view>
<button v-if="isLogin && !getPhone" class="btn phone" open-type="getPhoneNumber" @getphonenumber="onGetPhoneNumber">
<image class="logo" src="@/static/image/logo.png" mode="widthFix"></image>
<view class="hello">欢迎登录职站商城</view>
<template v-if="isLogin">
<button class="btn phone" open-type="getPhoneNumber" @getphonenumber="onGetPhoneNumber">
<image src="@/static/image/phone.png" mode="widthFix"></image>
{{ isReg ? '获取手机号' : '绑定手机'}}
</button>
<view class="tips">未注册或未绑定职站商城的手机号将帮你注册新账号</view>
</template>
<template v-else>
<view class="btn wechat" @click="login">
<image src="@/static/image/wechat.png" mode="widthFix"></image>
微信授权登录
快捷登录
</view>
<view class="reg" @click="toReg">没有账号申请注册</view>
</template>
<view class="agree">
@ -25,18 +26,18 @@
</template>
<script>
import { login, userBinding, getSessionKey, queryPartnerAccount } from '@/apis/modules/user.js'
import { login, userBinding, getSessionKey, queryPartnerAccount, douYinLogin, douYinLoginByOpenid, douYinUserBinding } from '@/apis/modules/user.js'
import WXBizDataCrypt from '@/libs/WXBizDataCrypt'
export default {
data() {
return {
isDy: uni.getSystemInfoSync().uniPlatform === 'mp-toutiao', //
agree: [],
agreeData: [{
text: '同意',
value: 1
}],
isLogin: false, //
getPhone: false ,//
isReg: false, //
sessionKey: '',
openid: '',
@ -45,6 +46,7 @@
}
},
onShow() {
// uni.setStorageSync('token', 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyIiwiaWF0IjoxNjg2NzExNTA5LCJleHAiOjE2ODY3NTQ3MDksImFjY291bnRJZCI6IjEyNTU4In0.SX1sNFtb2JiCufgTz3ZmQkcJ-FtVci7Hp0DFd_mVk8E')
//
this.checkLogin()
},
@ -56,7 +58,6 @@
} else {
uni.clearStorageSync()
this.isLogin = false
this.getPhone = false
}
},
//
@ -69,24 +70,66 @@
lang: 'zh_CN',
desc: '登录',
success: ({ userInfo }) => {
console.log(22, userInfo)
uni.setStorageSync('userName', userInfo.nickName)
uni.setStorageSync('avatar', userInfo.avatarUrl)
uni.login({
success: ({ code }) => {
success: async ({ code }) => {
if (code) {
this.submiting = true
login({
//
if (this.isDy) {
try {
const res = await douYinLogin(code)
const { data, status } = res
this.submiting = false
this.sessionKey = data.sessionKey
this.openid = data.openid
this.unionid = data.unionid
uni.setStorageSync('sessionKey', data.sessionKey)
uni.setStorageSync('openid', data.openid)
// const res1 = await douYinLoginByOpenid('_000P6jr9bt8gW0ySNSzGsNBnCB0er4KtN3M')
//
if (data.state === 'login') {
this.toIndex()
uni.setStorageSync('token', data.token)
} else {
this.isLogin = true
// this.isReg = true
}
} catch (e) {
this.submiting = false
}
} else {
//
try {
const res = await login({
code,
avatarUrl: userInfo.avatarUrl
}).then(({ data }) => {
})
const { data, status } = res
this.submiting = false
//
if (status == 10028) {
// unilogincode
uni.login({
success: ({ code }) => {
getSessionKey({
code,
}).then(({ sessionKey }) => {
this.sessionKey = sessionKey.session_key
this.openid = sessionKey.openid
this.isLogin = true
}).catch(e => {})
this.isReg = true
}
})
} else {
const e = data.sessionKey
this.sessionKey = e.session_key
this.openid = e.openid
this.unionid = e.unionid
uni.setStorageSync('sessionKey', e.session_key)
uni.setStorageSync('openid', e.openid)
this.submiting = false
//
if (data.state === 'login') {
this.toIndex()
@ -94,9 +137,11 @@
} else {
this.isLogin = true
}
}).catch(e => {
}
} catch (e) {
this.submiting = false
})
}
}
} else {
this.submiting = false
that.$util.errMsg('登录失败!')
@ -113,37 +158,54 @@
}
},
//
onGetPhoneNumber(e){
async onGetPhoneNumber(e){
if (this.submiting) return false
const { encryptedData, iv } = e.detail
// 1.使js2.使
// const WXBizDataCrypt = require('@/libs/WXBizDataCrypt')
const accountInfo = uni.getAccountInfoSync() // appid
const pc = new WXBizDataCrypt(accountInfo.miniProgram.appId , this.sessionKey)
// 1.使js2.使 ()
const appId = this.isDy ? 'tt2192572fbea04fe601' : uni.getAccountInfoSync().miniProgram.appId
const pc = new WXBizDataCrypt(appId , this.sessionKey)
const data = pc.decryptData(encryptedData , iv)
this.submiting = true
const phone = data.phoneNumber
if (this.isReg) { //
uni.redirectTo({
url: `../reg/reg?openid=${this.openid}&phone=${phone}`
})
this.submiting = false
this.$util.to(`../reg/reg?openid=${this.openid}&phone=${phone}`)
} else { //
userBinding({
try {
const fn = this.isDy ? douYinUserBinding : userBinding
const res = await fn({
openid: this.openid,
phone,
unionid: this.unionid,
platformId: 4
}).then(({ token }) => {
})
const { token, status } = res
if (status == 10014) {
// unilogincode
uni.login({
success: ({ code }) => {
getSessionKey({
code,
}).then(({ sessionKey }) => {
this.sessionKey = sessionKey.session_key
this.openid = sessionKey.openid
this.$util.to(`../reg/reg?openid=${this.openid}&phone=${phone}`)
}).catch(e => {})
this.isReg = true
}
})
} else {
this.submiting = false
uni.setStorageSync('token', token)
this.toIndex()
}).catch(e => {
}
} catch (e) {
this.submiting = false
uni.showToast({
title: e.message,
icon: 'none'
})
})
}
}
},
//
@ -155,7 +217,6 @@
lang: 'zh_CN',
desc: '登录',
success: ({ userInfo }) => {
console.log(22, userInfo)
uni.setStorageSync('userName', userInfo.nickName)
uni.setStorageSync('avatar', userInfo.avatarUrl)
uni.login({
@ -165,12 +226,10 @@
getSessionKey({
code,
}).then(({ sessionKey }) => {
console.log(11, sessionKey)
this.sessionKey = sessionKey.session_key
this.openid = sessionKey.openid
this.submiting = false
this.isLogin = true
}).catch(e => {
this.submiting = false
})
@ -190,7 +249,7 @@
}
},
toAgreement(id) {
this.$util.openFile(id)
this.$util.to(id ? `/order/privacyAgreement/privacyAgreement` : `/order/serviceAgreement/serviceAgreement`)
},
//
toIndex() {
@ -220,13 +279,18 @@
border-radius: 20rpx;
.logo {
width: 393rpx;
height: 93rpx;
}
.hello {
margin: 36rpx 0;
font-size: 28rpx;
color: #333;
}
.tips {
margin-top: 30rpx;
font-size: 26rpx;
color: #adadad;
text-align: left;
}
.btn {
display: flex;
justify-content: center;

@ -1,5 +1,6 @@
<template>
<view>
<view :class="[{'not-auth': !per}]">
<view class="filter">
<uni-search-bar class="search" radius="30" placeholder="请输入学校名称,商务经理,订单号" v-model="keyword" clearButton="auto" cancelButton="none" />
<view :class="['sort', sort]" @click="switchSort"></view>
@ -38,7 +39,7 @@
<text class="name">订单内容</text>
<view class="val ell-wrap">
<view :class="{ell: !item.toggle}">{{ item.orderContent }}</view>
<view v-if="item.orderContent.length > 14" class="toggle" @click.stop="toggle(item)">{{ item.toggle ? '收起' : '展开' }}</view>
<view v-if="item.orderContent && item.orderContent.length > 14" class="toggle" @click.stop="toggle(item)">{{ item.toggle ? '收起' : '展开' }}</view>
</view>
</view>
<view class="line">
@ -58,9 +59,12 @@
</template>
<empty v-else></empty>
<uni-icons class="plus" type="plus-filled" size="60" color="#007eff" @click="$util.to('../orderDetail/orderDetail')"></uni-icons>
<uni-icons class="plus" type="plus-filled" size="60" color="#007eff" @click="$util.to('/order/orderDetail/orderDetail')"></uni-icons>
<filter-popup :data="filterData" :form.sync="filterForm" v-model="popup" title="全部筛选" height="1104rpx" @finsh="subFinsh"></filter-popup>
</view>
<notAuth v-if="!per"></notAuth>
</view>
</template>
<script>
@ -69,6 +73,7 @@
export default {
data() {
return {
per: true, //
popup: false,
//
filterData: [
@ -87,6 +92,10 @@
title: "已完成",
value: 1
},
{
title: "已取消",
value: 2
},
],
}
],
@ -143,22 +152,60 @@
}
},
onShow() {
//
this.per = true
//
try {
uni.removeStorageSync('orderForm')
uni.removeStorageSync('courses')
} catch (e) {}
this.initRole()
this.$uma.trackEvent('order') //
},
methods: {
//
initRole() {
this.tabs = []
const auth = uni.getStorageSync('auth')
auth.includes('首页:订单:我的订单') && this.tabs.push({
if (!auth.includes('订单')) {
this.per = false
this.list = [
{
businessManagerName: '智信云',
customerName: '智信云师资培训班',
orderContent: 'python实训系统',
createTime: '2023-08-08'
},
{
businessManagerName: '智信云智信云智信云',
customerName: '智信云师资培训班',
orderContent: 'python实训系统',
createTime: '2023-08-08'
},
{
businessManagerName: '智信云智信云',
customerName: '智信云师资培训班',
orderContent: 'python系统',
createTime: '2023-08-08'
},
{
businessManagerName: '智信云',
customerName: '智信云师资培训班智信云师资培训班',
orderContent: 'python实训系统,实训系统',
createTime: '2023-08-08'
},
{
businessManagerName: '智信云',
customerName: '智信云师资培训班',
orderContent: 'python实训系统',
createTime: '2023-08-08'
}
]
}
this.tabs = []
auth.includes('订单:我的订单') && this.tabs.push({
name: '我的订单',
id: 0
})
auth.includes('首页:订单:团队全部订单') && this.tabs.push({
auth.includes('订单:团队全部订单') && this.tabs.push({
name: '团队全部订单',
id: 1
})
@ -168,7 +215,7 @@
this.curTab = this.tabs[0].id
this.tabs = []
}
this.initList()
this.per && this.initList()
},
getList() {
const data = {
@ -189,7 +236,7 @@
// list
const list = data.records
list.map(e => {
e.toggle = e.orderContent.length < 14 // 14
if (e.orderContent) e.toggle = e.orderContent.length < 14 // 14
})
this.list = this.reachBottom > 0 ? [...this.list, ...list] : list
this.page++ // page+1
@ -227,7 +274,7 @@
},
//
toDetail(item) {
this.$util.to(`../orderDetail/orderDetail?orderId=${item.orderId}&show=1`)
this.$util.to(`/order/orderDetail/orderDetail?orderId=${item.orderId}&show=1`)
},
//
del(e) {
@ -256,8 +303,10 @@
margin-top: 20rpx;
background-color: #fff;
.item {
width: 100%;
padding: 20rpx 40rpx;
border-bottom: 1px solid #f1f1f1;
box-sizing: border-box;
}
.c-name {
font-size: 30rpx;

@ -1,5 +1,6 @@
<template>
<view class="page">
<view class="status-bar"></view>
<image class="bg" src="@/static/image/person-bg.png"></image>
<view class="wrap">
<view class="info">
@ -10,12 +11,20 @@
<view class="name">{{ my.info.userName }}</view>
<view class="phone">{{ my.info.phone }}</view>
</view>
<view v-if="!disabled" class="tag">团队负责人</view>
</view>
<view class="list">
<view v-if="auth('我的:我的团队')" class="item" @click="$util.to('/team/teams/teams')">
<view class="left">
<image class="icon" src="@/static/image/person4.png" mode=""></image>
<text class="name">我的团队</text>
<text class="name">{{ disabled ? '所属团队' : '我的团队' }}</text>
</view>
<uni-icons type="right" size="15" color="#ccc"></uni-icons>
</view>
<view v-if="!hasOwnTeam && auth('我的:我的团队')" class="item" @click="createTeam">
<view class="left">
<image class="icon" src="@/static/image/person4.png" mode=""></image>
<text class="name">创建自己的团队</text>
</view>
<uni-icons type="right" size="15" color="#ccc"></uni-icons>
</view>
@ -39,16 +48,18 @@
<text class="name">我的收藏</text>
</view>
</view> -->
<view v-if="auth('我的:市场服务费')" class="item">
<view class="left">
<image class="icon" src="@/static/image/person6.png" mode=""></image>
<image class="icon" src="@/static/image/person26.png" mode=""></image>
<text class="name">市场服务费</text>
</view>
<text class="val">{{ my.teamInfo.annualMarketingFee ? '项目抽成' + my.teamInfo.annualMarketingFee + '%' :'-' }}</text>
</view>
<view v-if="auth('我的:团队年费')" class="item">
<view class="left">
<image class="icon" src="@/static/image/person7.png" mode=""></image>
<image class="icon" src="@/static/image/person27.png" mode=""></image>
<text class="name">团队年费</text>
</view>
<text class="val">{{ my.teamInfo.annualTeamFee ? '固定年费' + my.teamInfo.annualTeamFee + 'w' : '-' }}</text>
@ -87,11 +98,15 @@
<script>
import { my, editProvinceCity } from '@/apis/modules/parner.js'
import { queryProvince, queryCity, updateAvatars } from '@/apis/modules/user.js'
import { queryProvince, queryCity, updateAvatars, getUserRolesPermissionMenu } from '@/apis/modules/user.js'
import { getTeamsByAccountId } from '@/apis/modules/client.js'
import OSS from '@/libs/Oss/upload'
export default {
data() {
return {
per: true, //
teamId: uni.getStorageSync('teamId') || '',
teams: [],
my: {
info: {
phone: ''
@ -105,6 +120,7 @@
},
avatar: uni.getStorageSync('avatar') || '@/static/image/avatar.png',
userName: uni.getStorageSync('userName'),
hasOwnTeam: 0, //
disabled: true,
provinces: [],
cities: [],
@ -125,10 +141,15 @@
}
},
onShow() {
console.log(11, uni.getStorageSync('avatar'))
this.per = true
this.initRole()
this.disabled = uni.getStorageSync('team').isTeam == 0 //
if (uni.getStorageSync('token')) {
this.getTeam()
} else {
uni.redirectTo({
url: '/pages/login/login'
})
}
},
methods: {
//
@ -139,6 +160,80 @@
this.getInfo()
}
},
//
getAuth() {
uni.showLoading({
title: '加载中'
})
getUserRolesPermissionMenu({
teamId: this.teams.find(e => e.teamId == this.teamId).partnerClassificationId,
platformId: 4
}).then(({ permissionMenu }) => {
uni.hideLoading()
const auth = []
//
const generateAuth = (list, parent) => {
list.map(e => {
const name = `${parent ? parent + ':' : ''}${e.name}`
auth.push(name)
generateAuth(e.children, name)
})
}
generateAuth(permissionMenu[0].children, '')
uni.setStorageSync('auth', auth)
this.initRole()
}).catch(e => {
uni.hideLoading()
uni.setStorageSync('auth', [])
this.initRole()
})
},
//
getTeam() {
uni.showLoading({
title: '加载中'
})
getTeamsByAccountId().then(({ data }) => {
let hasOwnTeam = 0 //
data.map(e => {
const n = e.partnerClassificationList
e.id = n.id
// parnerIdidteamIduni.getStorageSync('team').partnerId使
e.teamId = e.isTeam == 1 ? +e.partnerClassificationId : n.id
e.partnerClassificationName = n.partnerClassificationName
delete e.partnerClassificationList
if (e.isTeam == 1) hasOwnTeam = 1
})
this.hasOwnTeam = hasOwnTeam
const teamId = uni.getStorageSync('teamId')
if (data.length) {
/**
* @description 如果是第一次进则默认选中第一个团队并把该团队的信息存入缓存
* 或者团队列表里没有该id则说明超管已经被转让也需要重新选中团队
*/
const curTeam = data.find(e => e.teamId == teamId)
if (teamId && curTeam) {
uni.setStorageSync('team', curTeam)
} else if (!uni.getStorageSync('team') || !curTeam) {
this.teamId = data[0].teamId
uni.setStorageSync('teamId', data[0].teamId)
uni.setStorageSync('team', data[0])
}
} else {
// 退
uni.hideLoading()
uni.clearStorageSync()
uni.redirectTo({
url: '../index/index'
})
}
this.disabled = uni.getStorageSync('team').isTeam == 0 //
this.teams = data
this.getAuth()
}).catch(e => {
uni.hideLoading()
})
},
//
getInfo() {
const { partnerId, teamId } = uni.getStorageSync('team')
@ -147,8 +242,9 @@
teamId
}).then(({ my }) => {
this.my = my
this.avatar = my.info.userAvatars
uni.setStorageSync('avatar', my.info.userAvatars)
const avatar = my.info.userAvatars || 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'
this.avatar = avatar
uni.setStorageSync('avatar', avatar)
this.provinceId = my.teamInfo.provinceId
this.cityId = my.teamInfo.cityId
uni.setStorageSync('provinceId', this.provinceId)
@ -159,21 +255,16 @@
},
//
onChooseAvatar(e) {
uni.uploadFile({
url: 'https://huorantech.cn/nakadai/nakadai/oss/fileUpload',
filePath: e.detail.avatarUrl,
name: 'file',
header: {
token: uni.getStorageSync('token'),
},
formData: {},
success: ({ data }) => {
updateAvatars(JSON.parse(data).filesResult.fileUrl).then(res => {
OSS(e.detail.avatarUrl, ({ url }) => {
updateAvatars(url).then(res => {
this.getInfo()
}).catch(e => {})
}
})
},
//
createTeam() {
this.$util.to(`../reg/reg?openid=${uni.getStorageSync('openid')}&phone=${this.my.info.phone}&my=1`)
},
//
toSet() {
this.$util.to(`/team/setting/setting`)
@ -224,9 +315,16 @@
</script>
<style scoped lang="scss">
.status-bar {
// width: 100%;
// height: calc(var(--status-bar-height) + 120rpx);
}
.bg {
width: 100%;
height: 300rpx;
height: calc(var(--status-bar-height) + 250rpx);
// #ifdef MP-WEIXIN
height: calc(var(--status-bar-height) + 317rpx);
// #endif
}
.wrap {
position: relative;
@ -253,6 +351,9 @@
height: 120rpx;
border: 0;
}
.text {
margin-right: 20rpx;
}
.name {
margin-bottom: 10rpx;
font-size: 40rpx;
@ -262,6 +363,14 @@
font-size: 28rpx;
color: #333;
}
.tag {
padding: 8rpx 16rpx;
margin-top: -50rpx;
font-size: 24rpx;
color: #fff;
background-color: #2979ff;
border-radius: 20px;
}
}
.list {
margin-top: 16rpx;
@ -279,8 +388,8 @@
align-items: center;
}
.icon {
width: 48rpx;
height: 48rpx;
width: 40rpx;
height: 40rpx;
margin-right: 16rpx;
}
text {

@ -1,218 +0,0 @@
<template>
<view>
<view class="filter">
<uni-search-bar class="search" radius="30" placeholder="请输入产品名称" v-model="keyword" clearButton="auto" cancelButton="none" />
<view :class="['sort', sort]" @click="switchSort"></view>
</view>
<ul class="tab">
<li v-for="(tab, i) in tabs" :class="{active: curTab === tab.id}" @click="tabChange(tab)">{{ tab.name }}</li>
</ul>
<ul class="list">
<li v-for="item in list">
<view class="pro-name">
<image class="icon" :src="$util.getIcon(item)" mode="widthFix"></image>
{{ item.productName }}
</view>
<view class="info">
<view class="line">
<text class="name">产品简介</text>
<view class="val ell-wrap">
<view :class="{ell: !item.toggle}">{{ item.briefIntroduction }}</view>
<view v-if="item.briefIntroduction.length > 14" class="toggle" @click="toggle(item)">{{ item.toggle ? '收起' : '展开' }}</view>
</view>
</view>
<view class="line">
<text class="name">产品类型</text>
<text class="val">{{ tabs.find(e => e.id === item.productType).name }}</text>
</view>
<view class="line">
<text class="name">市场单价</text>
<text class="val">{{ item.marketPrice }}/</text>
</view>
<view class="line">
<text class="name">结算方式</text>
<text class="val">{{ item.settlementMethod ? '比例分成' : '结算单价' }} {{ item.settlementPrice }}/</text>
</view>
<view class="line">
<text class="name">供应厂商</text>
<text class="val">{{ item.supplierName }}</text>
</view>
</view>
</li>
</ul>
<uni-load-more :status="status" />
</view>
</template>
<script>
import { AppletsDataProductList } from '@/apis/modules/product.js'
export default {
data() {
return {
curTab: '',
tabs: [
{
name: '全部',
id: ''
},
{
name: '实训课程',
id: 1
},
{
name: '理论课程',
id: 0
},
{
name: '数据产品',
id: 2
}
],
reachBottom: 0, // 0->,1->,-1->
status: 'more', // more|loading|noMore
searchTimer: null,
sort: 'desc',
keyword: '',
list: [],
page: 1,
pageSize: 10
}
},
watch: {
keyword () {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.initList()
}, 500)
}
},
//
onPullDownRefresh() {
this.initList()
setTimeout(() => {
uni.stopPullDownRefresh()
}, 1500)
},
//
onReachBottom() {
if (this.reachBottom >= 0) {
this.reachBottom = 1
this.status = 'loading'
this.getList()
}
},
onShow() {
this.initList()
},
methods: {
getList() {
AppletsDataProductList({
sort: this.sort,
keywords: this.keyword,
productType: this.curTab,
pageNum: this.page,
pageSize: this.pageSize
}).then(({ data }) => {
// list
const list = data.records
list.map(e => {
e.toggle = e.briefIntroduction.length < 14 // 14
})
this.list = this.reachBottom > 0 ? [...this.list, ...list] : list
this.page++ // page+1
const noMore = this.list.length === data.total //
this.status = noMore ? 'noMore' : 'more' // noMore
this.reachBottom = noMore ? -1 : 0 // -1
}).catch(e => {})
},
initList() {
this.page = 1
this.reachBottom = 0
this.getList()
},
//
toggle(item) {
item.toggle = !item.toggle
},
//
switchSort() {
this.sort = this.sort === 'desc' ? 'asc' : 'desc'
this.initList()
},
// tab
tabChange(tab) {
this.curTab = tab.id
this.initList()
}
}
}
</script>
<style scoped lang="scss">
.filter {
display: flex;
align-items: center;
.search {
flex: 1;
}
.sl-filter {
width: 30%;
margin-left: 10%;
}
}
.list {
li {
padding: 0 24rpx;
margin: 16rpx 24rpx;
background-color: #fff;
border-radius: 16rpx;
}
.pro-name {
display: flex;
align-items: center;
padding: 18rpx 0;
font-size: 30rpx;
color: #333;
border-bottom: 1px solid #E6E8ED;
.icon {
width: 52rpx;
height: 52rpx;
margin-right: 20rpx;
}
}
.info {
padding: 12rpx 0;
}
.line {
display: flex;
padding: 12rpx 0;
}
.name {
margin-right: 10rpx;
font-size: 28rpx;
color: #999;
}
.val {
max-width: 70%;
font-size: 28rpx;
color: #333;
}
.ell-wrap {
display: inline-flex;
align-items: center;
}
.ell {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.toggle {
margin-left: 10rpx;
white-space: nowrap;
font-size: 24rpx;
color: #0e92ef;
}
}
</style>

@ -1,9 +1,9 @@
<template>
<view class="page">
<image class="logo" src="@/static/image/logo.png" mode=""></image>
<image class="logo" src="@/static/image/logo.png" mode="widthFix"></image>
<view class="wrap">
<view v-if="form.isTeam !== 0" class="hello">
{{ form.isTeam ? '或然科技城市合伙人,欢迎回来!' : '欢迎加入或然城市合伙人计划!请认真填写您的姓名和意向开展业务的区域。注册后,我们将会有区域运营与您联系沟通后续事宜。'}}
<view class="hello">
{{ form.isTeam ? '或然科技城市合伙人,欢迎回来!' : form.isTeam === 0 ? '请认真填写您的姓名和意向开展业务的区域。创建成功后,我们将会有区域运营与您联系沟通后续事宜。' : '欢迎加入或然城市合伙人计划!请认真填写您的姓名和意向开展业务的区域。注册后,我们将会有区域运营与您联系沟通后续事宜。'}}
</view>
<view>
<uni-forms>
@ -33,8 +33,10 @@
export default {
data() {
return {
isDy: uni.getSystemInfoSync().uniPlatform === 'mp-toutiao', //
openid: '',
phone: '',
my: false,
form: {
userName: '',
provinceId: '',
@ -51,17 +53,19 @@
const { options } = pages[pages.length - 1]
this.openid = options.openid
this.phone = options.phone
this.my = options.my
this.getProvince()
this.checkLogin()
},
methods: {
//
checkLogin() {
if (uni.getStorageSync('token')) {
this.toIndex()
} else {
// isTeam 10team
queryPartnerAccount(this.phone).then(({ team, username }) => {
queryPartnerAccount({
phone: this.phone,
openId: this.isDy ? '' : this.openid,
douYinOpenId: this.isDy ? this.openid : '',
}).then(({ team, username }) => {
if (team) {
team.teamId && uni.setStorageSync('teamId', team.teamId)
this.form.userName = team.userName
@ -72,25 +76,11 @@
} else {
this.form.isTeam = 0
if (team.userName) this.form.userName = team.userName
uni.showModal({
title: '提示',
content: `或然科技城市合伙人,欢迎回来!您已在${team.teamName},是否要创建自己的团队?`,
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
} else if (res.cancel) {
uni.redirectTo({
url: '../login/login'
})
}
}
})
}
} else if (username) { // username
this.form.userName = username
}
}).catch(e => {})
}
},
//
getProvince() {
@ -112,21 +102,20 @@
if (val) this.form.cityId = ''
},
//
submit() {
async submit() {
const { form } = this
if (!form.userName) return this.$util.errMsg('请输入姓名!')
if (!form.provinceId) return this.$util.errMsg('请选择意向省份!')
if (!form.cityId) return this.$util.errMsg('请选择意向城市!')
form.phone = this.phone
form.appOpenId = this.openid
form[this.isDy ? 'douYinOpenId' : 'appOpenId'] = this.openid
form.uniqueIdentification = Date.now()
if (form.isTeam) { //
loginByOpenid(this.openid).then(({ data }) => {
const { data } = await loginByOpenid(this.openid)
uni.setStorageSync('token', data.token)
this.toIndex()
}).catch(res => {})
} else { // or
partnerAccountApplication(form).then(({ token, teamId }) => {
const { token, teamId } = await partnerAccountApplication(form)
this.$util.sucMsg(form.isTeam === 0 ? '创建成功' : '注册成功')
// tokenteamId
if (token) {
@ -142,20 +131,17 @@
})
}, 1500)
}
}).catch(res => {})
}
},
//
toIndex() {
uni.reLaunch({
url: '../index/index'
url: this.my ? '../person/person' : '../home/home'
})
},
//
back() {
uni.redirectTo({
url: '../login/login'
})
uni.navigateBack()
}
}
}
@ -169,7 +155,6 @@
url(@/static/image/login2.png) bottom right/123rpx auto no-repeat;
.logo {
width: 393rpx;
height: 93rpx;
margin: 100rpx 0 60rpx;
}
}

@ -0,0 +1,530 @@
<template>
<view :class="['page', {oh: !per}]">
<view class="status-bar"></view>
<image class="bg" src="@/static/image/workbench/index2.png" mode="widthFix"></image>
<view class="team-wrap" :style="{paddingTop: headerTop}">
<view class="team">
<uni-data-picker class="picker-input" placeholder="切换团队" popup-title="切换团队" preload :clear-icon="false" :localdata="list" :map="{text: 'partnerClassificationName', value: 'teamId'}" v-model="teamId" @change="teamChange"></uni-data-picker>
</view>
</view>
<view class="banner">
<image class="img" src="@/static/image/workbench/index1.png" mode="widthFix"></image>
<view class="info">
<view class="title">城市合伙人招募中</view>
<view class="text">携手共创教育信息化新未来合伙共享产业互联领域新红利</view>
</view>
</view>
<ul class="entry">
<li @click="toModule('client')">
<image class="icon" src="@/static/image/workbench/index3.png" mode="widthFix"></image>
<view class="text">客户</view>
</li>
<li @click="toModule('plan')">
<image class="icon" src="@/static/image/workbench/index4.png" mode="widthFix"></image>
<view class="text">方案</view>
</li>
<li @click="toModule('study')">
<image class="icon" src="@/static/image/workbench/index5.png" mode="widthFix"></image>
<view class="text">学习</view>
</li>
<li @click="toModule('info')">
<image class="icon" src="@/static/image/workbench/index6.png" mode="widthFix"></image>
<view class="text">资讯</view>
</li>
</ul>
<view class="panel study-panel">
<view class="title" @click="toStudy">
<view class="left">
<image class="icon" src="@/static/image/workbench/index8.png" mode="widthFix"></image>
学习速递
</view>
<view class="right">
<text>全部</text>
<image class="arrow" src="@/static/image/workbench/index10.png" mode="widthFix"></image>
</view>
</view>
<view class="study">
<scroll-view class="scroll" scroll-x="true">
<view v-for="(item, i) in studies" :key="i" class="item" @click="toDetail(item)">
<image class="pic" :src="item.bannerImg"></image>
<view class="text">{{ item.title }}</view>
</view>
</scroll-view>
</view>
</view>
<view class="panel">
<view class="title" @click="toPanel(1)">
<view class="left">
<image class="icon" src="@/static/image/workbench/index8.png" mode="widthFix"></image>
销售进展
</view>
<view class="right">
<image class="date" src="@/static/image/workbench/index7.png" mode="widthFix"></image>
<text>本月</text>
<image class="arrow" src="@/static/image/workbench/index10.png" mode="widthFix"></image>
</view>
</view>
<view class="data first">
<view class="line">
<view class="item">
<view class="name">本月新增试用客户</view>
<view class="val">{{ sell.trialUser || 0 }}</view>
</view>
<view class="item">
<view class="name">本月成单客户</view>
<view class="val">{{ sell.regularUser || 0 }}</view>
</view>
</view>
<view class="line">
<view class="item">
<view class="name">本月新增产品试用</view>
<view class="val">{{ sell.trialProduct || 0 }}</view>
</view>
<view class="item">
<view class="name">本月成交订单产品</view>
<view class="val">{{ sell.officialProduct || 0 }}</view>
</view>
</view>
</view>
</view>
<view class="panel">
<view class="title y-title" @click="toPanel(1)">
<view class="left">
<image class="icon" src="@/static/image/workbench/index9.png" mode="widthFix"></image>
年度经营分析
</view>
<image class="arrow" src="@/static/image/workbench/index10.png" mode="widthFix"></image>
</view>
<view class="data second">
<view class="line">
<view class="item item1">
<view class="val">{{ handleNum(analysis.finalPrice) }}</view>
<view class="name">总成交金额</view>
</view>
<view class="item item2">
<view class="val">{{ handleNum(analysis.settlementPrice) }}</view>
<view class="name">总结算金额</view>
</view>
<view class="item equal">
<view class="val">{{ handleNum(analysis.marketingServiceCharge) }}</view>
<view class="name">市场服务费</view>
</view>
<view class="item">
<view class="val">{{ handleNum(analysis.projectBenefit) }}</view>
<view class="name">项目收益</view>
</view>
</view>
</view>
</view>
<view v-if="!per" class="per-mask">功能升级中敬请期待...</view>
</view>
</template>
<script>
import { getUserRolesPermissionMenu } from '@/apis/modules/user.js'
import { getTeamsByAccountId, getTheBusinessManagerIdsUnderTheTeam } from '@/apis/modules/client.js'
import { treeList, salesProgress, annualOperatingAnalysis } from '@/apis/modules/parner.js'
import { partnerOperatingList } from '@/apis/modules/article.js'
export default {
data() {
return {
per: true, //
teamId: uni.getStorageSync('teamId') || '',
list: [],
id: '',
teamList: [],
studies: [],
sell: {},
analysis: {
finalPrice: 0,
settlementPrice: 0,
marketingServiceCharge: 0,
projectBenefit: 0,
},
headerTop: '8px',
}
},
onShow() {
// #ifdef MP-WEIXIN
this.headerTop = uni.getMenuButtonBoundingClientRect().top + 8 + 'px'
// #endif
this.per = true
if (uni.getStorageSync('token')) {
this.getInfo()
} else {
uni.redirectTo({
url: '/pages/login/login'
})
}
},
methods: {
//
initRole() {
if (!uni.getStorageSync('auth').includes('工作台')) {
this.per = false
}
this.getStudy()
this.getSell()
this.getAnalysis()
uni.hideLoading()
},
//
getAuth() {
getUserRolesPermissionMenu({
teamId: this.list.find(e => e.teamId == this.teamId).partnerClassificationId,
platformId: 4
}).then(({ permissionMenu }) => {
uni.hideLoading()
const auth = []
//
const generateAuth = (list, parent) => {
list.map(e => {
const name = `${parent ? parent + ':' : ''}${e.name}`
auth.push(name)
generateAuth(e.children, name)
})
}
generateAuth(permissionMenu[0].children, '')
uni.setStorageSync('auth', auth)
this.$forceUpdate()
this.initRole()
}).catch(e => {
uni.hideLoading()
uni.setStorageSync('auth', [])
this.initRole()
})
},
//
getInfo() {
uni.showLoading({
title: '加载中'
})
getTeamsByAccountId().then(({ data }) => {
data.map(e => {
const n = e.partnerClassificationList
e.id = n.id
// parnerIdidteamIduni.getStorageSync('team').partnerId使
e.teamId = e.isTeam == 1 ? +e.partnerClassificationId : n.id
e.partnerClassificationName = n.partnerClassificationName
delete e.partnerClassificationList
})
if (data.length) {
/**
* @description 如果是第一次进则默认选中第一个团队并把该团队的信息存入缓存
* 或者团队列表里没有该id则说明超管已经被转让也需要重新选中团队
*/
if (!uni.getStorageSync('team') || !data.find(e => e.teamId == this.teamId)) {
this.teamId = data[0].teamId
uni.setStorageSync('teamId', data[0].teamId)
uni.setStorageSync('team', data[0])
}
} else {
// 退
uni.hideLoading()
uni.clearStorageSync()
uni.redirectTo({
url: '../index/index'
})
}
this.list = data
this.getAuth()
}).catch(e => {
uni.hideLoading()
})
},
//
getStudy() {
partnerOperatingList({
topSort: 'desc',
pageNum: 1,
pageSize: 5,
querySource: 4,
typeId: 1,
}).then(({ page }) => {
this.studies = page
}).catch(e => {})
},
//
toStudy() {
this.$util.to('/team/study/study')
},
//
toDetail(item) {
this.$util.to(`/team/article/article?id=` + item.id)
},
//
getSell() {
salesProgress({
businessManagerId: uni.getStorageSync('team').partnerId,
teamId: this.teamId,
}).then(res => {
this.sell = res
}).catch(e => {})
},
// 10000 + w
handleNum(num) {
// return num ? parseInt(num / 10000) + 'w' : 0
return num
},
//
getAnalysis() {
annualOperatingAnalysis({
businessManagerId: uni.getStorageSync('team').partnerId,
teamId: this.teamId,
}).then(({ data }) => {
if (data) this.analysis = data
}).catch(e => {})
},
//
teamChange() {
const { teamId } = this
const e = this.list.find(e => e.teamId == teamId)
uni.setStorageSync('team', e)
uni.setStorageSync('teamId', teamId)
this.getAuth()
},
//
toModule(i) {
this.$uma.trackEvent(i) //
let path = '/order/clients/clients'
if (i === 'plan') {
path = '/team/plans/plans'
} else if (i === 'study') {
path = '/team/study/study'
} else if (i === 'info') {
path = '/team/info/info'
}
this.$util.to(path, { type: i })
},
//
toPanel(i) {
this.$util.errMsg('功能暂未开放!')
}
}
}
</script>
<style scoped lang="scss">
.page {
position: relative;
min-height: 100%;
padding: 0 22rpx 30rpx;
box-sizing: border-box;
}
.status-bar {
width: 100%;
// height: calc(var(--status-bar-height));
}
.bg {
z-index: -1;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.team {
position: relative;
width: 300rpx;
margin-bottom: 30rpx;
/deep/.selected-item text {
font-size: 30rpx;
font-weight: 600;
color: #5f5f5f;
}
}
.banner {
position: relative;
.img {
width: 100%;
}
.info {
position: absolute;
top: 80rpx;
left: 46rpx;
}
.title {
margin-bottom: 15rpx;
font-size: 36rpx;
font-weight: 600;
color: #001D67;
}
.text {
font-size: 20rpx;
font-family: PingFangSC-Regular, PingFang SC;
color: #001D67;
}
}
.entry {
display: flex;
justify-content: space-around;
align-items: center;
margin: 10rpx 0 30rpx;
text-align: center;
.icon {
width: 78rpx;
}
.info-icon {
width: 64rpx;
max-height: 64rpx;
}
.text {
font-size: 28rpx;
color: #333;
}
}
.panel {
margin: 20rpx 10rpx;
background-color: #fff;
border-radius: 20rpx;
overflow: hidden;
&.study-panel {
background-color: transparent;
}
.title {
display: flex;
justify-content: space-between;
align-items: center;
padding: 17rpx 20rpx;
background: linear-gradient(90deg, #E5EFFF 0%, #FFFFFF 100%);
}
.y-title {
background: linear-gradient(90deg, #FFF5E5 0%, #FFFFFF 100%);
}
.left {
display: flex;
align-items: center;
font-size: 30rpx;
color: #333;
}
.right {
display: flex;
align-items: center;
font-size: 28rpx;
color: #333;
text {
margin: 0 15rpx 0 8rpx;
}
}
.icon {
width: 36rpx;
margin-right: 10rpx;
}
.date {
width: 26rpx;
}
.arrow {
width: 16rpx;
}
.data {
padding: 33rpx 36rpx;
}
.line {
display: flex;
}
.first {
.item:first-child {
width: 65%;
}
.name {
margin-bottom: 14rpx;
font-size: 24rpx;
color: #999;
}
.val {
font-size: 30rpx;
color: #333;
}
.line:first-child {
margin-bottom: 32rpx;
}
}
.second {
padding: 38rpx 10rpx;
.item {
position: relative;
text-align: center;
&:after {
content: '';
position: absolute;
bottom: 14rpx;
right: -35rpx;
width: 22rpx;
height: 2px;
background-color: #ccc;
}
&.item1 {
margin-right: 53rpx;
}
&.item2 {
margin-right: 54rpx;
}
&.equal {
margin-right: 50rpx;
&:after {
bottom: 6rpx;
right: -39rpx;
height: 2px;
padding-bottom: 5px;
border-bottom: 2px solid #ccc;
background-clip:content-box;
box-sizing: content-box;
}
}
&:last-child:after {
display: none;
}
}
.val {
margin-bottom: 10rpx;
font-size: 30rpx;
color: #333;
}
.name {
font-size: 24rpx;
color: #999;
}
}
.study {
width: 100%;
margin-top: 15rpx;
overflow: auto;
.item {
display: inline-block;
width: 280rpx;
margin-right: 20rpx;
background-color: #fff;
border-radius: 8px;
overflow: hidden;
}
.pic {
width: 100%;
height: 130rpx;
}
.text {
padding: 15rpx;
font-size: 28rpx;
color: #333;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.scroll {
width: 100%;
white-space: nowrap;
}
}
.oh {
overflow: hidden;
}
</style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 775 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 599 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 439 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 840 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 319 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 727 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 844 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 572 B

After

Width:  |  Height:  |  Size: 528 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 654 B

After

Width:  |  Height:  |  Size: 620 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 B

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

Loading…
Cancel
Save