Compare commits

...

27 Commits

  1. 4
      .hbuilderx/launch.json
  2. 2
      README.md
  3. 21
      apis/modules/user.js
  4. 33
      apis/request.js
  5. 26
      components/notAuth/notAuth.vue
  6. 4
      config/request.js
  7. 16
      directives/auth.js
  8. 12
      directives/index.js
  9. 135
      libs/Oss/base64.js
  10. 117
      libs/Oss/crypto.js
  11. 37
      libs/Oss/hmac.js
  12. 82
      libs/Oss/sha1.js
  13. 71
      libs/Oss/upload.js
  14. 39
      libs/mtj-wx-sdk.config.js
  15. 1
      libs/mtj-wx-sdk.js
  16. 36
      libs/share.js
  17. 18
      libs/uma.js
  18. 17
      libs/util.js
  19. 10
      main.js
  20. 12
      manifest.json
  21. 27
      order/addCourse/addCourse.vue
  22. 19
      order/clientDetail/clientDetail.vue
  23. 38
      order/clients/clients.vue
  24. 7
      order/curClient/curClient.vue
  25. 182
      order/editCourse/editCourse.vue
  26. 619
      order/orderDetail/orderDetail.vue
  27. 107
      order/privacyAgreement/privacyAgreement.vue
  28. 95
      order/productDetail/productDetail.vue
  29. 65
      order/products/products.vue
  30. 88
      order/serviceAgreement/serviceAgreement.vue
  31. 119
      order/shopCart/shopCart.vue
  32. 5
      package-lock.json
  33. 3
      package.json
  34. 71
      pages.json
  35. 217
      pages/index/index.vue
  36. 133
      pages/login/login.vue
  37. 57
      pages/orders/orders.vue
  38. 137
      pages/person/person.vue
  39. 219
      pages/products/products.vue
  40. 49
      pages/reg/reg.vue
  41. 67
      pages/workbench/workbench.vue
  42. BIN
      static/image/index/banner.png
  43. BIN
      static/image/index/banner1.png
  44. BIN
      static/image/logo.png
  45. BIN
      static/image/logo1.png
  46. BIN
      static/image/product/shop-blue.png
  47. BIN
      static/image/product/shop.png
  48. BIN
      static/image/tab1-1.png
  49. BIN
      static/image/tab1.png
  50. BIN
      static/image/tab2-1.png
  51. BIN
      static/image/tab2.png
  52. BIN
      static/image/tab3-1.png
  53. BIN
      static/image/tab3.png
  54. BIN
      static/image/tab4-1.png
  55. BIN
      static/image/tab4.png
  56. 41
      styles/common.scss
  57. 3
      team/article/article.vue
  58. 8
      team/info/info.vue
  59. 59
      team/plans/plans.vue
  60. 8
      team/qrcode/qrcode.vue
  61. 4
      team/scheme/scheme.vue
  62. 4
      team/setting/setting.vue
  63. 6
      team/study/study.vue

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

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

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

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

@ -5,8 +5,8 @@
*/
export default {
baseURL: 'https://huorantech.cn/',
// baseURL: 'http://192.168.31.152: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,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 {
@ -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()
@ -121,4 +122,8 @@ export default {
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

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

@ -18,7 +18,7 @@
<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>
@ -67,7 +67,8 @@
value: 1
}],
checked: uni.getStorageSync('courses') || [], //
courses: uni.getStorageSync('courses') || []
courses: uni.getStorageSync('courses') || [],
submiting: false,
}
},
watch: {
@ -212,7 +213,7 @@
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: '', //
@ -226,11 +227,15 @@
isEnable: 0, // 10
ship: 0, // 01
authority, // 01
options: 2,
options: trial ? 1 : 2,
miniProgramPictureAddress: e.appletIcon || '', //
settlementPrice: trial ? 0 : '', //
settlementPriceUnit: e.settlementPrice || 0, //
serviceFee: 0 //
serviceFee: 0, //
mallNonAssociatedLinks: e.mallNonAssociatedLinks, //
typeId: e.typeId,
typeName: e.typeName,
classificationId: e.classificationId,
}
},
//
@ -257,8 +262,13 @@
submit() {
const list = this.checked //
if (list.length) {
if (this.submiting) return false
this.submiting = true
uni.showLoading({
title: '加载中'
})
const result = this.courses
console.log(123, result)
const list1 = [] //
const list0 = [] //
const list2 = [] //
@ -276,7 +286,6 @@
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
@ -317,6 +326,7 @@
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}`
@ -358,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: {
@ -131,12 +137,42 @@
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>
@ -64,6 +72,7 @@
</view>
</view>
</view>
</template>
</view>
</view>
</template>
@ -74,15 +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 { productCategoryList } from '@/apis/modules/product.js'
import { productTypeList } from '@/apis/modules/product.js'
export default {
data() {
return {
orderType: 1,
customerId: '',
action: '',
provinceId: '',
cityId: '',
timer: null,
units: [{
text: '日',
@ -95,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() {
@ -122,41 +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')
let courses = {}
//
productCategoryList().then(res => {
res.classificationList.forEach(e => {
courses['list' + this.$util.getOrderType(e.classificationId)] = {
productTypeList().then(res => {
res.typeList.forEach(e => {
courses['list' + e.typeId] = {
shrink: false,
name: e.classificationName,
name: e.typeName,
deadline: '',
unit: '',
list: []
}
})
list.map(e => {
courses['list' + e.authority].list.push(e)
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 => {})
try {
uni.removeStorageSync('courses')
} catch (e) {}
},
//
batchDeadlineChange (c) {
c.list.map(e => {
e.periodOfUse = c.deadline
this.calcDate(e, !e.authority)
})
},
//
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)
})
}
}
})
},
//
selectUnit(item) {
const that = this
uni.showActionSheet({
title: '标题',
itemList: that.unitText,
success: ({ tapIndex }) => {
if (tapIndex !== '') {
item.options = tapIndex
that.calcDate(item)
}
}
})
},
showUnit(i) {
@ -176,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) {
@ -195,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
@ -218,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))
@ -236,13 +290,11 @@
}
//
this.calcDiscount(row)
}, 500)
},
//
dealSettlePrice(row) {
// 0
console.log('dealSettlePrice=>', row, this.orderType)
if (this.orderType == 2) {
// 0
if (this.orderType != 1) {
row.settlementPrice = 0
row.serviceFee = 0
} else {
@ -258,7 +310,6 @@
priceUnit * useUnit) * (row.authority ?
1 :
row.accountNum)).toFixed((2))
console.log('dealSettlePrice2=>', row, this.orderType, this.$util.handleNaN(sPrice))
row.settlementPrice = this.$util.handleNaN(sPrice)
//
if (row.settlementPrice) {
@ -271,7 +322,6 @@
getPartnerTeamRates({
teamId: uni.getStorageSync('team').teamId
}).then(({ teamRates }) => {
console.log('teamRates=>',teamRates)
this.rate = teamRates.annualMarketingFee || 0
}).catch(res => {})
},
@ -325,6 +375,7 @@
},
//
submit() {
if (this.submiting) return false
const { courses } = this
const list = []
let msg = ''
@ -332,7 +383,6 @@
for (const i in courses) {
list.push(...courses[i].list)
}
console.log(11, list)
//
for (const i in list) {
const e = list[i]
@ -342,6 +392,11 @@
msg = '请输入使用期限!'
break
}
if (e.options === '') {
this.err = 'accountNum' + suf
msg = '请选择期限!'
break
}
if (!e.startTime) {
this.err = 'startTime' + suf
msg = '请选择起止日期!'
@ -358,12 +413,18 @@
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.redirectTo({
url: `../orderDetail/orderDetail`
url: `../orderDetail/orderDetail?edited=1`
})
},
}
@ -381,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;

@ -12,7 +12,7 @@
<view v-if="isDetail" class="val">{{ form.customerName }}</view>
<view v-else class="customer-wrap">
<view :class="['ph', {val: form.customerName}]" @click="customerVisible = true">{{ form.customerName || '请选择客户' }}</view>
<view class="create" @click="toClient">找不到客户马上创建</view>
<!-- <view class="create" @click="toClient">找不到客户马上创建</view> -->
</view>
</view>
<view class="line" v-if="form.customerName">
@ -40,11 +40,12 @@
<view v-if="isDetail" class="val">{{ orderTypes.find(e => e.value === form.orderType).text }}</view>
<uni-data-picker v-else class="picker-input" placeholder="请选择订单类型" popup-title="请选择订单类型" preload :clear-icon="false" :localdata="orderTypes" v-model="form.orderType" @change="calcTotal(1)"></uni-data-picker>
</view>
<view class="line">
<template v-if="edited">
<view v-if="form.orderNumber" class="line">
<view class="name">订单编号</view>
<view class="val">{{ form.orderNumber }}</view>
</view>
<view class="line">
<view v-if="form.createTime" class="line">
<view class="name">订单时间</view>
<view class="val">{{ form.createTime }}</view>
</view>
@ -52,15 +53,24 @@
<view class="name">订单金额</view>
<view class="val">{{ form.orderAmount }}</view>
</view>
</template>
</view>
</view>
<view id="products">
<template v-for="c in courseList">
<view v-if="c.list.length" class="block pro-wrap" id="products">
<view v-if="c.list.length" class="block pro-wrap">
<view class="type-wrap">
<view class="l-title">{{ c.name }}</view>
<view v-if="!isDetail" 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>
<ul class="pro-list" v-show="!c.shrink">
<li v-for="(item, i) in c.list" @click.stop="editCourse(c, i)">
<li v-for="(item, i) in c.list">
<view class="name">
<view class="left">
<image class="icon" :src="$util.getIcon(item)" mode="widthFix"></image>
@ -68,43 +78,80 @@
</view>
<view class="course-action">
<image v-if="!isDetail" class="del" src="@/static/image/trash.png" mode="widthFix" @click.stop="delCourse(c, i)"></image>
<button v-if="(item.authority == 3 || item.authority == 4) && ((item.mallNonAssociatedLinks && item.mallNonAssociatedLinks.length) || item.shipContent)" class="info-btn" type="primary" @click.stop="showShip(item)">发货信息</button>
</view>
</view>
<view class="info">
<view class="line">
<view class="label">起始日期</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="dateChange(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" 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="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>
</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 && item.marketValue + '元' }}</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 && item.settlementPrice + '元' }}</view>
<view class="ph">{{ item.settlementPrice && item.settlementPrice + '元' }}</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 v-if="(item.authority == 0 || item.authority == 3 || item.authority == 4) && item.shipInfo" class="line">
<view class="label">发货信息</view>
<view class="ph ship-info" v-html="item.shipInfo" @click="copy(item)"></view>
</view>
</view>
</li>
</ul>
</view>
</template>
</view>
<view class="bottom">
<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" class="add-wrap">
<view class="add-btn" @click="toAdd">
<view class="lg-btn" @click="toAdd(1)">
<uni-icons class="icon" type="plus" color="#007FFF"></uni-icons>
添加产品
</view>
@ -127,6 +174,14 @@
</view>
<view v-if="!isDetail" class="btn" @click="submit">提交({{ courses.length }})</view>
</view>
</template>
</view>
<view v-if="isDetail && form.isDel !== 1 && form.orderStatus === 1" class="action">
<view class="item" @click="toAction(`../orderDetail/orderDetail?orderId=${orderId}&action=renew`)">
<uni-icons class="icon" custom-prefix="iconfont" type="icon-product" size="30" color="#959595"></uni-icons>
<view class="text">续费</view>
</view>
</view>
<view class="popup-mask" v-show="customerVisible" @click="closeCustomer"></view>
@ -134,26 +189,27 @@
<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" v-html="shipInfo" @click="copy"></view>
</uni-popup>
</view>
</template>
<script>
import { productCategoryList, delCart } from '@/apis/modules/product.js'
import { productTypeList, delCart } from '@/apis/modules/product.js'
import { queryCustomer, queryCustomerDetails } from '@/apis/modules/client.js'
import { add, update, getDetail, queryCitySettlementPrice } from '@/apis/modules/order.js'
import { add, getDetail, renew, queryCitySettlementPrice, getOrderOtherTime } from '@/apis/modules/order.js'
import { getPartnerTeamRates } from '@/apis/modules/parner.js'
export default {
data() {
return {
isDetail: false,
isRenew: 0, //
orderId: '',
edited: false,
shopCart: false,
orderTypes: [{
text: '正式',
value: 1
@ -198,8 +254,20 @@
customerList: [],
customerListAll: [],
err: '',
promises: [],
rate: '',
shipInfo: ''
orderRepeat:[],
units: [{
text: '日',
id: 0
}, {
text: '月',
id: 1
}, {
text: '年',
id: 2
}],
unitText: ['日', '月', '年'],
}
},
watch: {
@ -215,6 +283,10 @@
const { options } = pages[pages.length - 1]
this.orderId = options.orderId
this.isDetail = !!options.show
const { action } = options
this.isRenew = action === 'renew'
this.edited = options.edited //
this.shopCart = options.shopCart //
const store = uni.getStorageSync('courses')
const form = uni.getStorageSync('orderForm')
if (form) {
@ -224,24 +296,36 @@
this.getRate()
if (this.orderId) {
this.getInfo()
} else if (store) {
} else if (options.edited && store) { //
uni.showLoading({
title: '加载中'
})
//
const list = []
for (const i in store) {
//
store[i].list.map(e => {
let val = []
e.mallNonAssociatedLinks && e.mallNonAssociatedLinks.forEach(e => {
val.push(e.urlName + ':' + e.url)
})
e.shipInfo = e.shipContent || val.join('<br>')
e.copyInfo = e.shipContent || val.join(';')
})
list.push(...store[i].list)
}
this.courseList = store
this.courses = list
this.$nextTick(() => {
uni.pageScrollTo({
selector: '#products',
selector: '#products'
})
})
try {
uni.removeStorageSync('courses')
} catch (e) {}
this.calcTotal()
this.$nextTick(() => {
uni.hideLoading()
})
}
// id
@ -272,14 +356,20 @@
orderId: this.orderId
}).then(({ orderDetails }) => {
const order = orderDetails
this.contract = order.contractInformation
if (!this.isRenew) this.contract = order.contractInformation //
this.form = order.order
order.orderOther.forEach(e => {
e.settlementPriceUnit = e.settlementPrice
})
this.courses = order.orderOther
this.handleProduct(order.orderOther)
if(!this.orderId) {
this.calcTotal()
for (let i = 0; i < 5; i++) {
this.handleRenew(i)
}
Promise.all(this.promises).then(_ => {
this.handleProduct(this.courses)
this.calcTotal()
uni.hideLoading()
})
}).catch(e => {
uni.hideLoading()
})
@ -288,23 +378,88 @@
handleProduct(list) {
let courses = {}
//
productCategoryList().then(res => {
res.classificationList.forEach(e => {
courses['list' + this.$util.getOrderType(e.classificationId)] = {
productTypeList().then(res => {
res.typeList.forEach(e => {
courses['list' + e.typeId] = {
shrink: false,
name: e.classificationName,
name: e.typeName,
deadline: '',
unit: '',
list: []
}
})
const isTrial = this.form.orderType == 2
// 3push(0-> 1- 2 )
list.map(e => {
//
let val = []
e.mallNonAssociatedLinks && e.mallNonAssociatedLinks.forEach(e => {
val.push(e.urlName + ':' + e.url)
})
e.shipInfo = e.shipContent || val.join('<br>')
e.copyInfo = e.shipContent || val.join(';')
e.serviceFee = (e.finalPrice * (this.rate / 100)).toFixed(2) // != 0 &&
courses['list' + e.authority].list.push(e)
// 1
if (isTrial) {
e.periodOfUse = 1
e.options = 1
this.calcDate(e, !e.authority)
}
courses['list' + e.typeId].list.push(e)
})
console.log(123,courses)
this.courseList = courses
}).catch(e => {})
},
// pc
handleRenew(authority) {
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,
}).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) { //
let date = new Date(e.endTime)
if (now < date) { // +1
date = new Date(date.setDate(date.getDate() + 1))
item.startTime = this.$util.formatDate(date, 'yyyy-MM-dd')
} else { //
item.startTime = this.$util.formatDate(now, 'yyyy-MM-dd')
}
item.endTime = ''
item.periodOfUse = ''
item.marketValue = e.marketValue
} else if (!this.isDetail) { //
item.startTime = e.startTime.split(' ')[0]
item.endTime = e.endTime ? e.endTime.split(' ')[0] : ''
}
}
const startTime = new Date(item.startTime)
const endTime = new Date(item.endTime)
// 1: 23
item.status = now < startTime ?
1 :
now > startTime && now < endTime ?
2 :
3
if (item.status === 3) item.isEnable = 0 //
})
resolve()
}).catch(e => {
reject()
})
}))
},
//
getCustomer() {
queryCustomer({
@ -380,26 +535,30 @@
}).catch(res => {})
},
//
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}&provinceId=${this.form.provinceId}&cityId=${this.form.cityId}`) :
this.$util.errMsg('请先选择客户!')
},
//
editCourse(c, i) {
if (this.isDetail) return false
uni.setStorageSync('courses', this.courses)
toAdd(add) {
const { form } = this
if (!form.customerId) {
this.err = 'customerName'
return this.$util.errMsg('请选择客户!')
}
if (!form.orderType) {
this.err = 'orderType'
return this.$util.errMsg('请选择订单类型!')
}
add && uni.setStorageSync('courses', this.courses)
uni.setStorageSync('orderForm', this.form)
const { customerId, orderType } = this.form
this.$util.to(`../editCourse/editCourse?orderType=${orderType}&customerId=${customerId}`)
//
const url = this.shopCart ?
`../editCourse/editCourse` :
`../addCourse/addCourse`
this.$util.to(url + `?orderType=${orderType}&customerId=${customerId}&provinceId=${this.form.provinceId}&cityId=${this.form.cityId}`)
},
//
toClient() {
uni.setStorageSync('courses', this.courseList)
this.$util.to(`/order/clientDetail/clientDetail`)
this.shopCart || uni.setStorageSync('courses', this.courses)
this.$util.to(`/order/clientDetail/clientDetail?order=1${this.shopCart ? '&shopCart=1' : ''}`)
},
//
delCourse(c, i) {
@ -458,35 +617,108 @@
} else {
this.calcDiscount(e)
this.dealSettlePrice(e)
this.calcFinalPrice(e)
// this.calcFinalPrice(e)
const curPurchase = +e.settlementPrice + +e.serviceFee
purchase += curPurchase
profit += +e.finalPrice - curPurchase
}
})
form.purchaseCost = purchase
form.profit = profit
form.purchaseCost = purchase.toFixed(2)
form.profit = profit.toFixed(2)
form.orderAmount = (+form.purchaseCost + +form.profit).toFixed(2)
},
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%'
//
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)
},
// 使
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) {
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({
authority: row.authority,
customerId: this.form.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)
},
//
dealSettlePrice(row) {
console.log('row==>',row)
// 0
if (this.form.orderType == 2) {
// 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
let sPrice = ((!unit ?
sPrice = ((!unit ?
priceUnit / 365 * useUnit :
unit === 1 ?
priceUnit / 12 * useUnit :
@ -495,10 +727,62 @@
row.accountNum)).toFixed((2))
row.settlementPrice = this.$util.handleNaN(sPrice)
//
if (row.settlementPrice) {
row.serviceFee = (row.finalPrice * (this.rate / 100)).toFixed(2)
this.calcAmount()
}
},
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%'
},
//
batchDeadlineChange (c) {
c.list.map(e => {
e.periodOfUse = c.deadline
this.calcDate(e, !e.authority)
})
},
//
batchUnitChange(c) {
const that = this
uni.showActionSheet({
title: '标题',
itemList: that.unitText,
success: ({ tapIndex }) => {
c.unit = tapIndex
c.list.map(e => {
e.options = tapIndex
that.calcDate(e, !e.authority)
})
}
})
},
//
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) {
@ -523,21 +807,11 @@
this.dealSettlePrice(row)
}, 500)
},
//
showShip(row) {
console.log(33)
let val = ''
row.mallNonAssociatedLinks && row.mallNonAssociatedLinks.forEach(e => {
val += e.urlName + ':' + e.url + '\n'
})
this.shipInfo = row.shipContent || val
this.$refs.info.open()
},
//
copy() {
copy(row) {
const that = this
uni.setClipboardData({
data: this.shipInfo,
data: row.copyInfo,
success() {
that.$util.sucMsg('复制成功')
}
@ -547,10 +821,15 @@
handleErr(val) {
if (val === this.err) this.err = ''
},
toAction(url) {
uni.redirectTo({
url
})
},
//
publicNotice() {
uni.requestSubscribeMessage({
tmplIds: ['8pDVfWYqh9c-nn3CeA1NXJtBxdd1FYiCtrl5BeLvbgU'],
tmplIds: ['8pDVfWYqh9c-nn3CeA1NXJtBxdd1FYiCtrl5BeLvbgU', 'mg3RiI8tDNaChVQKjImXzYK63C5Il3BENfBwF0NDzDM'],
success: (res) => {
uni.switchTab({
url: '/pages/orders/orders'
@ -564,7 +843,6 @@
});
}
})
},
//
async delShopCart(courses) {
@ -573,7 +851,8 @@
},
//
submit() {
const { form, courses } = this
const { form } = this
const courses = []
if (!form.customerId) {
this.err = 'customerName'
return this.$util.errMsg('请选择客户!')
@ -582,10 +861,20 @@
this.err = 'orderType'
return this.$util.errMsg('请选择订单类型!')
}
if (!courses.length) return this.$util.errMsg('请选择课程后再确认订单!')
courses.map(e => {
for (const i in this.courseList) {
courses.push(...this.courseList[i].list)
}
if (!courses.length) return this.$util.errMsg('请选择课程权限或数据权限后再确认订单!')
let invalid = 0
courses.forEach(e => {
if (!e.periodOfUse) {
invalid = 1
return this.$util.errMsg('请输入使用期限!')
}
e.startTime = this.$util.formatDate(new Date(e.startTime), 'yyyy-MM-dd')
})
if (invalid) return false
if (this.isRenew || courses.some(e => e.renew)) form.orderNature = 2
uni.showLoading({
title: '提交中'
})
@ -594,36 +883,55 @@
order: form, //
orderOther: courses //
}
if (this.orderId) {
update(data).then(res => {
//
add(data).then(res => {
this.delShopCart(courses)
uni.hideLoading()
this.$util.sucMsg('编辑成功')
this.$util.sucMsg('添加成功')
// #ifdef MP-WEIXIN
this.publicNotice()
// #endif
// #ifdef MP-TOUTIAO
setTimeout(() => {
uni.switchTab({
url: '/pages/orders/orders'
})
}, 1500)
}).catch(res => {
uni.hideLoading()
})
} else {
add(data).then(res => {
this.delShopCart(courses)
uni.hideLoading()
this.$util.sucMsg('添加成功')
this.publicNotice()
// #endif
}).catch(res => {
uni.hideLoading()
})
}
}
}
}
</script>
<style scoped lang="scss">
.page {
padding-bottom: 420rpx;
.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;
}
}
}
.show {
padding-bottom: 280rpx;
@ -632,12 +940,13 @@
.customer-wrap {
text-align: right;
}
}
.create {
margin-top: 10rpx;
padding: 0 20rpx;
font-size: 20rpx;
text-align: right;
color: #f00;
}
}
.pro-wrap {
position: relative;
padding: 0;
@ -645,11 +954,6 @@
margin: 0 24rpx;
}
}
.arrow {
position: absolute;
top: 20rpx;
right: 30rpx;
}
.pro-list {
.name {
display: flex;
@ -660,21 +964,24 @@
color: #333;
background: linear-gradient(90deg, #FFF5E5 0%, #FFFFFF 100%);
}
.left {
display: inline-flex;
align-items: center;
max-width: 480rpx;
margin-right: 10rpx;
}
.course-action {
display: inline-flex;
align-items: center;
}
.info-btn {
.course-btn {
padding: 0 16rpx;
margin-left: 10rpx;
font-size: 28rpx;
}
.left {
display: inline-flex;
align-items: center;
white-space: nowrap;
}
.del {
width: 40rpx;
margin-right: 20rpx;
}
.icon {
width: 60rpx;
@ -688,13 +995,25 @@
.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 {
margin-right: 20rpx;
font-size: 28rpx;
white-space: nowrap;
color: #333;
}
.ph {
font-size: 28rpx;
color: #999;
&.ship-info {
text-align: right;
}
}
.val {
font-size: 28rpx;
@ -711,8 +1030,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);
@ -720,12 +1046,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;
@ -741,6 +1069,11 @@
.uni-icons {
font-size: 38rpx !important;
}
&.next {
color: #fff;
background-color: #007EFF;
}
}
}
.product {
display: flex;
@ -808,11 +1141,61 @@
background-color: #007EFF;
}
}
.ship-info {
height: 400rpx;
padding: 20rpx;
white-space: pre-wrap;
.unit {
display: inline-flex;
align-items: center;
.icon {
width: 28rpx;
margin-left: 20rpx;
}
input {
font-size: 28rpx;
}
text{
font-size: 28rpx;
}
&.placeholder {
color: #797979 !important;
}
}
.line {
.inline {
display: flex;
align-items: center;
font-size: 28rpx;
overflow: auto;
input {
text-align: right;
margin-right: 10rpx;
margin-left: 20rpx;
color: #333;
}
}
.edit {
margin-left: 10rpx;
}
}
.action {
z-index: 2;
position: fixed;
bottom: 24rpx;
display: flex;
justify-content: flex-end;
width: 100%;
padding-right: 50rpx;
padding-bottom: env(safe-area-inset-bottom);
// background-color: #fff;
// border-top: 1px solid #f3f3f3;
// box-shadow: 0 -2px 2px #f5f5f5;
box-sizing: border-box;
&:empty {
padding: 0 !important;
}
.item {
text-align: center;
}
.text {
font-size: 10px;
color: #959595;
}
}
</style>

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

@ -8,18 +8,20 @@
<view class="fields">
<view class="field">
<image class="icon" src="@/static/image/product/1.png"></image>
市场建议价{{ form.mall.marketUnitPrice }}/
市场建议价{{ form.mall.marketUnitPrice || '' }}/
</view>
<view class="field">
<image class="icon" src="@/static/image/product/2.png"></image>
产品类型{{ form.goodsRes.typeName }}
产品类型{{ form.goodsRes.typeName || '' }}
</view>
</view>
</view>
<view class="detail">
<ul class="tabs">
<li v-for="(tab, i) in tabs" :class="{active: curTab === tab.id}" @click="tabChange(tab)">{{ tab.name }}</li>
<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>
@ -48,8 +50,7 @@
</view>
<view class="line">
<text class="name">详情介绍</text>
<!-- <view class="val" v-html="form.mall.detailedIntroduction"></view> -->
<mp-html class="val" :content="form.mall.detailedIntroduction"/>
<mp-html class="des-html" :tag-style="mpStyle" :content="form.mall.detailedIntroduction"/>
</view>
</view>
</view>
@ -74,19 +75,19 @@
<image class="icon" src="@/static/image/product/5.png"></image>
产品参数
</view>
<view class="download" @click="downloadAll">
<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" @click="download(file)">
<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 class="download" @click="download(file)">下载</view>
<view v-if="auth('产品:下载')" class="download" @click="download(file)">下载</view>
</view>
</view>
</view>
@ -108,7 +109,7 @@
</template>
<script>
import { detailsOfGoods, addToShoppingCart, shoppingCartList, productCategoryList } from '@/apis/modules/product.js'
import { detailsOfGoods, addToShoppingCart, shoppingCartList } from '@/apis/modules/product.js'
export default {
data() {
return {
@ -118,6 +119,14 @@
{
name: '详情介绍',
id: 0
},
{
name: '界面图',
id: 1
},
{
name: '参数',
id: 2
}
],
form: {
@ -130,29 +139,30 @@
mallAnnex: []
},
shopCartTotal: 0,
types: [],
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() {
this.tabs = [
{
name: '详情介绍',
id: 0
}
]
const pages = getCurrentPages()
const { options } = pages[pages.length - 1]
this.id = options.id
this.getInfo()
this.getShopCart()
this.getTypes()
//
try {
uni.removeStorageSync('orderForm')
uni.removeStorageSync('courses')
} catch (e) {}
},
methods: {
//
@ -163,19 +173,20 @@
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
})
// 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()
@ -190,14 +201,9 @@
this.shopCartTotal = data.total
}).catch(e => {})
},
//
getTypes() {
productCategoryList().then(res => {
this.types = res.classificationList
}).catch(e => {})
},
// tab
tabChange({ id }) {
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',
@ -247,7 +253,7 @@
},
//
order() {
const { mall } = this.form
const { mall, typeIds } = this.form
const classificationId = this.form.classificationIds[0]
const authority = this.$util.getOrderType(classificationId)
//
@ -273,9 +279,11 @@
miniProgramPictureAddress: mall.appletIcon || '', //
settlementPrice: 0, //
settlementPriceUnit: 0, //
serviceFee: 0 //
serviceFee: 0, //
typeId: typeIds && typeIds.length ? typeIds[0] : '',
classificationId,
}])
this.$util.to(`/order/editCourse/editCourse`)
this.$util.to(`../orderDetail/orderDetail?shopCart=1`)
}
}
}
@ -341,6 +349,9 @@
background-color: #007EFF;
}
}
.disabled {
color: #b3b3b3;
}
}
.detail {
padding: 34rpx 32rpx;
@ -396,6 +407,17 @@
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%;
@ -431,6 +453,7 @@
left: 0;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
padding: 24rpx 32rpx 24rpx 73rpx;
background-color: #fff;

@ -4,12 +4,17 @@
<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">
<li v-for="(tab, i) in tabs" :class="{active: curTab === tab.id}" @click="tabChange(tab)">
{{ tab.name }}
<view v-if="i == 2" :class="['sort', {desc: sort == 2, asc: sort == 5}]"></view>
</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.value}" @click="tabChange(tab.value)">{{ tab.title }}</li>
</scroll-view>
</ul>
<view class="tags">
<view v-if="categoryName" class="tag" @click="delCategory">
{{ categoryName }}
@ -32,7 +37,7 @@
<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)" mode="widthFix"></image>
<image class="icon" :src="$util.getIcon(item)"></image>
{{ item.productName }}
</view>
<view class="info">
@ -119,21 +124,9 @@
tagId: ''
},
tagId: '',
curTab: 0,
tabs: [
{
name: '综合排序',
id: 0
},
{
name: '热销排行',
id: 1
},
{
name: '发布时间',
id: 2
}
],
curTab: '',
tabs: [],
scrollLeft: 0,
reachBottom: 0, // 0->,1->,-1->
status: 'more', // more|loading|noMore
searchTimer: null,
@ -179,7 +172,7 @@
this.form.tagId = +tagId || ''
if (tagId) {
this.filterForm.tagId = [+tagId]
this.tagName = tagsName
// this.tagName = tagsName
}
this.keyword = options.keyword || ''
@ -193,11 +186,12 @@
listOfGoods({
pageNum: this.page,
pageSize: this.pageSize,
sort: this.curTab == 2 ? this.sort : this.curTab,
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
@ -233,6 +227,7 @@
e.value = e.typeId
e.title = e.typeName
})
this.tabs = res.typeList
this.filters[0].data = res.typeList
}).catch(e => {})
@ -295,10 +290,7 @@
this.initList()
},
// tab
tabChange({ id }) {
this.sort = id == 2 ?
this.sort == 2 ? 5 : 2
: ''
tabChange(id) {
this.curTab = id
this.initList()
},
@ -312,10 +304,14 @@
</script>
<style scoped lang="scss">
.tab {
.tab-wrap {
display: flex;
.tab-scroll {
width: calc(100% - 100rpx);
white-space: nowrap;
li {
display: inline-flex;
align-items: center;
display: inline-block;
}
}
}
.tags {
@ -349,12 +345,15 @@
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;
border-radius: 4px;
}
}
.info {
@ -394,7 +393,7 @@
bottom: 140rpx;
right: 60rpx;
.icon {
width: 80rpx;
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>

@ -1,20 +1,36 @@
<template>
<view class="page">
<ul class="list">
<li v-for="(item, i) in 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)" mode="widthFix"></image>
{{ item.productName }}
<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>
@ -40,6 +56,12 @@
value: 1
}],
checked: [], //
delOption: [{
text: '删除',
style: {
backgroundColor: '#F56C6C'
}
}],
}
},
//
@ -62,9 +84,10 @@
//
try {
uni.removeStorageSync('orderForm')
uni.removeStorageSync('courses')
uni.removeStorageSync('orderEdited')
} catch (e) {}
this.page = 1
this.getList()
this.initList()
},
methods: {
//
@ -134,17 +157,18 @@
//
createParam(e, authority, shopCartId) {
const { orderType } = this
const { mall, typeIds } = e
const trial = orderType == 2 //
return {
dataOrCourseId: e.associatedProduct, // id
mallId: e.mallId,
productName: e.productName, //
dataOrCourseId: mall.associatedProduct, // id
mallId: mall.mallId,
productName: mall.productName, //
periodOfUse: '', // 使
startTime: this.$util.formatDate(new Date(), 'yyyy-MM-dd'), //
endTime: '', //
remainingPeriod: '', //
marketValue: '', //
marketPrice: e.marketUnitPrice, //
marketPrice: mall.marketUnitPrice, //
finalPrice: 0, //
finalValue: 0, //
discountRate: '0%', //
@ -154,11 +178,49 @@
ship: 0, // 01
authority, // 01
options: 2,
miniProgramPictureAddress: e.appletIcon || '', //
miniProgramPictureAddress: mall.appletIcon || '', //
settlementPrice: trial ? 0 : '', //
settlementPriceUnit: 0, //
serviceFee: 0, //
shopCartId// id
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('请选择产品!')
}
},
//
@ -175,16 +237,16 @@
//
const res = await detailsOfGoods(e.mallId)
const n = res.orderDetails
courses.push(this.createParam(n.mall, this.$util.getOrderType(n.classificationIds[0]), e.id))
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(`/order/editCourse/editCourse`)
this.$util.to(`../orderDetail/orderDetail?shopCart=1`)
})
} else {
this.$util.errMsg('请选择产品!')
this.$util.errMsg('请先添加产品!')
}
}
}
@ -199,16 +261,28 @@
li {
display: flex;
align-items: center;
width: 100%;
padding: 30rpx 24rpx;
margin: 16rpx 24rpx;
font-size: 30rpx;
color: #333;
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: 80rpx;
width: 100rpx;
min-width: 100rpx;
height: 100rpx;
margin: 0 20rpx;
border-radius: 4px;
}
}
/deep/.check {
@ -228,9 +302,16 @@
.btn-wrap {
position: fixed;
justify-content: space-between;
.btns {
display: inline-flex;
}
.btn {
width: 340rpx;
margin-left: 27rpx;
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,18 +1,18 @@
{
"pages": [
{
"path" : "pages/login/login",
"path" : "pages/index/index",
"style" :
{
"navigationBarTitleText": "登录",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/index/index",
"path" : "pages/login/login",
"style" :
{
"navigationBarTitleText": "",
"navigationBarTitleText": "登录",
"enablePullDownRefresh": false
}
},
@ -21,6 +21,7 @@
"style" :
{
"navigationBarTitleText": "工作台",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
@ -32,38 +33,22 @@
"enablePullDownRefresh": true
}
},
{
"path" : "pages/products/products",
"style" :
{
"navigationBarTitleText": "产品",
"enablePullDownRefresh": true
}
},
{
"path" : "pages/plans/plans",
"style" :
{
"navigationBarTitleText": "产品方案",
"enablePullDownRefresh": true
}
},
{
"path" : "pages/person/person",
"style" :
{
"navigationBarTitleText": "我的",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
}
,{
},
{
"path" : "pages/reg/reg",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
}
],
"subPackages": [
@ -148,9 +133,24 @@
"style" :
{
"navigationBarTitleText": "购物车",
"enablePullDownRefresh": true
}
},
{
"path" : "serviceAgreement/serviceAgreement",
"style" :
{
"navigationBarTitleText" : "用户服务协议",
"enablePullDownRefresh" : false
}
},
{
"path" : "privacyAgreement/privacyAgreement",
"style" :
{
"navigationBarTitleText" : "用户隐私协议",
"enablePullDownRefresh" : false
}
}
]
},
@ -162,15 +162,26 @@
"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
}
@ -243,7 +254,9 @@
"path" : "article/article",
"style" :
{
"navigationBarTitleText": "",
"navigationBarTitleText": "学习",
"navigationBarTextStyle": "black",
"navigationBarBackgroundColor": "#fff",
"enablePullDownRefresh": false
}
}
@ -276,7 +289,7 @@
"current": 0, //list
"list": [{
"name": "test", //
"path": "pages/login/login" //
"path": "pages/index/index" //
}]
},
"globalStyle": {
@ -293,8 +306,8 @@
"selectedColor": "#007FFF",
"borderStyle": "white",
"backgroundColor": "#ffffff",
"fontSize": "16px",
"iconWidth": "30px",
"fontSize": "22px",
"iconWidth": "20px",
"list": [{
"pagePath": "pages/index/index",
"iconPath": "static/image/tab1.png",

@ -1,9 +1,24 @@
<template>
<view :class="['page', {oh: !per}]">
<uni-search-bar class="search" radius="30" placeholder="请输入" v-model="keyword" clearButton="auto" cancelButton="none" @confirm="searchConfirm" />
<view :class="[{oh: !per}]">
<view class="banner">
<image class="img" src="@/static/image/index/banner.png" mode="widthFix"></image>
<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>
<view class="rect"></view>
</view>
<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="block" style="margin-top: 0">
@ -12,30 +27,26 @@
</view>
<ul class="tags">
<li v-for="(tag, i) in tags" :key="i" @click="toHot(tag)">
<image class="icon" :src="require('@/static/image/index/' + (i + 1) + '.png')"></image>
<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="block">
<view class="title-wrap">
<view class="title">热销产品</view>
<view class="all" @click="toProduct">全部产品</view>
</view>
<view class="list">
<view v-for="(item, i) in hotProducts" :key="i" class="item" @click="toDetail(item)">
<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.productIntroduction }}</view>
<view class="meta">
<image class="icon" src="@/static/image/index/9.png"></image>
适用专业:
<text class="ell">{{ item.professionalName }}</text>
</view>
<view class="des ell">{{ item.tagsName }}</view>
<view class="meta">{{ item.marketUnitPrice }}/</view>
</view>
</view>
</view>
@ -45,31 +56,33 @@
<view class="block" style="margin-top: 40rpx">
<view class="title-wrap">
<view class="title">官方推荐</view>
<view class="all" @click="toProduct">全部产品</view>
</view>
<view class="list">
<view v-for="(item, i) in offcialProducts" :key="i" class="item" @click="toDetail(item)">
<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.productIntroduction }}</view>
<view class="meta">
<image class="icon" src="@/static/image/index/9.png"></image>
适用专业:
<text class="ell">{{ item.professionalName }}</text>
<view class="des ell">{{ item.tagsName }}</view>
<view class="meta">{{ item.marketUnitPrice }}/</view>
</view>
</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 { tagsList, listOfGoods } from '@/apis/modules/product.js'
import { tagsList, listOfGoods, shoppingCartList } from '@/apis/modules/product.js'
import { getTeamsByAccountId } from '@/apis/modules/client.js'
export default {
data() {
@ -81,12 +94,27 @@
tags: [],
hotProducts: [],
offcialProducts: [],
total: 0,
customStyle: {
width: '46rpx',
height: '46rpx',
lineHeight: '40rpx',
fontSize: '34rpx'
}
}
},
onShow() {
this.keyword = ''
this.per = true
//
if (uni.getStorageSync('token')) {
this.getInfo()
this.getShopCart()
} else {
this.getTags()
this.getProducts()
}
},
methods: {
//
@ -99,7 +127,7 @@
},
//
getAuth() {
uni.getStorageSync('token') && getUserRolesPermissionMenu({
getUserRolesPermissionMenu({
teamId: this.list.find(e => e.teamId == this.teamId).partnerClassificationId,
platformId: 4
}).then(({ permissionMenu }) => {
@ -150,8 +178,8 @@
// 退
uni.hideLoading()
uni.clearStorageSync()
uni.navigateTo({
url: '../login/login'
uni.redirectTo({
url: '../index/index'
})
}
@ -167,6 +195,15 @@
this.tags = res.tagsList.slice(0, 8)
}).catch(e => {})
},
//
getShopCart() {
shoppingCartList({
pageNum: 1,
pageSize: 1000,
}).then(({ data }) => {
this.total = data.total
}).catch(e => {})
},
//
getProducts() {
//
@ -200,19 +237,11 @@
},
//
searchConfirm(e) {
e.value && this.$util.to(`/order/products/products?keyword=${e.value}`)
},
//
toHot(item) {
this.$util.to(`/order/products/products?tagId=${item.tagsId}&tagsName=${item.tagsName}`)
if (e.value) this.$util.to(uni.getStorageSync('token') ? `/order/products/products?keyword=${e.value}` : '../login/login')
},
//
toProduct() {
this.$util.to('/order/products/products')
},
//
toDetail(item) {
this.$util.to('/order/productDetail/productDetail?id=' + item.mallId)
//
to(url) {
this.$util.to(uni.getStorageSync('token') ? url : '../login/login')
},
}
}
@ -221,31 +250,74 @@
<style scoped lang="scss">
.page {
position: relative;
min-height: 100%;
padding: 10rpx 22rpx;
margin-top: -61rpx;
box-sizing: border-box;
background-color: #fff;
border-top-left-radius: 16px;
border-top-right-radius: 16px;
}
.banner {
position: relative;
.img {
.pic {
width: 100%;
}
.bg1 {
position: absolute;
top: -120rpx;
left: -380rpx;
width: 100%;
transform: rotate(20deg);
}
.logo {
width: 70rpx;
margin-right: 14rpx;
}
.info {
.texts {
position: absolute;
top: 80rpx;
left: 46rpx;
top: 230rpx;
left: 0;
width: 100%;
text-align: center;
color: #fff;
}
.title {
margin-bottom: 15rpx;
font-size: 36rpx;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 22rpx;
font-size: 48rpx;
font-family: AlimamaShuHeiTi-Bold, AlimamaShuHeiTi;
font-weight: 600;
color: #001D67;
}
.text {
font-size: 20rpx;
font-family: PingFangSC-Regular, PingFang SC;
color: #001D67;
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);
}
}
.search-wrap {
display: flex;
justify-content: space-between;
align-items: center;
.search {
flex: 1;
}
}
.all {
font-size: 24rpx;
border-radius: 20px;
&::after {
border: none;
}
}
.block {
@ -254,10 +326,6 @@
display: flex;
justify-content: space-between;
margin-bottom: 34rpx;
.all {
font-size: 24rpx;
color: #666;
}
}
.title {
display: inline-flex;
@ -282,14 +350,29 @@
width: 25%;
margin-bottom: 24rpx;
text-align: center;
&:last-child {
image {
width: 50rpx;
height: 50rpx;
}
}
}
.icon {
width: 70rpx;
height: 70rpx;
margin-bottom: 18rpx;
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%;
}
image {
width: 60rpx;
height: 60rpx;
}
.text {
width: 110rpx;
width: 165rpx;
margin: 0 auto;
font-size: 24rpx;
color: #333;
@ -298,12 +381,14 @@
.list {
.item {
display: flex;
align-items: center;
margin-bottom: 28rpx;
}
.pic {
width: 136rpx;
height: 136rpx;
width: 100rpx;
height: 100rpx;
margin-right: 20rpx;
border-radius: 8px;
}
.texts {
width: calc(100% - 156rpx);
@ -314,8 +399,8 @@
color: #333;
}
.des {
margin: 17rpx 0;
font-size: 24rpx;
margin: 10rpx 0;
font-size: 22rpx;
color: #666;
}
.meta {
@ -333,4 +418,14 @@
}
}
}
.plus {
bottom: 140rpx;
right: 60rpx;
.icon {
width: 106rpx;
}
.uni-badge {
font-size: 32rpx;
}
}
</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: '',
@ -57,7 +58,6 @@
} else {
uni.clearStorageSync()
this.isLogin = false
this.getPhone = false
}
},
//
@ -70,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()
@ -95,9 +137,11 @@
} else {
this.isLogin = true
}
}).catch(e => {
}
} catch (e) {
this.submiting = false
})
}
}
} else {
this.submiting = false
that.$util.errMsg('登录失败!')
@ -114,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'
})
})
}
}
},
//
@ -156,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({
@ -166,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
})
@ -191,7 +249,7 @@
}
},
toAgreement(id) {
this.$util.openFile(id)
this.$util.to(id ? `/order/privacyAgreement/privacyAgreement` : `/order/serviceAgreement/serviceAgreement`)
},
//
toIndex() {
@ -221,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 :class="[{oh: !per}]">
<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">
@ -60,7 +61,9 @@
<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 v-if="!per" class="per-mask">功能升级中敬请期待...</view>
</view>
<notAuth v-if="!per"></notAuth>
</view>
</template>
@ -89,6 +92,10 @@
title: "已完成",
value: 1
},
{
title: "已取消",
value: 2
},
],
}
],
@ -146,12 +153,13 @@
},
onShow() {
this.per = true
//
//
try {
uni.removeStorageSync('orderForm')
uni.removeStorageSync('courses')
} catch (e) {}
this.initRole()
this.$uma.trackEvent('order') //
},
methods: {
//
@ -159,6 +167,38 @@
const auth = uni.getStorageSync('auth')
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({
@ -175,7 +215,7 @@
this.curTab = this.tabs[0].id
this.tabs = []
}
this.initList()
this.per && this.initList()
},
getList() {
const data = {
@ -196,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
@ -263,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;
@ -315,7 +357,4 @@
color: #bdbdbd;
}
}
.oh {
overflow: hidden;
}
</style>

@ -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">
@ -16,7 +17,14 @@
<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>
@ -90,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: ''
@ -108,6 +120,7 @@
},
avatar: uni.getStorageSync('avatar') || '@/static/image/avatar.png',
userName: uni.getStorageSync('userName'),
hasOwnTeam: 0, //
disabled: true,
provinces: [],
cities: [],
@ -128,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: {
//
@ -142,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')
@ -150,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)
@ -162,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`)
@ -227,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;
@ -293,8 +388,8 @@
align-items: center;
}
.icon {
width: 48rpx;
height: 48rpx;
width: 40rpx;
height: 40rpx;
margin-right: 16rpx;
}
text {

@ -1,219 +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, tagsList, listOfGoods } 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() {
listOfGoods({
pageNum: this.page,
pageSize: this.pageSize,
sort: 0,
isShelves: 0,
hotTag: 1,
productName: this.keyword,
}).then(({ page }) => {
// list
const list = page.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 === 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()
},
//
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;
}
}

@ -1,9 +1,12 @@
<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>
@ -14,20 +17,20 @@
</view>
<ul class="entry">
<li v-if="auth('工作台:客户')" @click="$util.to('/order/clients/clients')">
<li @click="toModule('client')">
<image class="icon" src="@/static/image/workbench/index3.png" mode="widthFix"></image>
<view class="text">客户</view>
</li>
<li v-if="auth('工作台:方案')" @click="$util.to('../plans/plans')">
<li @click="toModule('plan')">
<image class="icon" src="@/static/image/workbench/index4.png" mode="widthFix"></image>
<view class="text">方案</view>
</li>
<li v-if="auth('工作台:学习')" @click="$util.to('/team/study/study')">
<image class="icon" src="@/static/image/workbench/index11.png" mode="widthFix" style="width: 64rpx"></image>
<li @click="toModule('study')">
<image class="icon" src="@/static/image/workbench/index5.png" mode="widthFix"></image>
<view class="text">学习</view>
</li>
<li v-if="auth('工作台:资讯')" @click="$util.to('/team/info/info')">
<image class="icon" src="@/static/image/workbench/index12.png" mode="widthFix" style="width: 64rpx"></image>
<li @click="toModule('info')">
<image class="icon" src="@/static/image/workbench/index6.png" mode="widthFix"></image>
<view class="text">资讯</view>
</li>
</ul>
@ -143,12 +146,23 @@
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: {
//
@ -163,7 +177,7 @@
},
//
getAuth() {
uni.getStorageSync('token') && getUserRolesPermissionMenu({
getUserRolesPermissionMenu({
teamId: this.list.find(e => e.teamId == this.teamId).partnerClassificationId,
platformId: 4
}).then(({ permissionMenu }) => {
@ -208,19 +222,20 @@
*/
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.navigateTo({
url: '../login/login'
uni.redirectTo({
url: '../index/index'
})
}
this.list = data
this.initRole()
this.getAuth()
}).catch(e => {
uni.hideLoading()
})
@ -273,8 +288,22 @@
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('功能暂未开放!')
@ -287,9 +316,13 @@
.page {
position: relative;
min-height: 100%;
padding: 30rpx 22rpx;
padding: 0 22rpx 30rpx;
box-sizing: border-box;
}
.status-bar {
width: 100%;
// height: calc(var(--status-bar-height));
}
.bg {
z-index: -1;
position: absolute;
@ -299,8 +332,14 @@
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;
@ -333,6 +372,10 @@
.icon {
width: 78rpx;
}
.info-icon {
width: 64rpx;
max-height: 64rpx;
}
.text {
font-size: 28rpx;
color: #333;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 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: 473 B

After

Width:  |  Height:  |  Size: 1007 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 578 B

After

Width:  |  Height:  |  Size: 510 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 434 B

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 B

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 265 B

After

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 440 B

After

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 246 B

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 377 B

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 B

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 468 B

After

Width:  |  Height:  |  Size: 410 B

@ -197,12 +197,17 @@ ul {
.type-popup {
z-index: 10;
position: fixed;
top: 0;
top: 100%;
left: 0;
width: 100%;
height: 100%;
padding: 10rpx;
background-color: #fff;
transition: .3s;
overflow: auto;
&.active {
top: 0;
}
.close {
position: absolute;
top: 50rpx;
@ -256,19 +261,45 @@ ul {
}
}
.per-mask {
z-index: 3;
z-index: 1000;
position: fixed;
top: 0;
left: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
font-size: 28rpx;
color: #333;
background-color: rgba(255, 255, 255, 0.95);
-webkit-user-drag: none;
-webkit-user-select: none;
user-select: none;
.mask {
position: relative;
width: 100%;
height: 100%;
filter: blur(10px);
}
.texts {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 100%;
text-align: center;
}
.text {
margin-bottom: 40rpx;
font-size: 28rpx;
color: #333;
}
.qrcode {
width: 78%;
}
}
.not-auth {
height: 100vh;
padding-bottom: 0 !important;
overflow: hidden;
filter: blur(10px);
}

@ -51,6 +51,9 @@
const { options } = pages[pages.length - 1]
this.id = options.id
this.isInfo = options.info
options.info && uni.setNavigationBarTitle({
title: '资讯'
})
this.getInfo()
},
methods: {

@ -3,15 +3,13 @@
<view class="search-wrap">
<image class="bg" src="@/static/image/info.png"></image>
<view class="info">
<!-- <view class="text">行业资讯与活动</view>
<view class="text">速览</view> -->
<uni-search-bar class="search" radius="30" placeholder="请输入文章名称,标签" v-model="keyword" clearButton="auto" cancelButton="none" bgColor="#fff" />
</view>
</view>
<view class="type">
<view v-for="(item, i) in classifications.slice(0, 4)" :key="i" :class="['item', {active: active == item.id}]" @click="classificationClick(item, 1)">{{ item.classificationName }}</view>
<image class="unfold" src="@/static/image/unfold.png" mode="widthFix" @click="typeVisible = true"></image>
<uni-icons class="icon" custom-prefix="iconfont" type="icon-filter" size="22" color="#007eff" @click="typeVisible = true"></uni-icons>
</view>
<template v-if="list.length">
@ -36,7 +34,7 @@
</template>
<empty v-else></empty>
<view class="type-popup" v-show="typeVisible">
<view :class="['type-popup', {active: typeVisible}]">
<uni-icons class="close" type="closeempty" size="20" color="#757575" @click="closeType"></uni-icons>
<view class="title">所属分类</view>
<view class="types">
@ -215,7 +213,7 @@
font-weight: 600;
}
}
.unfold {
.icon {
position: absolute;
right: 40rpx;
width: 40rpx;

@ -1,12 +1,13 @@
<template>
<view>
<view :class="[{'not-auth': !per}]">
<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>
<uni-icons class="icon" custom-prefix="iconfont" type="icon-filter" size="22" color="#007eff" @click="typeVisible = true"></uni-icons>
</ul>
<view v-if="list.length" class="list">
@ -17,7 +18,8 @@
<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.toggle" class="product ell">{{ item.productNames }}</view>
<view v-else class="product" v-html="item.productNamesHtml"></view>
<view v-if="item.productNames && item.productNames.length > 14" class="toggle" @click.stop="toggle(item)">{{ item.toggle ? '收起' : '展开' }}</view>
</view>
</view>
@ -36,7 +38,7 @@
</view>
<empty v-else></empty>
<view class="type-popup" v-show="typeVisible">
<view :class="['type-popup', {active: typeVisible}]">
<uni-icons class="close" type="closeempty" size="20" color="#757575" @click="closeType"></uni-icons>
<view class="title">所属分类</view>
<view class="types">
@ -44,6 +46,9 @@
</view>
</view>
</view>
<notAuth v-if="!per"></notAuth>
</view>
</template>
<script>
@ -51,6 +56,7 @@
export default {
data() {
return {
per: true, //
active: '',
typeVisible: false,
classifications: [],
@ -88,12 +94,48 @@
}
},
onShow() {
this.per = true
this.keyword = ''
this.active = ''
this.initRole()
},
methods: {
//
initRole() {
const auth = uni.getStorageSync('auth')
if (!auth.includes('工作台:方案')) {
this.per = false
this.list = [
{
title: '智信云',
productNames: '智信云师资培训班',
applicableMajor: 'python实训系统',
updateTime: '2023-08-08'
},
{
title: '智信云',
productNames: '智信云师资培训班智信云师资培训班',
applicableMajor: 'python实训系统',
updateTime: '2023-08-08'
},
{
title: '智信云智信云',
productNames: '智信云师资培训班智信云师资培训班',
applicableMajor: 'python实训系统',
updateTime: '2023-08-08'
},
{
title: '智信云',
productNames: '智信云师资培训班智信云师资培训班',
applicableMajor: 'python实训系统实训系统',
updateTime: '2023-08-08'
},
]
} else {
this.initList()
this.getClassification()
}
},
methods: {
getList() {
uni.showLoading({
title: '加载中'
@ -109,7 +151,10 @@
// list
const list = data.records
list.forEach(e => {
if (e.productNames) e.toggle = e.productNames.length < 14 // 14
if (e.productNames) {
e.toggle = e.productNames.length < 14 // 14
e.productNamesHtml = e.productNames.split(',').join('<br>')
}
})
this.list = this.reachBottom > 0 ? [...this.list, ...list] : list
this.page++ // page+1
@ -175,12 +220,10 @@
li {
padding: 0 30rpx;
}
.unfold {
.icon {
position: absolute;
top: 32rpx;
right: 12rpx;
right: 44rpx;
width: 40rpx;
}
}

@ -11,7 +11,7 @@
</view>
</view>
<view class="com">{{ team.partnerClassificationName }}</view>
<u-qrcode class="qrcode" ref="qrcode" canvas-id="qrcode" isQueueLoadImage :size="size" :value="link" @complete="qrcodeComplete"></u-qrcode>
<u-qrcode v-if="link" class="qrcode" ref="qrcode" canvas-id="qrcode" isQueueLoadImage :size="size" :value="link" @complete="qrcodeComplete"></u-qrcode>
<image class="qrcode-img" :src="qrcodeImg" show-menu-by-longpress @click="previewImage"></image>
<view class="tips" style="margin-top: 20rpx;">扫一扫加入我们吧</view>
@ -63,15 +63,19 @@
generateInvitationCode(uni.getStorageSync('team').accountId).then(({ expireTime }) => {
const date = new Date(Date.now() + expireTime * 1000) // *1000
this.expireTime = `${date.getFullYear()}-${this.$util.preZero(date.getMonth() + 1)}-${this.$util.preZero(date.getDate())} ${this.$util.preZero(date.getHours())}:${this.$util.preZero(date.getMinutes())}:${this.$util.preZero(date.getMinutes())}`
this.link = `https://huorantech.cn/#/join?accountId=${team.accountId}&id=${team.teamId}&isTeam=0&teamName=${this.my.info.userName}&provinceId=${uni.getStorageSync('provinceId')}&cityId=${uni.getStorageSync('cityId')}`
this.link = `https://www.occupationlab.com/#/join?accountId=${team.accountId}&id=${team.teamId}&isTeam=0&teamName=${this.my.info.userName}&provinceId=${uni.getStorageSync('provinceId')}&cityId=${uni.getStorageSync('cityId')}`
// this.link = `http://121.37.12.51/backstage/#/join?accountId=${team.accountId}&id=${team.teamId}&isTeam=0&teamName=${this.my.info.userName}&provinceId=${uni.getStorageSync('provinceId')}&cityId=${uni.getStorageSync('cityId')}`
}).catch(e => {})
},
// imageimage
qrcodeComplete() {
console.log('complete', this.$refs.qrcode.toTempFilePath, this.link)
this.$refs.qrcode.toTempFilePath({
success: res => {
this.qrcodeImg = res.tempFilePath
},
fail: res => {
console.log('fail', res)
}
});
},

@ -4,7 +4,7 @@
<view class="text">{{ form.applicableMajor }}</view>
<view class="text">{{ form.schemeIntroduction }}</view>
<view class="text">{{ form.product }}</view>
<view class="text" v-html="form.product"></view>
<template v-if="form.fileName">
<view class="file">{{ form.fileName }}</view>
<view class="detail" @click.stop="download">下载</view>
@ -36,7 +36,7 @@
title: '加载中'
})
schemeFindById(this.id).then(({ data }) => {
if (data.productList) data.product = data.productList.map(e => e.productName).join('')
if (data.productList) data.product = data.productList.map(e => e.productName).join('<br>')
this.form = data
uni.hideLoading()
}).catch(e => {

@ -69,7 +69,9 @@
success(res) {
if (res.confirm) {
uni.clearStorageSync()
that.$util.to('/pages/login/login')
uni.reLaunch({
url: '/pages/index/index'
})
}
}
})

@ -10,7 +10,7 @@
<view class="type">
<view v-for="(item, i) in classifications.slice(0, 4)" :key="i" :class="['item', {active: active == item.id}]" @click="classificationClick(item, 1)">{{ item.classificationName }}</view>
<image class="unfold" src="@/static/image/unfold.png" mode="widthFix" @click="typeVisible = true"></image>
<uni-icons class="icon" custom-prefix="iconfont" type="icon-filter" size="22" color="#007eff" @click="typeVisible = true"></uni-icons>
</view>
<template v-if="list.length">
@ -40,7 +40,7 @@
</template>
<empty v-else></empty>
<view class="type-popup" v-show="typeVisible">
<view :class="['type-popup', {active: typeVisible}]">
<uni-icons class="close" type="closeempty" size="20" color="#757575" @click="closeType"></uni-icons>
<view class="title">所属分类</view>
<view class="types">
@ -221,7 +221,7 @@
font-weight: 600;
}
}
.unfold {
.icon {
position: absolute;
right: 40rpx;
width: 40rpx;

Loading…
Cancel
Save