Compare commits

..

12 Commits

  1. 4
      .hbuilderx/launch.json
  2. 14
      apis/modules/article.js
  3. 4
      apis/modules/order.js
  4. 8
      apis/modules/parner.js
  5. 44
      apis/modules/product.js
  6. 4
      apis/modules/user.js
  7. 25
      apis/request.js
  8. 4
      config/request.js
  9. 28
      libs/util.js
  10. 198
      order/addCourse/addCourse.vue
  11. 37
      order/clientDetail/clientDetail.vue
  12. 2
      order/clients/clients.vue
  13. 8
      order/curClient/curClient.vue
  14. 119
      order/editCourse/editCourse.vue
  15. 602
      order/orderDetail/orderDetail.vue
  16. 55
      order/ordered/ordered.vue
  17. 13
      order/orders/orders.vue
  18. 108
      order/products/products.vue
  19. 117
      pages.json
  20. 8
      pages/index/index.vue
  21. 6
      pages/login/login.vue
  22. 2
      pages/person/person.vue
  23. 199
      pages/plans/plans.vue
  24. 8
      pages/teams/teams.vue
  25. BIN
      static/image/edit.png
  26. BIN
      static/image/unfold.png
  27. 8
      styles/common.scss
  28. 0
      team/account/account.vue
  29. 0
      team/addStaff/addStaff.vue
  30. 0
      team/editTeam/editTeam.vue
  31. 0
      team/email/email.vue
  32. 0
      team/password/password.vue
  33. 0
      team/phone/phone.vue
  34. 272
      team/plans/plans.vue
  35. 0
      team/qrcode/qrcode.vue
  36. 83
      team/scheme/scheme.vue
  37. 22
      team/send/send.vue
  38. 2
      team/setting/setting.vue
  39. 2
      team/teamDetail/teamDetail.vue
  40. 10
      uni_modules/uni-tooltip/changelog.md
  41. 70
      uni_modules/uni-tooltip/components/uni-tooltip/uni-tooltip.vue
  42. 83
      uni_modules/uni-tooltip/package.json
  43. 8
      uni_modules/uni-tooltip/readme.md

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

@ -0,0 +1,14 @@
import request from '@/apis/request.js'
const { get, post } = request
export const queryClassificationByType = id => {
return post('nakadai/nakadai/partner/article/classification/queryClassificationByType?typeId=' + id)
}
export const schemeList = data => {
return post('nakadai/nakadai/partner/schemeManagement/schemeList', data)
}
export const schemeFindById = id => {
return post('nakadai/nakadai/partner/schemeManagement/findById?id=' + id)
}

@ -48,3 +48,7 @@ export const publicConfiguration = (data) => {
export const bulkShipping = (data) => {
return post('nakadai/nakadai/orderOther/bulkShipping', data)
}
export const queryCitySettlementPrice = (mallId, provinceId, cityId) => {
return post(`nakadai/mallPrice/queryCitySettlementPrice?mallId=${mallId}&provinceId=${provinceId}&cityId=${cityId}`)
}

@ -40,3 +40,11 @@ export const queryTeamMembers = (data) => {
export const updatePartner = (data) => {
return post('nakadai/nakadai/partnerClassification/update', data)
}
export const editProvinceCity = data => {
return post(`nakadai/nakadai/partner-team/editProvinceCity`, data)
}
export const getPartnerTeamRates = data => {
return post(`nakadai/nakadai/partner-team/getPartnerTeamRates`, data)
}

@ -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)
}

@ -9,6 +9,10 @@ export const userBinding = (data) => {
return post('users/users/user/userBinding', data)
}
export const sendPhoneOrEmailCode = (data) => {
return post('users/users/userAccount/sendPhoneOrEmailCode', data)
}
export const queryProvince = () => {
return get('nakadai/nakadai/province/queryProvince')
}

@ -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')
})
@ -29,6 +20,7 @@ const request = options => {
if (status === 200) {
resolve(data)
} else if (status == 401) {
if (!logouted) {
// 登录过期
uni.clearStorageSync()
uni.showToast({
@ -36,11 +28,14 @@ const request = options => {
icon: 'none'
})
setTimeout(() => {
uni.navigateTo({
url: '../login/login'
logouted = 0
uni.reLaunch({
url: '/pages/index/index'
})
}, 1500)
reject(data)
logouted = 1
}
} else if (!status) {
resolve(data)
} else {
@ -58,12 +53,6 @@ const request = options => {
})
reject(err)
},
complete: () => {
if (config.showLoading) {
// HTTP_COUNT--
// HTTP_COUNT || uni.hideLoading()
}
}
})
})
}

@ -5,8 +5,8 @@
*/
export default {
baseURL: 'https://huorantech.cn/',
// baseURL: 'http://192.168.31.151:9000/',
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,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/1709798714897.docx', // 用户服务协议
'https://huoran.oss-cn-shenzhen.aliyuncs.com/1709798737175.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', // 金融科技
]
export default {
// 路由跳转
@ -67,9 +67,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
},
// 预览文档
openFile(id) {
@ -103,5 +103,17 @@ 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 , '')
},
}

@ -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">
<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 { productCategoryList, 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: '',
teamId: '',
curTab: '',
tabs: [
{
name: '全部',
id: ''
},
{
name: '实训课程',
id: 1
},
{
name: '理论课程',
id: 0
},
{
name: '数据产品',
id: 2
}
],
tabs: [],
reachBottom: 0, // 0->,1->,-1->
status: 'more', // more|loading|noMore
searchTimer: null,
@ -105,22 +98,38 @@
const { options } = pages[pages.length - 1]
this.orderType = options.orderType
this.customerId = options.customerId
this.provinceId = options.provinceId
this.cityId = options.cityId
this.teamId = options.teamId
this.getTypes()
this.getList()
},
methods: {
//
getTypes() {
productCategoryList().then(res => {
res.classificationList.forEach(e => {
e.id = e.classificationId
e.name = e.classificationName
})
this.tabs.push(...res.classificationList)
}).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,
productClassification: 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)
@ -196,35 +205,37 @@
}
})
},
//
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, //
typeName: e.typeName, //
periodOfUse: '', // 使
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 )
authority, // 01
options: 2,
miniProgramPictureAddress: e.miniProgramPictureAddress, //
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, //
typeName: e.typeName
}
},
//
@ -232,15 +243,14 @@
renew({
authority,
customerId,
productId
productId,
}).then(({ orderOthers }) => {
result.map(e => {
const item = orderOthers.find(n => n.dataOrCourseId == e.dataOrCourseId && n.authority == authority == e.authority)
const item = orderOthers.find(n => n.dataOrCourseId == e.dataOrCourseId && n.authority == authority && e.authority == authority)
if (item) {
let date = new Date(item.endTime)
date = new Date(date.setDate(date.getDate() + 1))
e.startTime = this.$util.formatDate(date, 'yyyy-MM-dd')
e.renew = 1
}
})
resolve()
@ -253,28 +263,69 @@
const list = this.checked //
if (list.length) {
const result = this.courses
const courseIds = []
const dataIds = []
console.log(123, result)
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
}
console.log(44, e)
const classId = e.classificationId
const pid = +e.associatedProduct
const mallId = e.mallId
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)
}))
list3.length && promises.push(new Promise((resolve, reject) => {
this.handleRenew(3, customerId, list3, result, resolve, reject)
}))
courseIds.length && promises.push(new Promise((resolve, reject) => {
this.handleRenew(1, customerId, courseIds, result, resolve, reject)
list4.length && promises.push(new Promise((resolve, reject) => {
this.handleRenew(4, customerId, list4, result, resolve, reject)
}))
Promise.all(promises).then(_ => {
uni.setStorageSync('courses', result) //
uni.redirectTo({
url: `../editCourse/editCourse?customerId=${customerId}&orderType=${this.orderType}&action=add`
url: `../editCourse/editCourse?customerId=${customerId}&orderType=${this.orderType}&teamId=${this.teamId}`
})
})
})
} else {
@ -289,6 +340,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;
@ -302,7 +363,10 @@
}
.icon {
width: 80rpx;
min-width: 80rpx;
height: 80rpx;
margin: 0 20rpx;
border-radius: 4px;
}
}
/deep/.check {

@ -37,27 +37,37 @@
<view :class="['line req', {err: err === 'name'}]">
<view class="name">联系人姓名</view>
<view v-if="isDetail" class="val">{{ form.name }}</view>
<input v-else type="text" placeholder="请输入" v-model="form.name" @change="handleErr('name')">
<template v-else>
<input type="text" placeholder="请输入" v-model="form.name" @change="handleErr('name')">
</template>
</view>
<view :class="['line req', {err: err === 'phone'}]">
<view class="name">手机</view>
<view v-if="isDetail" class="val">{{ form.phone }}</view>
<input v-else type="number" maxlength="11" placeholder="请输入" v-model="form.phone" @change="handleErr('phone')">
<template v-else>
<input type="number" maxlength="11" placeholder="请输入" v-model="form.phone" @change="handleErr('phone')">
</template>
</view>
<view :class="['line req', {err: err === 'account'}]">
<view class="name">账号</view>
<view v-if="isDetail" class="val">{{ form.account }}</view>
<input v-else type="text" placeholder="请以院校首字母+admin的格式来设置" v-model="form.account" @change="handleErr('account')">
<template v-else>
<input type="text" placeholder="请以院校首字母+admin的格式来设置" v-model="form.account" @change="handleErr('account')">
</template>
</view>
<view class="line">
<view class="name">职务</view>
<view v-if="isDetail" class="val">{{ form.position }}</view>
<input v-else type="text" placeholder="请输入" v-model="form.position">
<template v-else>
<input type="text" placeholder="请输入" v-model="form.position">
</template>
</view>
<view class="line">
<view class="name">邮箱</view>
<view v-if="isDetail" class="val">{{ form.email }}</view>
<input v-else type="text" placeholder="请输入" v-model="form.email">
<template v-else>
<input type="text" placeholder="请输入" v-model="form.email">
</template>
</view>
<view v-if="customerId" class="line">
<view class="name">产品到期时间</view>
@ -71,7 +81,7 @@
</view>
<view v-if="isDetail" class="action">
<view class="item" @click="toPage(`../clientDetail/clientDetail?customerId=${customerId}`)">
<view class="item" v-if="auth('客户管理:编辑')" @click="toPage(`../clientDetail/clientDetail?customerId=${customerId}`)">
<uni-icons class="icon" custom-prefix="iconfont" type="icon-edit" size="30" color="#959595"></uni-icons>
<view class="text">编辑</view>
</view>
@ -79,7 +89,7 @@
<uni-icons class="icon" custom-prefix="iconfont" type="icon-product" size="30" color="#959595"></uni-icons>
<view class="text">已订阅产品</view>
</view>
<view class="item" @click="toPage(`/order/curClient/curClient?customerId=${customerId}&name=${form.customerName}`)">
<view v-if="auth('订单管理')" class="item" @click="toPage(`/order/curClient/curClient?customerId=${customerId}&name=${form.customerName}`)">
<uni-icons class="icon" custom-prefix="iconfont" type="icon-dingdan" size="30" color="#959595"></uni-icons>
<view class="text">订单</view>
</view>
@ -355,4 +365,17 @@
margin-right: 10rpx;
}
}
.form-list {
.edit {
margin-left: 10rpx;
}
}
.editIcon {
width: 50rpx;
height: 50rpx;
margin-left: 20rpx;
image{
width: 100%;height: 100%
}
}
</style>

@ -33,7 +33,7 @@
</template>
<empty v-else text="您当前暂无有下单的客户,请快去给客户下订单吧"></empty>
<uni-icons class="plus" type="plus-filled" size="60" color="#007eff" @click="$util.to('../clientDetail/clientDetail')"></uni-icons>
<uni-icons class="plus" v-if="auth('客户管理:新增')" 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>
</template>

@ -12,6 +12,7 @@
v-for="item in list"
:threshold="0"
:right-options="delOption"
:disabled="!auth('订单管理:删除')"
@click="del(item)"
>
<view class="item" @click="toDetail(item)">
@ -54,7 +55,7 @@
</template>
<empty v-else></empty>
<uni-icons class="plus" type="plus-filled" size="60" color="#007eff" @click="$util.to(`../orderDetail/orderDetail?customerId=${customerId}`)"></uni-icons>
<uni-icons v-if="auth('订单管理:新建订单')" class="plus" type="plus-filled" size="60" color="#007eff" @click="$util.to(`../orderDetail/orderDetail?customerId=${customerId}`)"></uni-icons>
<filter-popup :data="filterData" :form.sync="filterForm" v-model="popup" title="全部筛选" height="1104rpx" @finsh="subFinsh"></filter-popup>
</view>
</template>
@ -133,6 +134,11 @@
this.customerId = options.customerId
this.customerName = options.name
this.initList()
//
try {
uni.removeStorageSync('courses')
uni.removeStorageSync('orderEdited')
} catch (e) {}
},
methods: {
getList() {

@ -1,11 +1,12 @@
<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="l-title">{{ c.name }}</view>
<uni-icons class="arrow" type="top" size="20" color="#007EFF" @click="toggle(c)"></uni-icons>
<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 +17,13 @@
<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="['line', {err: err === 'periodOfUse' + item.dataOrCourseId + item.authority}]">
<view class="name">使用期限</view>
<view class="period-wrap">
<input class="period" type="number" v-model="item.periodOfUse" placeholder="请输入" :disabled="isEdit" @input="calcDate(item, !item.authority)" @change="handleErr(item, 'periodOfUse')">
</view>
<view v-if="isEdit">{{ units.find(e => e.id === item.options).text }}</view>
<view v-else class="val unit" @click="selectUnit(item)">
<text>{{ units.find(e => e.id === item.options).text }}</text>
@ -30,20 +33,23 @@
<view :class="['line req', {err: err === 'startTime' + item.dataOrCourseId + item.authority}]">
<view class="name">起止日期</view>
<view v-if="isEdit">{{ item.endTime ? item.startTime + ' - ' + item.endTime : item.startTime}}</view>
<uni-datetime-picker v-else type="date" v-model="item.startTime" :border="false" @change="calcDate(item)">
<view v-else class="val unit">
<uni-datetime-picker type="date" v-model="item.startTime" :border="false" @change="calcDate(item)">
<view :class="['ph', {val: item.startTime}]">
{{ item.endTime ? item.startTime + ' - ' + item.endTime : item.startTime}}
</view>
</uni-datetime-picker>
<image class="icon" src="@/static/image/arrow-down.png" mode="widthFix"></image>
</view>
</view>
<view :class="['line req', {err: err === 'accountNum' + item.dataOrCourseId + item.authority}]">
<view class="name">数量</view>
<view v-if="item.authority" class="val">1</view>
<view v-if="item.authority" class="ph">1</view>
<input v-else type="number" v-model="item.accountNum" placeholder="请输入账号数量" @input="calcFinalPrice(item)" @change="handleErr(item, 'accountNum')">
</view>
<view class="line">
<view class="name">{{ item.authority ? '市场价' : '市场单价' }}</view>
<view class="val">{{ item.marketValue }}</view>
<view class="ph">{{ item.marketValue }}</view>
</view>
<view class="line">
<view class="name">结算价</view>
@ -54,11 +60,11 @@
</view>
<view class="line">
<view class="name">折扣率</view>
<view class="val">{{ item.discountRate }}</view>
<view class="ph">{{ item.discountRate }}</view>
</view>
<view class="line">
<view class="name">平台服务费</view>
<view class="val">{{ item.serviceFee }}</view>
<view class="ph">{{ item.serviceFee }}</view>
</view>
<view :class="['line req', {err: err === 'finalPrice' + item.dataOrCourseId + item.authority}]">
<view class="name">成交价</view>
@ -69,6 +75,7 @@
</view>
</view>
</view>
</template>
</view>
</view>
</template>
@ -80,6 +87,8 @@
<script>
import { getOrderOtherTime } from '@/apis/modules/order.js'
import { getPartnerTeamRates } from '@/apis/modules/parner.js'
import { productCategoryList, productTypeList } from '@/apis/modules/product.js'
export default {
data() {
return {
@ -89,6 +98,7 @@
isRenew: 0, //
orderType: 1,
customerId: '',
teamId: '',
timer: null,
units: [{
text: '日',
@ -101,24 +111,12 @@
id: 2
}],
unitText: ['日', '月', '年'],
productTypes: [
{
name: '实训课程',
id: 1
},
{
name: '理论课程',
id: 0
},
{
name: '数据产品',
id: 2
}
],
productTypes: [],
courses: {} , //
orderRepeat: [],
repeatMsg: '',
err: ''
err: '',
rate: ''
}
},
onShow() {
@ -130,40 +128,34 @@
this.isHandle = options.action === 'handle'
this.isRenew = options.action === 'renew'
this.isAdd = options.action === 'add'
this.teamId = options.teamId
this.handleProduct()
this.teamId && this.getRate()
},
methods: {
//
handleProduct() {
//
productTypeList().then(res => {
this.productTypes = res.typeList
}).catch(e => {})
const list = uni.getStorageSync('courses')
const courses = {
practice: {
shrink: false,
name: '实训课程产品',
list: []
},
theory: {
let courses = {}
//
productCategoryList().then(res => {
res.classificationList.forEach(e => {
courses['list' + this.$util.getOrderType(e.classificationId)] = {
shrink: false,
name: '理论课程产品',
name: e.classificationName,
list: []
},
data: {
shrink: false,
name: '数据产品',
list: []
}
}
// 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)
courses['list' + e.authority].list.push(e)
})
this.courses = courses
}).catch(e => {})
try {
uni.removeStorageSync('courses')
} catch (e) {}
@ -258,15 +250,15 @@
},
//
dealSettlePrice(row) {
// 0
if (this.orderType == 2) {
// 0
console.log('dealSettlePrice=>', row, this.orderType)
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 ?
@ -276,17 +268,19 @@
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.settlementPrice * 0.1).toFixed(2)
}
//
row.serviceFee = (row.finalPrice * (this.rate / 100)).toFixed(2)
}
},
//
getRate() {
getPartnerTeamRates({
teamId: this.teamId
}).then(({ teamRates }) => {
this.rate = teamRates.annualMarketingFee || 0
}).catch(res => {})
},
//
calcDiscount(row) {
const price = row.authority ? row.finalPrice : row.finalValue
@ -372,10 +366,12 @@
msg = '请输入成交价!'
break
}
e.edited = 1 //
}
if (msg) return this.$util.errMsg(msg)
if (this.orderRepeat.length) return this.$util.errMsg(this.repeatMsg) //
uni.setStorageSync('courses', this.courses)
uni.setStorageSync('orderEdited', 1)
uni.navigateBack()
},
}
@ -421,7 +417,13 @@
.form-list {
padding: 0 24rpx;
border-top: 0;
.period-wrap {
display: inline-flex;
align-items: center;
}
.period {
flex: none;
width: 100rpx;
text-align: center;
}
.unit {
@ -432,5 +434,8 @@
margin-left: 20rpx;
}
}
.edit {
margin-left: 10rpx;
}
}
</style>

@ -1,30 +1,32 @@
<template>
<view :class="['page', { show: isDetail }]">
<view :class="['page', { show: isDetail && (form.isDel !== 1 && (auth('订单管理:修改') || (form.orderStatus === 1 && auth('订单管理:续费'))) || auth('订单管理:删除')) }]">
<view class="block">
<view class="l-title">基本信息</view>
<view class="form-list">
<view :class="['line req', {err: err === 'customerName'}]">
<view class="name">客户名称</view>
<view v-if="orderId" class="val">{{ form.customerName }}</view>
<view v-else :class="['ph', {val: form.customerName}]" @click="customerVisible = true">{{ form.customerName || '请选择客户' }}</view>
<view v-else class="customer-wrap">
<view :class="['ph', {val: form.customerName}]" @click="customerVisible = true">{{ form.customerName || '请选择客户' }}</view>
</view>
<view class="line">
</view>
<view class="line" v-if="form.customerName">
<view class="name">省份</view>
<view class="val">{{ form.provinceName }}</view>
</view>
<view class="line">
<view class="line" v-if="form.customerName">
<view class="name">城市</view>
<view class="val">{{ form.cityName }}</view>
</view>
<view class="line">
<view class="line" v-if="form.customerName">
<view class="name">联系人</view>
<view class="val">{{ form.orderContact }}</view>
</view>
<view class="line">
<view class="line" v-if="form.customerName">
<view class="name">电话</view>
<view class="val">{{ form.phone }}</view>
</view>
<view class="line">
<view class="line" v-if="form.customerName">
<view class="name">邮箱</view>
<view class="val">{{ form.email }}</view>
</view>
@ -43,6 +45,7 @@
<view v-if="isDetail" class="val">{{ form.businessManagerName }}</view>
<uni-data-picker v-else class="picker-input" placeholder="请选择商务经理" popup-title="请选择商务经理" preload :localdata="bms" :map="{text: 'userName', value: 'partnerId'}" v-model="form.businessManagerId" :readonly="form.teamId ? false : true"></uni-data-picker>
</view>
<template v-if="edited">
<view class="line">
<view class="name">订单编号</view>
<view class="val">{{ form.orderNumber }}</view>
@ -55,6 +58,7 @@
<view class="name">订单金额</view>
<view class="val">{{ form.orderAmount }}</view>
</view>
</template>
</view>
</view>
@ -63,7 +67,8 @@
<view class="l-title">{{ c.name }}</view>
<uni-icons class="arrow" type="top" size="20" color="#007EFF" @click="toggle(c)"></uni-icons>
<ul class="pro-list" v-show="!c.shrink">
<li v-for="(item, i) in c.list" :key="i" @click.stop="editCourse(c, i)">
<!-- <li v-for="(item, i) in c.list" :key="i" @click.stop="editCourse(c, i)"> -->
<li v-for="(item, i) in c.list" :key="i">
<view class="name">
<view class="left">
<image class="icon" :src="$util.getIcon(item)" mode="widthFix"></image>
@ -73,35 +78,71 @@
<!-- 1查看时不可操作
2发货和启用不要同时出现生效前只会显示发货不发货按钮生效后只显示禁启用按钮
3处理中的订单显示发货不显示禁用 -->
<button v-if="item.status === 1 || isHandle || !orderId" class="course-btn" type="primary" @click.stop="handleDeliver(n, i)">{{ item.ship ? '取消' : ''}}发货</button>
<button v-else-if="!isDetail" class="course-btn" type="primary" @click.stop="handleEnable(n, i)">{{ item.isEnable ? '禁用' : '启用'}}</button>
<image v-if="!orderId || isRenew" class="del" src="@/static/image/trash.png" mode="widthFix" @click.stop="delCourse(c, i)"></image>
<template v-if="!isDetail && (item.ship == 0 || isHandle || !orderId)">
<button v-if="auth('订单管理:发货')" class="course-btn" type="primary" @click.stop="handleDeliver(n, i)">{{ item.ship ? '取消' : ''}}发货</button>
</template>
<button v-else-if="!isDetail && auth('订单管理:启用')" class="course-btn" type="primary" @click.stop="handleEnable(n, i)">{{ item.isEnable ? '禁用' : '启用'}}</button>
<button v-if="auth('订单管理:发货') && (item.authority == 0 || item.authority == 3 || item.authority == 4) && (!isDetail || (isDetail && item.shipContent))" class="course-btn mg" type="primary" @click.stop="showShip(item)">发货信息</button>
<image v-if="!orderId || isRenew || isHandle" class="del" src="@/static/image/trash.png" mode="widthFix" @click.stop="delCourse(c, i)"></image>
</view>
</view>
<view class="info">
<view class="line">
<view class="label">起始日期</view>
<!-- <view class="val">{{ item.startTime + (item.endTime && ' - ' + item.endTime) }}</view> -->
<view v-if="isDetail || isEdit" class="ph">{{ item.endTime ? item.startTime + ' - ' + item.endTime : item.startTime}}</view>
<uni-datetime-picker v-else type="date" v-model="item.startTime" :border="false" @change="calcDate(item)">
<view :class="['ph', {val: item.startTime}]">
{{ item.endTime ? item.startTime + ' - ' + item.endTime : item.startTime}}
</view>
</uni-datetime-picker>
</view>
<view class="line" :class="[ {err: err === 'periodOfUse' + item.dataOrCourseId + item.authority}]">
<view class="label">使用期限</view>
<view class="val">{{ item.startTime + (item.endTime && ' - ' + item.endTime) }}</view>
<view v-if="isDetail || isEdit" class="ph">{{item.periodOfUse}}{{ units.find(e => e.id === item.options).text }}</view>
<template v-else>
<input class="period" type="number" v-model="item.periodOfUse" placeholder="请输入" @input="calcDate(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>
</view>
</template>
</view>
<view :class="['line req', {err: err === 'accountNum' + item.dataOrCourseId + item.authority}]">
<view class="label">数量</view>
<view v-if="item.authority || (!item.authority && isDetail)" class="ph">1</view>
<view v-else class="inline">
<input type="number" v-model="item.accountNum" placeholder="请输入账号数量" @input="calcFinalPrice(item)" @change="handleErr(item, 'accountNum')">
</view>
</view>
<view class="line">
<view class="label">市场价</view>
<view class="val">{{ item.marketValue || 0 }}</view>
<view class="label">{{ item.authority ? '市场价' : '市场单价' }}</view>
<view class="ph">{{ item.marketValue && item.marketValue + '元' }}</view>
</view>
<view class="line">
<view class="label">结算价</view>
<view class="val">{{ item.settlementPrice }}</view>
<view v-if="isDetail" class="ph">{{ item.settlementPrice }}</view>
<view class="inline" v-else>
<input type="number" v-model="item.settlementPrice" placeholder="请输入" @change="handleErr(item, 'settlementPrice')" @input="updateServiceFee(item)">
</view>
</view>
<view class="line">
<view class="label">折扣率</view>
<view class="val">{{ item.discountRate }}</view>
<view class="ph">{{ item.discountRate }}</view>
</view>
<view class="line">
<view class="label">平台服务费</view>
<view class="val">{{ item.serviceFee }}</view>
<view class="ph">{{ item.serviceFee }}</view>
</view>
<view :class="['line req', {err: err === 'finalPrice' + item.dataOrCourseId + item.authority}]">
<view class="label">成交价</view>
<view v-if="isDetail" class="ph">{{ item.finalPrice }}</view>
<view class="inline" v-else>
<input type="number" v-model="item.finalPrice" placeholder="请输入" @input="calcFinalValue(item)" @change="handleErr(item, 'finalPrice')">
</view>
<view class="line done">
<view class="val">成交价格</view>
<view class="price">{{ item.finalPrice }}</view>
</view>
</view>
</li>
@ -110,8 +151,14 @@
</template>
<view class="bottom">
<view v-if="!orderId" class="add-wrap">
<view class="add-btn" @click="toAdd">
<template v-if="!edited && !orderId">
<view class="next-wrap">
<view class="lg-btn next" @click="toAdd(0)">下一步</view>
</view>
</template>
<template v-else>
<view v-if="!orderId || isHandle" class="add-wrap">
<view class="lg-btn" @click="toAdd">
<uni-icons class="icon" type="plus" color="#007FFF"></uni-icons>
添加产品
</view>
@ -134,15 +181,16 @@
</view>
<view class="product-btns">
<view v-if="!isDetail" class="btn" @click="submit">提交({{ courses.length }})</view>
<view v-if="isHandle || (!orderId && courses.length)" class="btn" @click="batchDeliver">{{ courses.find(e => !e.ship) ? '一键发货' : '取消全部发货' }}</view>
<view v-if="auth('订单管理:发货') && (isHandle || (!orderId && courses.length))" class="btn" @click="batchDeliver">{{ courses.find(e => !e.ship) ? '一键发货' : '取消全部发货' }}</view>
</view>
</view>
</template>
</view>
<view v-if="isDetail" class="action">
<template v-if="form.isDel !== 1">
<template v-if="form.orderStatus === 1">
<view class="item" @click="toAction(`../orderDetail/orderDetail?orderId=${orderId}&action=edit`)">
<view class="item" v-if="auth('订单管理:修改')" @click="toAction(`../orderDetail/orderDetail?orderId=${orderId}&action=edit`)">
<uni-icons class="icon" custom-prefix="iconfont" type="icon-edit" size="30" color="#959595"></uni-icons>
<view class="text">修改</view>
</view>
@ -151,12 +199,12 @@
<view class="text">续费</view>
</view>
</template>
<view v-else class="item" @click="toAction(`../orderDetail/orderDetail?orderId=${orderId}&action=handle`)">
<view v-else-if="auth('订单管理:修改')" class="item" @click="toAction(`../orderDetail/orderDetail?orderId=${orderId}&action=handle`)">
<uni-icons class="icon" custom-prefix="iconfont" type="icon-edit" size="30" color="#959595"></uni-icons>
<view class="text">处理</view>
</view>
</template>
<view class="item" @click="del">
<view v-if="auth('订单管理:删除')" class="item" @click="del">
<uni-icons class="icon" type="trash-filled" size="30" color="#959595"></uni-icons>
<view class="text">删除</view>
</view>
@ -167,17 +215,35 @@
<view class="top">请选择客户</view>
<uni-icons class="close" type="closeempty" size="20" @click="closeCustomer"></uni-icons>
<uni-search-bar class="search" radius="5" placeholder="请输入客户名称" v-model="keyword" clearButton="auto" cancelButton="none" />
<view class="create" @click="toClient">找不到客户马上创建</view>
<view class="list">
<view class="item" v-for="item in customerList" @click="customerChange(item)">{{ item.customerName }}</view>
</view>
</view>
<uni-popup ref="info" type="bottom" background-color="#fff">
<view class="ship-info">
<view v-if="isDetail" class="ship-text" v-html="shipContent" @click="copy"></view>
<template v-else>
<uni-easyinput type="textarea" focus v-model="shipContent" placeholder="请填写需交付的产品登录地址、账号、密码等内容...(300个字以内)" maxlength="300"></uni-easyinput>
<view v-if="shipInfo" class="ship-links">
<view>产品链接</view>
<view class="tooltip" @click="copy">{{ shipInfo }}</view>
</view>
</template>
</view>
<view v-if="!isDetail" class="ship-btns">
<button @click.stop="closeShip">取消</button>
<button type="primary" @click.stop="submitShip">确定</button>
</view>
</uni-popup>
</view>
</template>
<script>
import { queryCustomer, queryCustomerDetails } from '@/apis/modules/client.js'
import { add, update, del, getDetail, renew, ship, miniProgramOrderRecord, bulkShipping } from '@/apis/modules/order.js'
import { teamList, getAllTeam } from '@/apis/modules/parner.js'
import { add, update, del, getDetail, renew, ship, miniProgramOrderRecord, bulkShipping, getOrderOtherTime, queryCitySettlementPrice } from '@/apis/modules/order.js'
import { teamList, getAllTeam, getPartnerTeamRates } from '@/apis/modules/parner.js'
import { productCategoryList } from '@/apis/modules/product.js'
export default {
data() {
return {
@ -185,6 +251,7 @@
isEdit: 0, //
isHandle: 0, //
isRenew: 0, //
edited: false,
orderId: '',
orderTypes: [{
text: '正式',
@ -193,6 +260,7 @@
text: '试用',
value: 2
}],
form: {
businessManagerId: '',
businessManagerName: '',
@ -234,6 +302,23 @@
customerListAll: [],
err: '',
promises: [],
orderRepeat:[],
units: [{
text: '日',
id: 0
}, {
text: '月',
id: 1
}, {
text: '年',
id: 2
}],
unitText: ['日', '月', '年'],
rate: '',
shipInfo: '',
shipContent: '',
curRow: {}
}
},
watch: {
@ -253,6 +338,7 @@
this.isEdit = action === 'edit'
this.isHandle = action === 'handle'
this.isRenew = action === 'renew'
this.edited = uni.getStorageSync('orderEdited')
const store = uni.getStorageSync('courses')
this.getTeam(!store)
if (store) {
@ -263,22 +349,21 @@
}
this.courseList = store
this.courses = list
this.$nextTick(() => {
uni.pageScrollTo({
selector: '#products',
})
})
// this.$nextTick(() => {
// uni.pageScrollTo({
// selector: '#products',
// })
// })
try {
uni.removeStorageSync('courses')
} catch (e) {}
this.calcTotal()
} else {
}
// id
const { customerId } = options
customerId && this.customerChange({
customerId
})
}
//
this.isDetail || this.getCustomer()
//
@ -308,14 +393,17 @@
const item = this.teams.find(e => e.id == teamId)
if (item) this.form.partnerClassificationName = item.partnerClassificationName
if (!this.isDetail) {
this.form.businessManagerId = +this.form.businessManagerId
if (this.form.businessManagerId) this.form.businessManagerId = +this.form.businessManagerId
this.getBm()
}
}
order.orderOther.forEach(e => {
e.settlementPriceUnit = e.settlementPrice
})
this.courses = order.orderOther
this.handleRenew(0)
this.handleRenew(1)
this.handleRenew(2)
for (let i = 0; i < 5; i++) {
this.handleRenew(i)
}
Promise.all(this.promises).then(_ => {
this.handleProduct(this.courses)
this.calcTotal()
@ -327,47 +415,38 @@
},
//
handleProduct(list) {
const courses = {
practice: {
let courses = {}
//
productCategoryList().then(res => {
res.classificationList.forEach(e => {
courses['list' + this.$util.getOrderType(e.classificationId)] = {
shrink: false,
name: '实训课程产品',
list: []
},
theory: {
shrink: false,
name: '理论课程产品',
list: []
},
data: {
shrink: false,
name: '数据产品',
name: e.classificationName,
list: []
}
}
// 3push(0-> 1- 2 )
})
list.map(e => {
e.serviceFee = (e.settlementPrice * 0.1).toFixed(2)
const type = e.productType
!type ?
courses.theory.list.push(e) :
type === 1 ?
courses.practice.list.push(e) :
courses.data.list.push(e)
e.serviceFee = (e.finalPrice * (this.rate / 100)).toFixed(2) // != 0 &&
courses['list' + e.authority].list.push(e)
})
this.courseList = courses
}).catch(e => {})
},
// pc
handleRenew(authority) {
const productId = this.courses.filter(e => e.authority == authority).map(e => e.dataOrCourseId)
const list = this.courses.filter(e => e.authority == authority)
const productId = list.map(e => e.mallId)
productId.length && this.promises.push(new Promise((resolve, reject) => {
renew({
authority,
customerId: this.form.customerId,
productId
productId,
}).then(({ orderOthers }) => {
const { courses } = this
const now = new Date()
orderOthers.map(e => {
// e.settlementPriceUnit = e.settlementPrice
const item = courses.find(n => n.dataOrCourseId == e.dataOrCourseId && n.authority == authority && e.authority == authority)
if (item) {
if (this.isRenew) { //
@ -454,25 +533,53 @@
this.keyword = ''
},
//
customerChange(item) {
async customerChange(item) {
const { form } = this
//
queryCustomerDetails({
const { result } = await queryCustomerDetails({
customerId: item.customerId
}).then(({ result }) => {
})
this.handleErr('customerName')
const e = result.customer
const { provinceId, cityId } = e
form.customerId = e.customerId
form.customerName = e.customerName
form.provinceId = e.provinceId
form.cityId = e.cityId
form.provinceId = provinceId
form.cityId = cityId
form.provinceName = e.provinceName
form.cityName = e.cityName
form.phone = e.phone
form.email = e.email
form.orderContact = e.name
}).catch(e => {})
//
const list = this.courseList
const courses = []
const promises = []
for (const i in list) {
list[i].list.forEach(n => {
promises.push(new Promise(async (resolve, reject) => {
const res = await queryCitySettlementPrice(n.mallId, provinceId, cityId)
n.settlementPriceUnit = res.mallPrice ? res.mallPrice.discountRate : 0
courses.push(n)
resolve()
}))
})
}
Promise.all(promises).then(_ => {
this.courses = courses
this.calcTotal()
this.closeCustomer()
})
},
//
getRate() {
getPartnerTeamRates({
teamId: this.form.teamId
}).then(({ teamRates }) => {
this.rate = teamRates.annualMarketingFee || 0
this.calcTotal()
}).catch(res => {})
},
//
getTeam(getInfo) {
@ -483,6 +590,7 @@
},
//
getBm() {
this.getRate()
teamList({
pageNum: 1,
pageSize: 1000,
@ -495,17 +603,27 @@
//
toAdd() {
uni.setStorageSync('courses', this.courses)
uni.setStorageSync('orderForm', this.form)
const { customerId, orderType } = this.form
customerId ?
this.$util.to(`../addCourse/addCourse?orderType=${orderType}&customerId=${customerId}`) :
this.$util.to(`../addCourse/addCourse?orderType=${orderType}&customerId=${customerId}&provinceId=${this.form.provinceId}&cityId=${this.form.cityId}&teamId=${this.form.teamId || ''}`) :
this.$util.errMsg('请先选择客户!')
},
//
editCourse(c, i) {
if (this.isDetail) return false
uni.setStorageSync('courses', this.courses)
uni.setStorageSync('orderForm', this.form)
const { customerId, orderType } = this.form
this.$util.to(`../editCourse/editCourse?orderType=${orderType}&customerId=${customerId}&action=${this.isEdit ? 'edit' : this.isRenew ? 'renew' : this.isHandle ? 'handle' : !this.orderId ? 'add' : ''}`)
this.$util.to(`../editCourse/editCourse?orderType=${orderType}&customerId=${customerId}&action=${this.isEdit ? 'edit' : this.isRenew ? 'renew' : this.isHandle ? 'handle' : !this.orderId ? 'add' : ''}&teamId=${this.form.teamId || ''}`)
},
//
toClient() {
uni.setStorageSync('courses', this.courseList)
uni.redirectTo({
url: `/order/clientDetail/clientDetail`
})
// this.$util.to(`/order/clientDetail/clientDetail`)
},
//
delCourse(c, i) {
@ -541,13 +659,13 @@
handleDeliver(c, i) {
const row = this.courseList[c].list[i]
row.ship = row.ship ? 0 : 1
this.isEdit && ship(row).then(res => {}).catch(res => {}) //
if (row.ship == 1) row.isEnable = 1 //
},
//
calcTotal(out) {
this.handleErr('orderType')
const { form } = this
const isTrial = form.orderType === 2 //
const isTrial = form.orderType == 2 //
let total = 0
const list = this.courses
let purchase = 0 //
@ -566,12 +684,16 @@
list.map(e => {
// out=1 && 0
if (out && isTrial) {
console.log(123, e, out, isTrial)
e.settlementPrice = 0
e.serviceFee = 0
e.finalPrice = 0
e.finalValue = 0
e.discountRate = '0%'
} else {
this.calcDiscount(e)
this.dealSettlePrice(e)
// this.calcFinalPrice(e)
const curPurchase = +e.settlementPrice + +e.serviceFee
purchase += curPurchase
profit += +e.finalPrice - curPurchase
@ -579,7 +701,55 @@
})
form.purchaseCost = Math.round(purchase)
form.profit = Math.round(profit)
form.orderAmount = +form.purchaseCost + +form.profit
form.orderAmount = (+form.purchaseCost + +form.profit).toFixed(2)
console.log(111, this.courseList, this.courses)
},
//
calcAmount() {
const { form } = this
const list = this.courses
let purchase = 0 //
let profit = 0 //
list.map(e => {
const curPurchase = +e.settlementPrice + +e.serviceFee
purchase += curPurchase
profit += +e.finalPrice - curPurchase
})
form.purchaseCost = Math.round(purchase)
form.profit = Math.round(profit)
form.orderAmount = (+form.purchaseCost + +form.profit).toFixed(2)
console.log(111, this.courseList, this.courses)
},
//
showShip(row) {
this.curRow = row
let val = ''
row.mallNonAssociatedLinks && row.mallNonAssociatedLinks.forEach(e => {
val += e.urlName + ':' + e.url + '\n'
})
this.shipInfo = val
this.shipContent = row.shipContent || val
this.$refs.info.open()
},
//
closeShip() {
this.$refs.info.close()
},
//
submitShip() {
if (this.shipContent.length > 300) return this.$util.errMsg('请填写300个字以内!')
this.curRow.shipContent = this.shipContent
this.$refs.info.close()
},
//
copy() {
const that = this
uni.setClipboardData({
data: that.isDetail ? that.shipContent : this.shipInfo,
success() {
that.$util.sucMsg('复制成功')
}
})
},
//
handleErr(val) {
@ -611,12 +781,154 @@
for (const i in list) {
list[i].list.forEach(e => {
e.ship = ship
if (e.ship == 1) e.isEnable = 1
courses.push(e)
})
}
this.courses = courses
this.isEdit && bulkShipping({orderOthers: courses}).then(res => {}).catch(res => {}) //
},
calcDate(row, fromData) {
clearTimeout(this.timer)
this.timer = setTimeout(() => {
const { periodOfUse, options } = row
let optionsData = 0
if (periodOfUse) {
if (options == 1){
optionsData = periodOfUse === '12' ? 31536000000 : periodOfUse*30*24*60*60*1000
} else if (options == 2){
optionsData = periodOfUse*365*24*60*60*1000
} else {
optionsData = periodOfUse*24*60*60*1000
}
}
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
let endYears = endYear/1000/60/60/24
row.remainingPeriod = endYears
const unit = row.options // 使
const useUnit = row.periodOfUse // 使
//
const price = row.marketPrice || 0 //
// //365,/12)
row.marketValue = (!unit ?
price / 365 * useUnit :
unit === 1 ?
price / 12 * useUnit :
price * useUnit).toFixed(2)
this.dealSettlePrice(row)
// +1
if (!fromData) {
const cId = row.dataOrCourseId
const date = new Date(row.startTime)
const orderRepeat = this.orderRepeat
getOrderOtherTime({
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)
if (res.endTime) {
let time = new Date(res.endTime)
time = new Date(time.setDate(time.getDate() + 1))
row.startTime = this.$util.formatDate(time, 'yyyy-MM-dd')
}
}).catch(res => {
this.repeatMsg = res.message
orderRepeat.includes(cId) || orderRepeat.push(cId)
})
}
//
this.calcDiscount(row)
}, 500)
},
dealSettlePrice(row) {
// 0
if (this.form.orderType != 1) {
row.settlementPrice = 0
row.serviceFee = 0
} else {
const unit = row.options // 使
const useUnit = row.periodOfUse // 使
let sPrice = ''
// **/**(1)
const priceUnit = row.settlementPriceUnit
sPrice = ((!unit ?
priceUnit / 365 * useUnit :
unit === 1 ?
priceUnit / 12 * useUnit :
priceUnit * useUnit) * (row.authority ?
1 :
row.accountNum)).toFixed((2))
row.settlementPrice = this.$util.handleNaN(sPrice)
//
row.serviceFee = (row.finalPrice * (this.rate / 100)).toFixed(2)
this.calcAmount()
console.log('row.settlementPrice =>' ,row.settlementPrice,row.settlementPriceUnit,sPrice,row)
}
},
calcDiscount(row) {
const price = row.authority ? row.finalPrice : row.finalValue
const { marketValue } = row
// (-)÷ x100%
if (price) row.discountRate = marketValue != 0 ? ((marketValue - price) / marketValue * 100).toFixed(2) + '%' : '0%'
},
selectUnit(item) {
const that = this
uni.showActionSheet({
title: '标题',
itemList: that.unitText,
success: ({ tapIndex }) => {
item.options = tapIndex
that.calcDate(item)
}
})
},
// ////
calcFinalValue(row) {
clearTimeout(this.timer)
this.timer = setTimeout(() => {
const { authority, periodOfUse, options, accountNum, finalPrice } = row
if (!authority && periodOfUse && accountNum && finalPrice) {
row.finalValue = (finalPrice / accountNum / periodOfUse).toFixed(2)
}
//
this.calcDiscount(row)
this.dealSettlePrice(row)
}, 500)
},
// **//
calcFinalPrice(row) {
clearTimeout(this.timer)
this.timer = setTimeout(() => {
const { finalValue, accountNum, periodOfUse, finalPrice } = row
if (periodOfUse) {
if (accountNum) {
// =**
if (finalValue) {
row.finalPrice = Math.round(finalValue * periodOfUse * accountNum)
} else if (!finalValue && finalPrice) {
// =//
row.finalValue = (finalPrice / periodOfUse / accountNum).toFixed(2)
this.calcDiscount(row)
}
} else if (finalValue && finalPrice && !row.authority) {
// =//
row.accountNum = Math.floor(finalPrice / periodOfUse / finalValue)
}
}
this.dealSettlePrice(row)
}, 500)
},
//
updateServiceFee(row) {
options.serviceFee = (row.finalPrice * (this.rate / 100)).toFixed(2)
},
//
submit() {
const { form } = this
@ -664,18 +976,20 @@
})
} else {
add(data).then(res => {
// form.orderOther.find(e => !e.ship) || this.publicNotice(form, orderId) //
uni.hideLoading()
this.$util.sucMsg('添加成功')
setTimeout(() => {
// this.$util.to(`../orders/orders`)
uni.navigateBack()
// uni.redirectTo({
// url: `../orders/orders`
// })
}, 1500)
}).catch(res => {
uni.hideLoading()
})
}
}
},
}
}
</script>
@ -690,6 +1004,17 @@
bottom: 100rpx;
}
}
.form-list {
.customer-wrap {
text-align: right;
}
}
.create {
padding: 0 20rpx;
font-size: 20rpx;
text-align: right;
color: #f00;
}
.pro-wrap {
position: relative;
padding: 0;
@ -715,6 +1040,8 @@
.left {
display: inline-flex;
align-items: center;
max-width: 480rpx;
margin-right: 10rpx;
}
.course-action {
display: inline-flex;
@ -724,6 +1051,10 @@
padding: 0 16rpx;
margin-right: 10rpx;
font-size: 28rpx;
white-space: nowrap;
&.mg {
margin-left: 10rpx;
}
}
.del {
width: 40rpx;
@ -740,11 +1071,18 @@
.line {
display: flex;
justify-content: space-between;
padding: 12rpx 0;
margin: 5px 0;
padding: 28rpx 0;
font-size: 12px;
border-bottom: 1px solid #E6E8ED;
&:last-child {
border-bottom: 0;
}
}
.label {
font-size: 28rpx;
color: #333;
}
.ph {
font-size: 28rpx;
color: #999;
}
@ -763,8 +1101,15 @@
font-size: 32rpx;
color: #007EFF;
}
.period {
flex: none;
width: 100rpx;
font-size: 28rpx;
text-align: center;
}
}
.bottom {
z-index: 2;
position: fixed;
bottom: 0;
padding-bottom: env(safe-area-inset-bottom);
@ -772,12 +1117,14 @@
background-color: #fff;
box-shadow: 0 -2px 2px #f5f5f5;
box-sizing: border-box;
}
.add-wrap {
padding: 16rpx 24rpx 40rpx;
background-color: #f5f5f5;
}
/deep/.add-btn {
.next-wrap {
padding: 24rpx 24rpx 0;
}
/deep/.lg-btn {
display: flex;
justify-content: center;
align-items: center;
@ -793,6 +1140,11 @@
.uni-icons {
font-size: 38rpx !important;
}
&.next {
color: #fff;
background-color: #007EFF;
}
}
}
.product {
display: flex;
@ -852,17 +1204,101 @@
.product-btns {
display: inline-flex;
align-items: center;
margin-left: 20rpx;
margin-left: 10rpx;
}
.btn {
padding: 0 20rpx;
margin-left: 16rpx;
margin-left: 8rpx;
line-height: 80rpx;
font-size: 30rpx;
font-size: 26rpx;
text-align: center;
color: #fff;
white-space: nowrap;
border-radius: 10rpx;
background-color: #007EFF;
}
}
.unit {
display: inline-flex;
align-items: center;
.icon {
width: 28rpx;
margin-left: 20rpx;
}
input {
font-size: 28rpx;
}
text{
font-size: 28rpx;
}
}
.line {
.inline {
display: flex;
align-items: center;
font-size: 28rpx;
input {
text-align: right;
margin-right: 10rpx;
margin-left: 20rpx;
color: #333;
}
}
.edit {
margin-left: 10rpx;
}
}
.ship-info {
height: 400rpx;
padding: 30rpx;
white-space: pre-wrap;
font-size: 28rpx;
overflow: auto;
.ship-text {
margin-bottom: 20rpx;
}
}
.ship-links {
position: relative;
display: flex;
justify-content: flex-end;
align-items: center;
margin-top: 20rpx;
font-size: 24rpx;
color: #007eff;
.tooltip {
z-index: 1000;
display: none;
position: absolute;
top: 40rpx;
left: 0;
max-width: 90%;
padding: 12px;
color: #fff;
font-size: 12px;
text-align: left;
line-height: 16px;
background-color: #333;
border-radius: 8px;
}
&:hover {
.tooltip {
display: block;
}
}
}
.ship-btns {
display: flex;
justify-content: center;
align-items: center;
button {
padding: 0 16rpx;
margin: 0;
font-size: 28rpx;
&:first-child {
margin-right: 20rpx;
}
}
}
</style>

@ -5,8 +5,14 @@
<uni-icons class="icon" custom-prefix="iconfont" type="icon-filter" size="22" color="#007eff" @click="popup = true"></uni-icons>
</view>
<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 v-if="list.length" class="list">
@ -37,6 +43,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 {
@ -84,24 +91,7 @@
],
filterForm: {},
curTab: '',
tabs: [
{
name: '全部',
id: ''
},
{
name: '实训课程',
id: 1
},
{
name: '理论课程',
id: 0
},
{
name: '数据产品',
id: 3
}
],
tabs: [],
searchTimer: null,
orderStatus: '',
productStatus: '',
@ -130,6 +120,7 @@
onShow() {
const pages = getCurrentPages()
this.customerId = pages[pages.length - 1].options.customerId
this.getTypes()
this.getList()
},
methods: {
@ -201,6 +192,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
@ -215,8 +216,8 @@
this.list = list.filter(e => (orderStatus === '' || ((orderStatus === 2 && e.status === '已过期') || (orderStatus === 1 && e.status === '生效中'))) && (productStatus === '' || ((productStatus === 2 && e.isEnable === '禁用') || (productStatus === 1 && e.isEnable === '启用'))) && e.productName.includes(keyword) && (curTab === '' || (curTab === e.productType)))
},
// tab
tabChange(tab) {
this.curTab = tab.id
tabChange(id) {
this.curTab = id
this.filter()
},
//
@ -231,6 +232,16 @@
.filter {
margin-bottom: 10px;
}
.tab-wrap {
display: flex;
.tab-scroll {
width: calc(100% - 100rpx);
white-space: nowrap;
li {
display: inline-block;
}
}
}
.list {
li {
padding: 0 24rpx;

@ -13,6 +13,7 @@
v-for="item in list"
:threshold="0"
:right-options="ops"
:disabled="!auth('订单管理:删除')"
@click="e => handle(item)"
>
<view class="item" @click="toDetail(item)">
@ -51,7 +52,7 @@
</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 v-if="auth('订单管理:新建订单')" class="plus" type="plus-filled" size="60" color="#007eff" @click="toAdd"></uni-icons>
<filter-popup :data="filterData" :form.sync="filterForm" showArea v-model="popup" title="全部筛选" height="1104rpx" @finsh="subFinsh"></filter-popup>
</view>
</template>
@ -144,9 +145,10 @@
}
},
onShow() {
//
//
try {
uni.removeStorageSync('courses')
uni.removeStorageSync('orderEdited')
} catch (e) {}
this.initList()
},
@ -205,8 +207,15 @@
this.sort = this.sort ? 0 : 1
this.initList()
},
toAdd() {
this.$util.to('../orderDetail/orderDetail')
// uni.redirectTo({
// url: '../orderDetail/orderDetail'
// })
},
//
toDetail(item) {
// if(!this.auth(':')) return
this.$util.to(`../orderDetail/orderDetail?orderId=${item.orderId}&show=1`)
},
//

@ -5,39 +5,41 @@
<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 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 in list">
<view class="pro-name">
<image class="icon" :src="$util.getIcon(item)" mode="widthFix"></image>
<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.toggle}">{{ item.briefIntroduction }}</view>
<view class="toggle" @click="toggle(item)">{{ item.toggle ? '收起' : '展开' }}</view>
<view :class="{ell: !item.toggle}">{{ item.productIntroduction }}</view>
<view v-if="item.productIntroduction.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>
<text class="val">{{ item.typeName }}</text>
</view>
<view class="line">
<text class="name">市场单价</text>
<text class="val">{{ item.marketPrice }}/</text>
<text class="name">适用专业</text>
<text class="val">{{ item.professionalName }}</text>
</view>
<view class="line">
<text class="name">结算方式</text>
<text class="val">{{ item.settlementMethod ? '比例分成' : '结算单价' }}</text>
</view>
<view class="line">
<text class="name">供应厂商</text>
<text class="val">{{ item.supplierName }}</text>
<text class="name">市场建议单价</text>
<text class="val">{{ item.marketUnitPrice }}/</text>
</view>
</view>
</li>
@ -47,29 +49,12 @@
</template>
<script>
import { AppletsDataProductList } from '@/apis/modules/product.js'
import { productCategoryList, listOfGoods } from '@/apis/modules/product.js'
export default {
data() {
return {
curTab: '',
tabs: [
{
name: '全部',
id: ''
},
{
name: '实训课程',
id: 1
},
{
name: '理论课程',
id: 0
},
{
name: '数据产品',
id: 2
}
],
tabs: [],
reachBottom: 0, // 0->,1->,-1->
status: 'more', // more|loading|noMore
searchTimer: null,
@ -104,25 +89,31 @@
}
},
onShow() {
this.getFilter()
this.initList()
},
methods: {
getList() {
AppletsDataProductList({
sort: this.sort,
keywords: this.keyword,
productType: this.curTab,
listOfGoods({
pageNum: this.page,
pageSize: this.pageSize
}).then(({ data }) => {
pageSize: this.pageSize,
sort: this.sort == 'desc' ? 2 : 5,
isShelves: 0,
productClassification: this.curTab,
hotTag: 1,
productName: this.keyword,
}).then(({ page }) => {
// list
const list = data.records
const list = page.records
list.map(e => {
e.toggle = e.briefIntroduction.length < 14 // 14
if (e.productIntroduction) {
e.productIntroduction = this.$util.removeTag(e.productIntroduction)
e.toggle = e.productIntroduction.length < 14 // 14
}
})
this.list = this.reachBottom > 0 ? [...this.list, ...list] : list
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
}).catch(e => {})
@ -132,6 +123,19 @@
this.reachBottom = 0
this.getList()
},
//
getFilter() {
console.log(11)
//
productCategoryList().then(res => {
const list = res.classificationList
list.forEach(e => {
e.id = e.classificationId
e.name = e.classificationName
})
this.tabs = list
}).catch(e => {})
},
//
toggle(item) {
item.toggle = !item.toggle
@ -142,8 +146,8 @@
this.initList()
},
// tab
tabChange(tab) {
this.curTab = tab.id
tabChange(id) {
this.curTab = id
this.initList()
}
}
@ -162,6 +166,16 @@
margin-left: 10%;
}
}
.tab-wrap {
display: flex;
.tab-scroll {
width: calc(100% - 100rpx);
white-space: nowrap;
li {
display: inline-block;
}
}
}
.list {
li {
padding: 0 24rpx;
@ -174,11 +188,13 @@
align-items: center;
padding: 18rpx 0;
font-size: 30rpx;
font-weight: 600;
color: #333;
border-bottom: 1px solid #E6E8ED;
.icon {
width: 52rpx;
height: 52rpx;
width: 58rpx;
min-width: 58rpx;
height: 58rpx;
margin-right: 20rpx;
}
}

@ -17,31 +17,36 @@
}
},
{
"path" : "pages/qrcode/qrcode",
"path" : "pages/person/person",
"style" :
{
"navigationBarTitleText": "邀请加入",
"navigationBarTitleText": "我的",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/clients/clients",
"path" : "pages/teams/teams",
"style" :
{
"navigationBarTitleText": "客户列表",
"navigationBarTitleText": "合伙人",
"enablePullDownRefresh": true
}
},
}
],
"subPackages": [
{
"path" : "pages/products/products",
"root": "order",
"pages": [
{
"path" : "clients/clients",
"style" :
{
"navigationBarTitleText": "产品",
"navigationBarTitleText": "客户列表",
"enablePullDownRefresh": true
}
},
{
"path" : "pages/clientDetail/clientDetail",
"path" : "clientDetail/clientDetail",
"style" :
{
"navigationBarTitleText": "客户详情",
@ -49,63 +54,69 @@
}
},
{
"path" : "pages/addStaff/addStaff",
"path" : "products/products",
"style" :
{
"navigationBarTitleText": "邀请成员",
"enablePullDownRefresh": false
"navigationBarTitleText": "产品",
"enablePullDownRefresh": true
}
},
{
"path" : "pages/plans/plans",
"path": "orders/orders",
"style" :
{
"navigationBarTitleText": "产品方案",
"enablePullDownRefresh": false
"navigationBarTitleText": "订单列表",
"enablePullDownRefresh": true
}
},
{
"path" : "pages/person/person",
"path" : "addCourse/addCourse",
"style" :
{
"navigationBarTitleText": "我的",
"enablePullDownRefresh": false
"navigationBarTitleText": "选择产品",
"enablePullDownRefresh": true
}
},
{
"path" : "pages/send/send",
"path" : "orderDetail/orderDetail",
"style" :
{
"navigationBarTitleText": "下载发送",
"navigationBarTitleText": "订单详情",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/password/password",
"path" : "ordered/ordered",
"style" :
{
"navigationBarTitleText": "修改密码",
"navigationBarTitleText": "已订阅产品",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/setting/setting",
"path" : "editCourse/editCourse",
"style" :
{
"navigationBarTitleText": "设置",
"navigationBarTitleText": "编辑产品",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/teams/teams",
"path" : "curClient/curClient",
"style" :
{
"navigationBarTitleText": "合伙人",
"enablePullDownRefresh": true
"navigationBarTitleText": "订单记录",
"enablePullDownRefresh": false
}
}
]
},
{
"path" : "pages/account/account",
"root": "team",
"pages": [
{
"path" : "account/account",
"style" :
{
"navigationBarTitleText": "修改账号",
@ -113,7 +124,7 @@
}
}
,{
"path" : "pages/phone/phone",
"path" : "phone/phone",
"style" :
{
"navigationBarTitleText": "修改手机号",
@ -121,7 +132,7 @@
}
}
,{
"path" : "pages/email/email",
"path" : "email/email",
"style" :
{
"navigationBarTitleText": "修改邮箱",
@ -129,7 +140,7 @@
}
}
,{
"path" : "pages/teamDetail/teamDetail",
"path" : "teamDetail/teamDetail",
"style" :
{
"navigationBarTitleText": "团队成员",
@ -137,68 +148,72 @@
}
}
,{
"path" : "pages/editTeam/editTeam",
"path" : "editTeam/editTeam",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},
{
"path" : "send/send",
"style" :
{
"navigationBarTitleText": "下载发送",
"enablePullDownRefresh": false
}
],
"subPackages": [{
"root": "order",
"pages": [
},
{
"path": "orders/orders",
"path" : "password/password",
"style" :
{
"navigationBarTitleText": "订单列表",
"enablePullDownRefresh": true
"navigationBarTitleText": "修改密码",
"enablePullDownRefresh": false
}
},
{
"path" : "addCourse/addCourse",
"path" : "setting/setting",
"style" :
{
"navigationBarTitleText": "选择产品",
"enablePullDownRefresh": true
"navigationBarTitleText": "设置",
"enablePullDownRefresh": false
}
},
{
"path" : "orderDetail/orderDetail",
"path" : "qrcode/qrcode",
"style" :
{
"navigationBarTitleText": "订单详情",
"navigationBarTitleText": "邀请加入",
"enablePullDownRefresh": false
}
},
{
"path" : "ordered/ordered",
"path" : "addStaff/addStaff",
"style" :
{
"navigationBarTitleText": "已订阅产品",
"navigationBarTitleText": "邀请成员",
"enablePullDownRefresh": false
}
},
{
"path" : "editCourse/editCourse",
"path" : "plans/plans",
"style" :
{
"navigationBarTitleText": "编辑产品",
"navigationBarTitleText": "产品方案",
"enablePullDownRefresh": false
}
},
{
"path" : "curClient/curClient",
"path" : "scheme/scheme",
"style" :
{
"navigationBarTitleText": "订单记录",
"navigationBarTitleText": "方案详情",
"enablePullDownRefresh": false
}
}
]
}],
}
],
"preloadRule": {
"pages/index/index": {
"network": "all",

@ -11,19 +11,19 @@
</view>
<ul class="entry">
<li v-if="auth('客户管理')" @click="$util.to('../clients/clients')">
<li v-if="auth('客户管理')" @click="$util.to('/order/clients/clients')">
<image class="icon" src="@/static/image/index/index3.png" mode="widthFix"></image>
<view class="text">客户</view>
</li>
<li @click="$util.to('../plans/plans')">
<li @click="$util.to('/team/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')">
<li @click="$util.to('/order/orders/orders')">
<image class="icon" src="@/static/image/index/index5.png" mode="widthFix"></image>
<view class="text">订单</view>
</li>
<li @click="$util.to('../products/products')">
<li @click="$util.to('/order/products/products')">
<image class="icon" src="@/static/image/index/index6.png" mode="widthFix"></image>
<view class="text">产品</view>
</li>

@ -9,8 +9,8 @@
</button>
<template v-else>
<view class="btn wechat" @click="login">
<image src="@/static/image/wechat.png" mode="widthFix"></image>
微信授权登录
<!-- <image src="@/static/image/wechat.png" mode="widthFix"></image> -->
快捷登录
</view>
</template>
@ -75,7 +75,7 @@
this.submiting = true
login({
code,
avatarUrl: userInfo.avatarUrl
// avatarUrl: userInfo.avatarUrl
}).then(({ data }) => {
const e = data.sessionKey
this.sessionKey = e.session_key

@ -10,7 +10,7 @@
</view>
</view>
<view class="list">
<view class="item" @click="$util.to('../setting/setting')">
<view class="item" @click="$util.to('/team/setting/setting')">
<view class="left">
<image class="icon" src="@/static/image/person3.png" mode=""></image>
<text class="name">设置</text>

@ -1,199 +0,0 @@
<template>
<view>
<view class="filter">
<uni-search-bar class="search" radius="30" placeholder="请输入方案名称" clearButton="auto" cancelButton="none" @confirm="search" />
</view>
<ul class="tab">
<li v-for="(tab, i) in tabs" :class="{active: curTab === tab.id}" @click="tabChange(tab)">{{ tab.name }}</li>
</ul>
<view v-if="list.length" class="list">
<view v-for="(item, i) in list" class="item" @click="toDetail(i + 2)">
<view class="c-name">{{ item.name }}</view>
<view class="content">
<view class="info">
<view class="line">
<view class="name">产品</view>
<view class="val ell-wrap">
<view :class="{ell: !item.toggle}" v-html="item.product"></view>
<view v-if="item.product.length > 14" class="toggle" @click.stop="toggle(item)">{{ item.toggle ? '收起' : '展开' }}</view>
</view>
</view>
<view class="line">
<view class="name">更新日期</view>
<view class="val">{{ item.date }}</view>
</view>
<view class="line">
<view class="name">适用专业</view>
<view class="val">{{ item.major }}</view>
</view>
</view>
<view class="detail" @click.stop="toEmail(i)">下载</view>
</view>
</view>
</view>
<empty v-else></empty>
</view>
</template>
<script>
export default {
data() {
return {
curTab: '',
tabs: [
{
name: '不限',
id: ''
},
{
name: '标准方案',
id: 1
},
{
name: '智信云方案',
id: 2
}
],
list: [],
all: [
{
type: 1,
toggle: false,
name: '人工智能实验室建设方案-2020.1',
product: `python程序设计实验教学系统<br>
Docker技术实验教学系统<br>
JAVA语言程序设计实验教学系统<br>
大数据开发实验教学系统<br>
Openstack云计算实验教学系统`,
date: '2022-06-02',
major: '人工智能方向'
},
{
type: 1,
toggle: false,
name: '大数据管理与应用专业建设方案',
product: `python程序设计实验教学系统<br>
量化投资实验教学系统<br>
区块链数字货币交易实验系统<br>
大数分析实验教学系统<br>
数据可视化实验教学系统<br>
大数据实证科研平台<br>
全球宏观经济<br>
数据库全球金融交易数据库 `,
date: '2022-06-02',
major: '大数据方向'
},
{
type: 1,
toggle: false,
name: '金融科技实验室建设方案V2.0',
product: `python程序设计实验教学系统<br>
量化投资实验教学系统<br>
区块链数字货币交易实验教学系统<br>
大数据采集实验教学系统<br>
大数据分析实验教学系统<br>
金融建模实验教学系统<br>
互联网小贷实验教学系统<br>
互联网支付实验教学系统<br>
R语言实验教学系统<br>
供应链金融实验教学系统<br>
Python数据清洗实验教学系统<br>
数据可视化实验教学系统<br>
金融随机过程实验教学系统<br>
银行综合系统<br>
大数据实证科研平台<br>
财经数据库`,
date: '2022-06-02',
major: '金融科技,大数据方向'
}
]
}
},
onShow() {
this.list = JSON.parse(JSON.stringify(this.all))
},
methods: {
search(res) {
uni.showToast({
title: '搜索:' + res.value,
icon: 'none'
})
},
// tab
tabChange(tab) {
const { id } = tab
const { all } = this
this.curTab = id
this.list = id ? all.filter(e => e.type === id) : all
},
//
toDetail(id) {
this.$util.openFile(id)
},
//
toEmail(id) {
this.$util.to(`../send/send?id=${id}`)
},
//
toggle(item) {
item.toggle = !item.toggle
}
}
}
</script>
<style scoped lang="scss">
.list {
background-color: #fff;
.item {
padding: 20rpx 40rpx;
border-bottom: 1px solid #f1f1f1;
}
.c-name {
font-size: 30rpx;
color: #333;
}
.line {
display: flex;
padding: 10rpx 0;
}
.content {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20rpx;
}
.name {
width: 140rpx;
margin-right: 10rpx;
white-space: nowrap;
font-size: 28rpx;
color: #999;
}
.val {
max-width: 88%;
font-size: 28rpx;
color: #333;
}
.ell {
height: 38rpx;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.toggle {
margin-top: 10rpx;
white-space: nowrap;
font-size: 24rpx;
color: #0e92ef;
}
.detail {
margin-left: 20rpx;
font-size: 26rpx;
color: #1f83ff;
white-space: nowrap;
}
}
</style>

@ -43,14 +43,14 @@
<text class="val">{{ item.invitationAccount }}</text>
</view>
</view>
<view class="iconfont icon-edit" @click.stop="toEdit(item)"></view>
<view v-if="auth('合伙管理:账号管理:编辑分类')" class="iconfont icon-edit" @click.stop="toEdit(item)"></view>
</li>
</ul>
<uni-load-more :status="status" />
</template>
<empty v-else></empty>
<uni-icons class="plus" type="plus-filled" size="60" color="#007eff" @click="$util.to('../addStaff/addStaff')"></uni-icons>
<uni-icons v-if="auth('合伙管理:账号管理:添加城市合伙人')" class="plus" type="plus-filled" size="60" color="#007eff" @click="$util.to('/team/addStaff/addStaff')"></uni-icons>
</view>
</template>
@ -148,11 +148,11 @@
},
//
toTeam(e) {
this.$util.to(`../teamDetail/teamDetail?id=${e.teamId}`)
this.$util.to(`/team/teamDetail/teamDetail?id=${e.teamId}`)
},
//
toEdit(e) {
this.$util.to(`../editTeam/editTeam?id=${e.teamId}&areaId=${e.partnerClassificationId}`)
this.$util.to(`/team/editTeam/editTeam?id=${e.teamId}&areaId=${e.partnerClassificationId}`)
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 843 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 B

@ -17,6 +17,11 @@ ul {
border-radius: 16rpx;
background-color: #fff;
}
.ell {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.l-title {
display: flex;
align-items: center;
@ -232,6 +237,9 @@ ul {
border-top: 1px solid #f3f3f3;
box-shadow: 0 -2px 2px #f5f5f5;
box-sizing: border-box;
&:empty {
padding: 0 !important;
}
.item {
text-align: center;
}

@ -0,0 +1,272 @@
<template>
<view>
<view class="filter">
<uni-search-bar class="search" radius="30" placeholder="请输入方案名称" clearButton="auto" cancelButton="none" v-model="keyword" />
</view>
<ul class="tab">
<li v-for="(tab, i) in classifications.slice(0, 4)" :class="{active: active === tab.id}" @click="tabChange(tab)">{{ tab.classificationName }}</li>
<image class="unfold" src="@/static/image/unfold.png" mode="widthFix" @click="typeVisible = true"></image>
</ul>
<view v-if="list.length" class="list">
<view v-for="(item, i) in list" class="item" @click="toDetail(item)">
<view class="c-name ell">{{ item.title }}</view>
<view class="content">
<view class="info">
<view class="line">
<view class="name">产品</view>
<view class="val ell-wrap">
<view :class="['product', {ell: !item.toggle}]">{{ item.productNames }}</view>
<view v-if="item.productNames && item.productNames.length > 24" class="toggle" @click.stop="toggle(item)">{{ item.toggle ? '收起' : '展开' }}</view>
</view>
</view>
<view class="line">
<view class="name">更新日期</view>
<view class="val">{{ item.updateTime }}</view>
</view>
<view class="line">
<view class="name">适用专业</view>
<view class="val">{{ item.applicableMajor }}</view>
</view>
</view>
</view>
</view>
</view>
<empty v-else></empty>
<view class="type-popup" v-show="typeVisible">
<uni-icons class="close" type="closeempty" size="20" color="#757575" @click="closeType"></uni-icons>
<view class="title">所属分类</view>
<view class="types">
<view v-for="(item, i) in classifications" :key="i" :class="['item', {active: active == item.id}]" @click="classificationClick(item)">{{ item.classificationName }}</view>
</view>
</view>
</view>
</template>
<script>
import { schemeList, queryClassificationByType } from '@/apis/modules/article.js'
export default {
data() {
return {
active: '',
typeVisible: false,
classifications: [],
reachBottom: 0, // 0->,1->,-1->
status: 'more', // more|loading|noMore
searchTimer: null,
articleNameSort: '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.keyword = ''
this.active = ''
this.initList()
this.getClassification()
},
methods: {
getList() {
uni.showLoading({
title: '加载中'
})
schemeList({
keyWord: this.keyword,
pageNum: this.page,
pageSize: this.pageSize,
querySource: 4,
classificationId: this.active
}).then(({ data }) => {
uni.hideLoading()
// list
const list = data.records
list.forEach(e => {
if (e.productNames) e.toggle = e.productNames.length < 24 // 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 => {
uni.hideLoading()
})
},
initList() {
this.page = 1
this.reachBottom = 0
this.getList()
},
//
getClassification() {
queryClassificationByType(3).then(({ data }) => {
this.classifications = [
{
id: '',
classificationName: '不限'
}
]
this.classifications.push(...data)
}).catch(e => {})
},
//
classificationClick(item, query) {
this.active = item.id
query && this.initList()
},
//
closeType() {
this.typeVisible = false
this.initList()
},
// tab
tabChange(tab) {
this.active = tab.id
this.initList()
},
//
toDetail(item) {
this.$util.to(`/team/scheme/scheme?id=` + item.id)
},
//
toggle(item) {
item.toggle = !item.toggle
}
}
}
</script>
<style scoped lang="scss">
.tab {
position: relative;
justify-content: flex-start;
li {
padding: 0 30rpx;
}
.unfold {
position: absolute;
top: 32rpx;
right: 12rpx;
right: 44rpx;
width: 40rpx;
}
}
.list {
background-color: #fff;
.item {
padding: 20rpx 40rpx;
border-bottom: 1px solid #f1f1f1;
}
.c-name {
font-size: 30rpx;
color: #333;
}
.line {
display: flex;
padding: 10rpx 0;
}
.content {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20rpx;
}
.name {
width: 140rpx;
margin-right: 10rpx;
white-space: nowrap;
font-size: 28rpx;
color: #999;
}
.val {
font-size: 28rpx;
color: #333;
}
.product {
max-width: 67vw;
white-space: pre-wrap;
&.ell {
white-space: nowrap;
}
}
.toggle {
margin-top: 10rpx;
white-space: nowrap;
font-size: 24rpx;
color: #0e92ef;
}
.detail {
margin-left: 20rpx;
font-size: 26rpx;
color: #1f83ff;
white-space: nowrap;
}
}
.type-popup {
z-index: 10;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
padding: 10rpx;
background-color: #fff;
.close {
position: absolute;
top: 50rpx;
right: 50rpx;
}
.title {
margin: 150rpx 20rpx 30rpx;
font-size: 30rpx;
color: #333;
}
.types {
display: flex;
flex-wrap: wrap;
}
.item {
width: calc((100% - 80rpx) / 3);
margin: 10rpx;
font-size: 28rpx;
line-height: 3;
text-align: center;
color: #1f1f1f;
background-color: #dbebff;
border-radius: 2px;
&.active {
color: #fff;
background-color: #007EFF;
}
}
}
</style>

@ -0,0 +1,83 @@
<template>
<view class="wrap">
<view class="title">{{ form.title }}</view>
<view class="text">{{ form.applicableMajor }}</view>
<view class="text">{{ form.schemeIntroduction }}</view>
<view class="text">{{ form.product }}</view>
<template v-if="form.fileName">
<view class="file">{{ form.fileName }}</view>
<view class="detail" @click.stop="download">下载</view>
</template>
</view>
</template>
<script>
import { schemeFindById } from '@/apis/modules/article.js'
export default {
data() {
return {
id: '',
form: {
totalBrowsing: ''
}
}
},
onShow() {
const pages = getCurrentPages()
const { options } = pages[pages.length - 1]
this.id = options.id
this.getInfo()
},
methods: {
//
getInfo() {
uni.showLoading({
title: '加载中'
})
schemeFindById(this.id).then(({ data }) => {
if (data.productList) data.product = data.productList.map(e => e.productName).join('、')
this.form = data
uni.hideLoading()
}).catch(e => {
uni.hideLoading()
})
},
//
download() {
uni.setStorageSync('files', {
copyWriting: this.form.title,
fileName: [this.form.fileName],
urls: [this.form.schemeFile]
})
this.$util.to(`/team/send/send`)
}
}
}
</script>
<style scoped lang="scss">
.wrap {
padding: 30rpx;
background-color: #fff;
}
.title {
font-size: 34rpx;
font-weight: 600;
color: #333;
}
.text {
margin: 20rpx 0;
font-size: 28rpx;
line-height: 1.6;
}
.file {
margin: 20rpx 0;
font-size: 26rpx;
word-break: break-all;
}
.detail {
font-size: 30rpx;
color: #1f83ff;
}
</style>

@ -25,7 +25,6 @@
export default {
data() {
return {
id: '',
email: '',
otherEmail: '',
myVal: 1,
@ -34,27 +33,15 @@
text: '',
value: 1
}],
files: [
'人工智能实验室建设方案-2020.1.docx',
'大数据管理与应用专业建设方案.docx',
'金融科技实验室建设方案V2.0.docx'
]
}
},
onShow() {
const pages = getCurrentPages()
const { options } = pages[pages.length - 1]
this.id = options.id
this.getInfo()
},
methods: {
//
getInfo() {
const team = uni.getStorageSync('team')
my({
partnerId: team.partnerId,
teamId: team.teamId
}).then(({ my }) => {
my().then(({ my }) => {
this.email = my.info.email
}).catch(e => {})
},
@ -69,10 +56,9 @@
const { otherEmail } = this
if (this.myVal && !this.email) return this.$util.errMsg('请选择其他邮箱!')
if (this.otherVal && !otherEmail) return this.$util.errMsg('请输入邮箱!')
mailFileSend({
copyWriting: this.files[this.id],
mail: this.myVal ? this.email : otherEmail
}).then(res => {
const data = uni.getStorageSync('files')
data.mail = this.myVal ? this.email : otherEmail
mailFileSend(data).then(res => {
this.$util.sucMsg('发送成功!')
setTimeout(() => {
uni.navigateBack()

@ -65,7 +65,7 @@
success(res) {
if (res.confirm) {
uni.clearStorageSync()
that.$util.to('../login/login')
that.$util.to('/pages/login/login')
}
}
})

@ -24,7 +24,7 @@
</template>
<empty v-else></empty>
<uni-icons class="plus" type="plus-filled" size="60" color="#007eff" @click="$util.to('../addStaff/addStaff')"></uni-icons>
<uni-icons v-if="auth('合伙管理:账号管理:添加城市合伙人')" class="plus" type="plus-filled" size="60" color="#007eff" @click="$util.to('../addStaff/addStaff')"></uni-icons>
</view>
</template>

@ -0,0 +1,10 @@
## 0.2.1(2022-05-09)
- 修复 content 为空时仍然弹出的bug
## 0.2.0(2022-05-07)
**注意:破坏性更新**
- 更新 text 属性变更为 content
- 更新 移除 width 属性
## 0.1.1(2022-04-27)
- 修复 组件根 text 嵌套组件 warning
## 0.1.0(2022-04-21)
- 初始化

@ -0,0 +1,70 @@
<template>
<view class="uni-tooltip">
<slot></slot>
<view v-if="content || $slots.content" class="uni-tooltip-popup">
<slot name="content">
{{content}}
</slot>
</view>
</view>
</template>
<script>
/**
* Tooltip 提示文字
* @description 常用于展示鼠标 hover 时的提示信息
* @tutorial https://uniapp.dcloud.io/component/uniui/uni-tooltip
* @property {String} content 弹出层显示的内容
* @property {String} placement出现位置, 目前只支持 left
*/
export default {
name: "uni-tooltip",
data() {
return {
};
},
props: {
content: {
type: String,
default: ''
},
placement: {
type: String,
default: 'bottom'
},
}
}
</script>
<style>
.uni-tooltip {
position: relative;
cursor: pointer;
}
.uni-tooltip-popup {
z-index: 1000;
display: none;
position: absolute;
top: 40rpx;
left: 0;
max-width: 90%;
background-color: #333;
border-radius: 8px;
color: #fff;
font-size: 12px;
text-align: left;
line-height: 16px;
padding: 12px;
}
.uni-tooltip:hover .uni-tooltip-popup {
display: block;
}
</style>

@ -0,0 +1,83 @@
{
"id": "uni-tooltip",
"displayName": "uni-tooltip",
"version": "0.2.1",
"description": "Tooltip 提示文字",
"keywords": [
"uni-tooltip",
"uni-ui",
"tooltip",
"tip",
"文字提示"
],
"repository": "",
"engines": {
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无 ",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"App": {
"app-vue": "y",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

@ -0,0 +1,8 @@
## Badge 数字角标
> **组件名:uni-tooltip**
> 代码块: `uTooltip`
数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景,
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-tooltip)
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
Loading…
Cancel
Save