榴莲果配置 扫码加好友

This commit is contained in:
lr 2025-02-18 11:38:36 +08:00
parent e6d75c5a01
commit d77e175b52
20 changed files with 1123 additions and 601 deletions

View File

@ -72,5 +72,15 @@ export const durian = {
load: true, load: true,
}) })
}, },
/**
* 榴莲果配置
* @param {Object} param
*/
durianFruitConfig() {
return util.request({
url: `/coreplay/durianFruitTransactionType/10`,
method: 'GET',
})
},
} }
export default durian export default durian

View File

@ -449,6 +449,31 @@ const shop = {
query: param, query: param,
}) })
}, },
/**
* 根据店铺id查商品列表
* @param {Object} param
*/
getShopProductList(param) {
return util.request({
url: `/shopify/appProductionApi/getProductionList`,
method: 'GET',
query: param,
})
},
/**
* 查询用户在当前商铺的订单列表
* @param {Object} param
*/
getShopOrderList(param) {
return util.request({
url: `/shopify/appOrder/getOrderList`,
method: 'GET',
query: param,
})
},
} }
export default shop export default shop

View File

@ -8,6 +8,7 @@ const config = {
// #ifndef H5 // #ifndef H5
// host: 'http://91f.xyz:8080', // host: 'http://91f.xyz:8080',
host: 'https://b433d23.r24.cpolar.top/', host: 'https://b433d23.r24.cpolar.top/',
// host: 'http://hvw2rn.natappfree.cc',
// #endif // #endif
// 支付方式配置 // 支付方式配置
payType: { payType: {

View File

@ -110,6 +110,28 @@ function handleList(list) {
if (item.groupId != null) { if (item.groupId != null) {
item.unreadCount = getGroupNoReadNum(item.groupId) item.unreadCount = getGroupNoReadNum(item.groupId)
} }
if (item.callbackJson.callback_json.length) {
let msgType = item.callbackJson.callback_json[0].MsgType;
if (msgType == TencentCloudChat.TYPES.MSG_TEXT) {
item.chatText = item.callbackJson.callback_json[0].MsgContent.Text
} else if (msgType == TencentCloudChat.TYPES.MSG_IMAGE) {
item.chatText = '[图片]'
} else if (msgType == TencentCloudChat.TYPES.MSG_AUDIO) {
item.chatText = '[语音]'
} else if (msgType == TencentCloudChat.TYPES.MSG_VIDEO) {
item.chatText = '[视频]'
} else if (msgType == TencentCloudChat.TYPES.MSG_CUSTOM) {
if (item.callbackJson.callback_json[0].businessType == 'redPacket') {
item.chatText = `[红包] ${item.callbackJson.blessing}`
} else if (item.callbackJson.callback_json[0].businessType == '1') {
// if (item.callbackJson.callback_json[0].call_type == '1') {
// item.chatText = '[]'
// } else if (item.callbackJson.callback_json[0].call_type == '2') {
// item.chatText = '[]'
// }
}
}
}
}) })
return list return list
@ -297,8 +319,7 @@ function setRead(item) {
<view class="datetime c999 f22"> <view class="datetime c999 f22">
{{ util.formatTime('MM-dd HH:mm', item.createTime) }}</view> {{ util.formatTime('MM-dd HH:mm', item.createTime) }}</view>
</view> </view>
<view class="desc thd mt10 c666 f24">{{ <view class="desc thd mt10 c666 f24">{{ item.chatText }}</view>
item.callbackJson.callback_json[0].MsgContent.Text }}</view>
</view> </view>
</view> </view>
</uni-swipe-action-item> </uni-swipe-action-item>

View File

@ -4,15 +4,15 @@
<uni-section> <uni-section>
<template v-slot:decoration> <template v-slot:decoration>
<!-- 商品图 --> <!-- 商品图 -->
<image class="shop-image" :src="orderInfo.productName" mode="aspectFill"></image> <image class="shop-image" :src="orderInfo.productImage" mode="aspectFill"></image>
</template> </template>
<template v-slot:content> <template v-slot:content>
<!-- 订单 | 聊天--> <!-- 订单 | 聊天-->
<template v-if="showType == 1 || showType == 4"> <template v-if="showType == 1 || showType == 4">
<view class="commodity-name commodity-name-1"> <view class="commodity-name commodity-name-1">
<text class="commodity-name-title t2hd">耳钉耳钉耳钉耳钉耳钉耳钉耳钉耳钉耳钉耳钉耳钉</text> <text class="commodity-name-title t2hd">{{ orderInfo.productName }}</text>
<text class="commodity-name-ks thd">X602 款式</text> <text class="commodity-name-ks thd">{{ orderInfo.status_text }}</text>
<text v-if="showType == 4">待发货</text> <text v-if="showType == 4">{{ orderInfo.status }}</text>
</view> </view>
</template> </template>
<!-- 历史浏览 | 收藏 --> <!-- 历史浏览 | 收藏 -->
@ -54,10 +54,10 @@
<view class="price-num"> <view class="price-num">
<view class="df aic price"> <view class="df aic price">
<text class="f20 jg"></text> <text class="f20 jg"></text>
<text class="f28">999.00</text> <text class="f28">{{ orderInfo.productPrice }}</text>
</view> </view>
<!-- 数量 --> <!-- 数量 -->
<text class="c999 f24">x1</text> <text class="c999 f24">x{{ orderInfo.totalNum }}</text>
</view> </view>
<!-- 发送到聊天 --> <!-- 发送到聊天 -->
<view @click.stop="emit('consult', orderInfo)" class="go-buy" v-if="showType == 4"> <view @click.stop="emit('consult', orderInfo)" class="go-buy" v-if="showType == 4">
@ -106,6 +106,10 @@ const props = defineProps({
}) })
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.commodity-information {
padding: 0 20rpx;
}
$h : 164rpx; $h : 164rpx;
.shop-image { .shop-image {

View File

@ -90,21 +90,11 @@ function handleBuy() {
// //
function toCustomer() { function toCustomer() {
api.shop.getCustomerService({ merchantId: props.detail.merId }).then(rs => { api.shop.getCustomerService({ merchantId: props.detail.merId }).then(rs => {
console.log(rs);
//
if (rs.code == 200) { if (rs.code == 200) {
} else {
util.alert(rs.msg)
}
})
let param = {}; let param = {};
param.type = 'C2C' param.type = 'C2C'
param.name = `${props.detail.merName}` param.name = `${props.detail.merName}`
param.msgId = `${props.detail.merId}` param.msgId = `${rs.data.serviceId}`
param.isCustomer = true param.isCustomer = true
util.toChat(param) util.toChat(param)
@ -113,7 +103,10 @@ function toCustomer() {
uni.navigateTo({ uni.navigateTo({
url: util.setUrl('/pages/news/chat/chat', param) url: util.setUrl('/pages/news/chat/chat', param)
}) })
} else {
util.alert(rs.msg)
}
})
} }
</script> </script>
@ -138,10 +131,10 @@ function toCustomer() {
</view> </view>
</view> </view>
<view class="option ver" @click="toCustomer"> <!-- <view class="option ver" @click="toCustomer">
<image class="wh30" src="/static/customer-service.png" mode="aspectFit" /> <image class="wh30" src="/static/customer-service.png" mode="aspectFit" />
<text class="text mt10">客服</text> <text class="text mt10">客服</text>
</view> </view> -->
</view> </view>
<!-- 下单 --> <!-- 下单 -->

View File

@ -0,0 +1,133 @@
// @ts-nocheck
export {};
; declare module 'vue' {
export interface GlobalComponents { }
export interface GlobalDirectives { }
}
; declare global {
const __VLS_intrinsicElements: __VLS_IntrinsicElements;
const __VLS_directiveBindingRestFields: { instance: null, oldValue: null, modifiers: any, dir: any };
const __VLS_unref: typeof import('vue').unref;
const __VLS_placeholder: any;
const __VLS_nativeElements = {
...{} as SVGElementTagNameMap,
...{} as HTMLElementTagNameMap,
};
type __VLS_IntrinsicElements = globalThis.JSX.IntrinsicElements;
type __VLS_Element = globalThis.JSX.Element;
type __VLS_GlobalComponents = import('vue').GlobalComponents & Pick<typeof import('vue'), 'Transition' | 'TransitionGroup' | 'KeepAlive' | 'Suspense' | 'Teleport'>;
type __VLS_GlobalDirectives = import('vue').GlobalDirectives;
type __VLS_IsAny<T> = 0 extends 1 & T ? true : false;
type __VLS_PickNotAny<A, B> = __VLS_IsAny<A> extends true ? B : A;
type __VLS_unknownDirective = (arg1: unknown, arg2: unknown, arg3: unknown, arg4: unknown) => void;
type __VLS_WithComponent<N0 extends string, LocalComponents, Self, N1 extends string, N2 extends string, N3 extends string> =
N1 extends keyof LocalComponents ? N1 extends N0 ? Pick<LocalComponents, N0 extends keyof LocalComponents ? N0 : never> : { [K in N0]: LocalComponents[N1] } :
N2 extends keyof LocalComponents ? N2 extends N0 ? Pick<LocalComponents, N0 extends keyof LocalComponents ? N0 : never> : { [K in N0]: LocalComponents[N2] } :
N3 extends keyof LocalComponents ? N3 extends N0 ? Pick<LocalComponents, N0 extends keyof LocalComponents ? N0 : never> : { [K in N0]: LocalComponents[N3] } :
Self extends object ? { [K in N0]: Self } :
N1 extends keyof __VLS_GlobalComponents ? N1 extends N0 ? Pick<__VLS_GlobalComponents, N0 extends keyof __VLS_GlobalComponents ? N0 : never> : { [K in N0]: __VLS_GlobalComponents[N1] } :
N2 extends keyof __VLS_GlobalComponents ? N2 extends N0 ? Pick<__VLS_GlobalComponents, N0 extends keyof __VLS_GlobalComponents ? N0 : never> : { [K in N0]: __VLS_GlobalComponents[N2] } :
N3 extends keyof __VLS_GlobalComponents ? N3 extends N0 ? Pick<__VLS_GlobalComponents, N0 extends keyof __VLS_GlobalComponents ? N0 : never> : { [K in N0]: __VLS_GlobalComponents[N3] } :
{ [K in N0]: unknown };
type __VLS_FunctionalComponentProps<T, K> =
'__ctx' extends keyof __VLS_PickNotAny<K, {}> ? K extends { __ctx?: { props?: infer P } } ? NonNullable<P> : never
: T extends (props: infer P, ...args: any) => any ? P :
{};
type __VLS_IsFunction<T, K> = K extends keyof T
? __VLS_IsAny<T[K]> extends false
? unknown extends T[K]
? false
: true
: false
: false;
type __VLS_NormalizeComponentEvent<Props, Events, onEvent extends keyof Props, Event extends keyof Events, CamelizedEvent extends keyof Events> = (
__VLS_IsFunction<Props, onEvent> extends true
? Props
: __VLS_IsFunction<Events, Event> extends true
? { [K in onEvent]?: Events[Event] }
: __VLS_IsFunction<Events, CamelizedEvent> extends true
? { [K in onEvent]?: Events[CamelizedEvent] }
: Props
) & Record<string, unknown>;
// fix https://github.com/vuejs/language-tools/issues/926
type __VLS_UnionToIntersection<U> = (U extends unknown ? (arg: U) => unknown : never) extends ((arg: infer P) => unknown) ? P : never;
type __VLS_OverloadUnionInner<T, U = unknown> = U & T extends (...args: infer A) => infer R
? U extends T
? never
: __VLS_OverloadUnionInner<T, Pick<T, keyof T> & U & ((...args: A) => R)> | ((...args: A) => R)
: never;
type __VLS_OverloadUnion<T> = Exclude<
__VLS_OverloadUnionInner<(() => never) & T>,
T extends () => never ? never : () => never
>;
type __VLS_ConstructorOverloads<T> = __VLS_OverloadUnion<T> extends infer F
? F extends (event: infer E, ...args: infer A) => any
? { [K in E & string]: (...args: A) => void; }
: never
: never;
type __VLS_NormalizeEmits<T> = __VLS_PrettifyGlobal<
__VLS_UnionToIntersection<
__VLS_ConstructorOverloads<T> & {
[K in keyof T]: T[K] extends any[] ? { (...args: T[K]): void } : never
}
>
>;
type __VLS_PrettifyGlobal<T> = { [K in keyof T]: T[K]; } & {};
type __VLS_PickFunctionalComponentCtx<T, K> = NonNullable<__VLS_PickNotAny<
'__ctx' extends keyof __VLS_PickNotAny<K, {}> ? K extends { __ctx?: infer Ctx } ? Ctx : never : any
, T extends (props: any, ctx: infer Ctx) => any ? Ctx : any
>>;
type __VLS_OmitStringIndex<T> = {
[K in keyof T as string extends K ? never : K]: T[K];
};
type __VLS_UseTemplateRef<T> = Readonly<import('vue').ShallowRef<T | null>>;
function __VLS_getVForSourceType(source: number): [number, number][];
function __VLS_getVForSourceType(source: string): [string, number][];
function __VLS_getVForSourceType<T extends any[]>(source: T): [
item: T[number],
index: number,
][];
function __VLS_getVForSourceType<T extends { [Symbol.iterator](): Iterator<any> }>(source: T): [
item: T extends { [Symbol.iterator](): Iterator<infer T1> } ? T1 : never,
index: number,
][];
// #3845
function __VLS_getVForSourceType<T extends number | { [Symbol.iterator](): Iterator<any> }>(source: T): [
item: number | (Exclude<T, number> extends { [Symbol.iterator](): Iterator<infer T1> } ? T1 : never),
index: number,
][];
function __VLS_getVForSourceType<T>(source: T): [
item: T[keyof T],
key: keyof T,
index: number,
][];
// @ts-ignore
function __VLS_getSlotParams<T>(slot: T): Parameters<__VLS_PickNotAny<NonNullable<T>, (...args: any[]) => any>>;
// @ts-ignore
function __VLS_getSlotParam<T>(slot: T): Parameters<__VLS_PickNotAny<NonNullable<T>, (...args: any[]) => any>>[0];
function __VLS_asFunctionalDirective<T>(dir: T): T extends import('vue').ObjectDirective
? NonNullable<T['created' | 'beforeMount' | 'mounted' | 'beforeUpdate' | 'updated' | 'beforeUnmount' | 'unmounted']>
: T extends (...args: any) => any
? T
: __VLS_unknownDirective;
function __VLS_withScope<T, K>(ctx: T, scope: K): ctx is T & K;
function __VLS_makeOptional<T>(t: T): { [K in keyof T]?: T[K] };
function __VLS_asFunctionalComponent<T, K = T extends new (...args: any) => any ? InstanceType<T> : unknown>(t: T, instance?: K):
T extends new (...args: any) => any
? (props: (K extends { $props: infer Props } ? Props : any) & Record<string, unknown>, ctx?: any) => __VLS_Element & { __ctx?: {
attrs?: any,
slots?: K extends { $scopedSlots: infer Slots } ? Slots : any,
emit?: K extends { $emit: infer Emit } ? Emit : any
} & { props?: (K extends { $props: infer Props } ? Props : any) & Record<string, unknown>; expose?(exposed: K): void; } }
: T extends () => any ? (props: {}, ctx?: any) => ReturnType<T>
: T extends (...args: any) => any ? T
: (_: {} & Record<string, unknown>, ctx?: any) => { __ctx?: { attrs?: any, expose?: any, slots?: any, emit?: any, props?: {} & Record<string, unknown> } };
function __VLS_asFunctionalElement<T>(tag: T, endTag?: T): (_: T & Record<string, unknown>) => void;
function __VLS_functionalComponentArgsRest<T extends (...args: any) => any>(t: T): 2 extends Parameters<T>['length'] ? [any] : [];
function __VLS_normalizeSlot<S>(s: S): S extends () => infer R ? (props: {}) => R : S;
function __VLS_tryAsConstant<const T>(t: T): T;
}

View File

@ -1,11 +1,11 @@
<script setup> <script setup>
/** /**
* 榴莲首页 * 榴莲首页
*/ */
import { import {
useStore, useStore,
} from 'vuex' } from 'vuex'
import { import {
onMounted, onMounted,
ref, ref,
reactive, reactive,
@ -13,30 +13,30 @@
getCurrentInstance, getCurrentInstance,
watch, watch,
defineExpose, defineExpose,
} from 'vue'; } from 'vue';
import { import {
onLoad, onLoad,
onReady, onReady,
onHide, onHide,
} from '@dcloudio/uni-app' } from '@dcloudio/uni-app'
// //
import noLogin from '@/components/login/noLogin.vue' import noLogin from '@/components/login/noLogin.vue'
// //
import util from '@/common/js/util.js' import util from '@/common/js/util.js'
// //
import task from '@/components/index/task' import task from '@/components/index/task'
// //
import api from '@/api/index.js' import api from '@/api/index.js'
// //
import payPwd from '@/components/mine/payPwd.vue' import payPwd from '@/components/mine/payPwd.vue'
const { const {
proxy proxy
} = getCurrentInstance() } = getCurrentInstance()
// //
const store = useStore() const store = useStore()
// //
const form = reactive({ const form = reactive({
// ID // ID
targetUserId: '', targetUserId: '',
// //
@ -49,38 +49,46 @@
name: '', name: '',
// //
secondPassword: '', secondPassword: '',
}) })
// //
const viewData = ref({ const viewData = ref({
seconds: 0 seconds: 0
}) })
// //
const userinfo = computed(() => { const userinfo = computed(() => {
return store.state.userinfo return store.state.userinfo
}) })
// //
const progress = computed(() => { const progress = computed(() => {
let result = viewData.value.seconds let result = viewData.value.seconds
result = Math.min(Number(result), 100) result = Math.min(Number(result), 100)
return result return result
}) })
// //
const purse = computed(() => { const purse = computed(() => {
return store.state.purse || {} return store.state.purse || {}
}) })
onReady(() => { //
const configData = reactive({
minConsumption: '',
platformPercentage: ''
})
onReady(() => {
// proxy.$refs.dealRef.open() // proxy.$refs.dealRef.open()
// proxy.$refs.payPwdRef.open() // proxy.$refs.payPwdRef.open()
}) })
onLoad(() => { onLoad(() => {
// //
util.getPurse() util.getPurse()
})
// getConfig()
function handleSubmit() { })
//
function handleSubmit() {
// //
if (!form.account) { if (!form.account) {
util.alert('请输入账号') util.alert('请输入账号')
@ -111,10 +119,10 @@
showCancel: false, showCancel: false,
}) })
}) })
} }
// //
function handlePayeeConfirm() { function handlePayeeConfirm() {
// //
if (!form.first) { if (!form.first) {
util.alert('请输入对方姓名首字母') util.alert('请输入对方姓名首字母')
@ -138,13 +146,13 @@
showCancel: false, showCancel: false,
}) })
}) })
} }
/** /**
* 交易 * 交易
* @param {Object} ev 二级密码 * @param {Object} ev 二级密码
*/ */
function handlePwdConfirm(ev) { function handlePwdConfirm(ev) {
// //
if (!form.first) { if (!form.first) {
util.alert('请输入对方姓名首字母') util.alert('请输入对方姓名首字母')
@ -192,14 +200,30 @@
showCancel: false, showCancel: false,
}) })
}) })
} }
// //
function navigateToPage(path) { function navigateToPage(path) {
uni.navigateTo({ uni.navigateTo({
url: path url: path
}) })
}
//
function getConfig() {
api.durian.durianFruitConfig().then(rs => {
if (rs.code == 200) {
configData.minConsumption = rs.data.minConsumption
configData.platformPercentage = +rs.data.platformPercentage * 100
return;
} }
util.alert({
content: rs.msg,
showCancel: false,
})
})
}
</script> </script>
<template> <template>
@ -221,7 +245,7 @@
<image class="wh110" src="/static/sapling.png" mode="aspectFit" /> <image class="wh110" src="/static/sapling.png" mode="aspectFit" />
</view> </view>
<view class="f1 fmid"> <view class="f1 fmid">
<view class=" f38 b wsn">* {{purse.seed}}</view> <view class=" f38 b wsn">* {{ purse.seed }}</view>
</view> </view>
</view> </view>
</view> </view>
@ -254,8 +278,8 @@
<navigator url="/pages/index/durianLog" hover-class="none"> <navigator url="/pages/index/durianLog" hover-class="none">
<image class="fruit wh150" src="/static/fruit.png" mode="aspectFit" /> <image class="fruit wh150" src="/static/fruit.png" mode="aspectFit" />
<view class="mt30 f20"> <view class="mt30 f20">
<view class=" f1 b">可用: {{purse.fruit}}</view> <view class=" f1 b">可用: {{ purse.fruit }}</view>
<view class="cFF4242 f1 mt10">待释放: 105.53</view> <view class="cFF4242 f1 mt10">待释放: {{ purse.fruitFrozen }}</view>
</view> </view>
</navigator> </navigator>
</view> </view>
@ -296,8 +320,8 @@
</view> </view>
<view class="hint mtb30 tac f22"> <view class="hint mtb30 tac f22">
<view>销毁15%</view> <view>销毁{{ configData.platformPercentage }}%</view>
<view>(最低x起转)</view> <view>(最低{{ configData.minConsumption }}起转)</view>
</view> </view>
<view class="button btn lg bar black" @click="handleSubmit">转移</view> <view class="button btn lg bar black" @click="handleSubmit">转移</view>
@ -314,7 +338,7 @@
<view class="inputBox rows mauto mtb20 plr30"> <view class="inputBox rows mauto mtb20 plr30">
<input class="first" v-model.trim="form.first" type="text" placeholder="" /> <input class="first" v-model.trim="form.first" type="text" placeholder="" />
<view class="">*</view> <view class="">*</view>
<view class="f1 tar">{{form.name}}</view> <view class="f1 tar">{{ form.name }}</view>
</view> </view>
<view class="rows mt50"> <view class="rows mt50">
@ -330,33 +354,33 @@
</template> </template>
<style lang="scss"> <style lang="scss">
// //
.board { .board {
background-image: linear-gradient(103deg, #27EFE2 0%, #A45EFF 43%, #FF004F 100%); background-image: linear-gradient(103deg, #27EFE2 0%, #A45EFF 43%, #FF004F 100%);
} }
// //
.bgColor { .bgColor {
background-color: #FFFBF3; background-color: #FFFBF3;
border-radius: 20rpx; border-radius: 20rpx;
} }
.explain { .explain {
.button { .button {
width: 250rpx; width: 250rpx;
margin-left: 0; margin-left: 0;
} }
} }
// //
.sapling { .sapling {
.button { .button {
width: 300rpx; width: 300rpx;
} }
} }
// //
.durianSection { .durianSection {
// //
.notice { .notice {
@ -369,18 +393,18 @@
border-radius: 100rpx; border-radius: 100rpx;
} }
} }
} }
// //
.dealAlt { .dealAlt {
.hint { .hint {
color: #3d3d3d; color: #3d3d3d;
opacity: .7; opacity: .7;
} }
} }
// //
.payee { .payee {
.inputBox { .inputBox {
width: 120rpx; width: 120rpx;
box-shadow: 0 0 20rpx rgba(0, 0, 0, .2); box-shadow: 0 0 20rpx rgba(0, 0, 0, .2);
@ -389,5 +413,5 @@
.first { .first {
width: 50rpx; width: 50rpx;
} }
} }
</style> </style>

View File

@ -1,69 +1,76 @@
<script setup> <script setup>
/** /**
* 添加朋友 * 添加朋友
*/ */
// //
import util from '@/common/js/util'; import util from '@/common/js/util';
// api // api
import api from '@/api/index.js' import api from '@/api/index.js'
import { import {
useStore, useStore,
} from 'vuex' } from 'vuex'
import { import {
ref, ref,
reactive, reactive,
computed, computed,
getCurrentInstance getCurrentInstance
} from 'vue' } from 'vue'
import { import {
onLoad, onLoad,
onReady, onReady,
onReachBottom, onReachBottom,
onPullDownRefresh onPullDownRefresh
} from '@dcloudio/uni-app' } from '@dcloudio/uni-app'
// //
const { const {
proxy proxy
} = getCurrentInstance() } = getCurrentInstance()
// vuex // vuex
const store = useStore() const store = useStore()
// //
const userinfo = computed(() => { const userinfo = computed(() => {
let result = store.state.userinfo let result = store.state.userinfo
return result return result
}) })
// //
const userList = reactive({ const userList = reactive({
data: [], data: [],
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
total: 0, total: 0,
}) })
const keyword = ref('') const keyword = ref('')
// //
const form = reactive({ const form = reactive({
Remark: '', Remark: '',
AddWording: '', AddWording: '',
}) })
// //
const friend = ref({}) const friend = ref({})
onReady(() => { onLoad((option) => {
if (option.account) {
keyword.value = option.account
refreshFriendList()
}
})
onReady(() => {
// proxy.$refs.friendRef.open() // proxy.$refs.friendRef.open()
}) })
onReachBottom(() => { onReachBottom(() => {
// //
getMoreFriendList() getMoreFriendList()
}) })
onPullDownRefresh(() => { onPullDownRefresh(() => {
refreshFriendList() refreshFriendList()
}) })
// //
function getSearchFriendList() { function getSearchFriendList() {
if (!keyword.value) { if (!keyword.value) {
util.alert('请输入你想搜索的内容') util.alert('请输入你想搜索的内容')
return return
@ -95,49 +102,49 @@
}).finally(() => { }).finally(() => {
uni.stopPullDownRefresh() uni.stopPullDownRefresh()
}) })
} }
// //
function refreshFriendList() { function refreshFriendList() {
userList.pageNum = 1 userList.pageNum = 1
userList.total = 0 userList.total = 0
getSearchFriendList() getSearchFriendList()
} }
// //
function getMoreFriendList() { function getMoreFriendList() {
if (userList.data.length >= userList.total) return if (userList.data.length >= userList.total) return
userList.pageNum++ userList.pageNum++
getSearchFriendList() getSearchFriendList()
} }
// //
function handleUser(item) { function handleUser(item) {
uni.navigateTo({ uni.navigateTo({
url: util.setUrl('/pages/index/videoHome', { url: util.setUrl('/pages/index/videoHome', {
userId: item.userId, userId: item.userId,
}) })
}) })
} }
/** /**
* 添加好友 * 添加好友
* @param {Object} item 用户信息 * @param {Object} item 用户信息
*/ */
function handleAdd(item) { function handleAdd(item) {
friend.value.userId = item.userId friend.value.userId = item.userId
friend.value.userName = item.userName friend.value.userName = item.userName
friend.value.AddWording = `你好,我是${userinfo.value.userNickname}` friend.value.AddWording = `你好,我是${userinfo.value.userNickname}`
proxy.$refs.friendRef.open() proxy.$refs.friendRef.open()
} }
// //
function pushNickname() { function pushNickname() {
friend.value.Remark = friend.value.userName friend.value.Remark = friend.value.userName
} }
// //
function addFriendConfirm() { function addFriendConfirm() {
api.news.addFriend({ api.news.addFriend({
data: [{ data: [{
toAccount: friend.value.userId, toAccount: friend.value.userId,
@ -155,7 +162,7 @@
showCancel: false, showCancel: false,
}) })
}) })
} }
</script> </script>
<template> <template>
<view class="app"> <view class="app">
@ -169,14 +176,14 @@
</view> </view>
<view class="listArea plr30 bfff"> <view class="listArea plr30 bfff">
<view class="item rows ptb30 c333 f32" v-for="(item,index) in userList.data" :key="index" <view class="item rows ptb30 c333 f32" v-for="(item, index) in userList.data" :key="index"
@click="handleUser(item)"> @click="handleUser(item)">
<view class="avatar fs0"> <view class="avatar fs0">
<image class="wh100 cir" :src="item.imageUrl" mode="aspectFill" /> <image class="wh100 cir" :src="item.imageUrl" mode="aspectFill" />
</view> </view>
<view class="content f1 mlr20"> <view class="content f1 mlr20">
<view class="name">{{item.userName}}</view> <view class="name">{{ item.userName }}</view>
<!-- <view class="time c999 f22">{{item.createTime}}</view> --> <!-- <view class="time c999 f22">{{item.createTime}}</view> -->
</view> </view>
@ -227,14 +234,14 @@
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.search { .search {
background-color: #eaeaea; background-color: #eaeaea;
} }
// //
.listArea { .listArea {
.item+.item { .item+.item {
border-top: 1rpx solid #ddd; border-top: 1rpx solid #ddd;
} }
} }
</style> </style>

View File

@ -12,6 +12,8 @@ import {
screenHeight screenHeight
} from '@/components/public/Mixins' } from '@/components/public/Mixins'
import JyCommodityInformation from '@/components/public/jy-commodity-information' import JyCommodityInformation from '@/components/public/jy-commodity-information'
// api
import api from '@/api/index.js'
// //
import util from '@/common/js/util.js' import util from '@/common/js/util.js'
import { inject } from 'vue' import { inject } from 'vue'
@ -75,6 +77,9 @@ const popupData = reactive({
title: '选择订单' title: '选择订单'
}) })
//
const list = reactive([])
// //
const plusClickObj = { const plusClickObj = {
voice: () => { voice: () => {
@ -109,14 +114,49 @@ const plusClickObj = {
// //
chooseOrder: () => { chooseOrder: () => {
let param = {
pageSize: 10,
pageNum: 1,
merId: props.msg.id,
}
api.shop.getShopOrderList(param).then(rs => {
if (rs.code == 200) {
list.length = 0
list.push(...rs.rows.map(item => {
//
item.status = Number(item.status)
//
item.status_text = {
'0': '待支付',
'1': '待发货',
'4': '待收货',
'5': '已收货',
'6': '已完成',
'9': '已取消',
}[item.status]
return item
}))
nextTick().then(() => { nextTick().then(() => {
popupRef.value.open() popupRef.value.open()
}); });
return
}
util.alert({
content: rs.msg,
showCancel: false,
})
})
}, },
// //
chooseShop: () => { chooseShop: () => {
checkLink('pages/news/goodsList/index') uni.navigateTo({
url: `/pages/news/goodsList/index?merId=${props.msg.id}`
});
}, },
// //
@ -228,11 +268,11 @@ const consult = (content) => {
</uni-easyinput> </uni-easyinput>
</view> </view>
<scroll-view scroll-y scroll-with-animation> <scroll-view scroll-y scroll-with-animation>
<view v-for="(item, index) in 2"> <view v-for="(item, index) in list" :key="index">
<view class="time"> <view class="time">
下单时间2024-07-28 22:45:25 下单时间{{ item.createTime }}
</view> </view>
<JyCommodityInformation :showType="4" @consult="consult"></JyCommodityInformation> <JyCommodityInformation :showType="4" :orderInfo="item" @consult="consult"></JyCommodityInformation>
</view> </view>
</scroll-view> </scroll-view>
</view> </view>

View File

@ -1,22 +1,122 @@
<script setup> <script setup>
/** /**
* 客服聊天界面商品列表 * 客服聊天界面商品列表
*/ */
import {
reactive,
defineExpose,
} from 'vue'
//
import util from '@/common/js/util.js'
// api
import api from '@/api/index.js'
// import { onLoad } from "@dcloudio/uni-app"
import JyCommodityInformation from '@/components/public/jy-commodity-information'
//
const listPrototype = reactive({
pageSize: 10,
pageNum: 1,
total: 0,
merId: '',
data: [],
})
onLoad(option => {
getList(option)
})
/**
* 点击列表项
* @param {Object} item 列表项
*/
function handleItem(item) {
//
uni.navigateTo({
url: util.setUrl('/pages/shop/commodity/index', {
productId: item.id
})
})
}
//
function refreshList() {
listPrototype.pageNum = 1
listPrototype.total = 0
getList()
}
//
function getMoreList() {
console.log('getMoreList', listPrototype)
if (listPrototype.total <= listPrototype.data.length) return
listPrototype.pageNum++
getList()
}
//
function getList(option) {
let param = {
pageSize: listPrototype.pageSize,
pageNum: listPrototype.pageNum,
merId: option.merId
}
api.shop.getShopProductList(param).then(rs => {
if (rs.code == 200) {
if (listPrototype.pageNum == 1) listPrototype.data.length = []
listPrototype.data.push(...rs.rows)
listPrototype.total = rs.total
return
}
util.alert({
content: rs.msg,
showCancel: false,
})
}).finally(rs => {
uni.stopPullDownRefresh()
})
}
//
function sendProduct(item) {
console.log('发送商品', item);
}
defineExpose({
getList,
listPrototype,
refreshList,
getMoreList,
})
</script> </script>
<template> <template>
<view class="appbw"> <view class="list">
<scroll-view scroll-y scroll-with-animation> <view class="product line df ptb20 plr20" v-for="(item, index) in listPrototype.data" :key="index"
<view v-for="(item, index) in 10"> @click="handleItem(item)">
<JyCommodityInformation :showType="5"></JyCommodityInformation>
<view class="poster wh160">
<image class="wh160 br10" :src="item.sliderImage.split(',')[0]" mode="aspectFill" />
</view>
<view class="info df fdc jcsb f1 ml20">
<view class="name t2hd c333 f28">{{ item.name }}</view>
<view class="other rows">
<view class="col c333">
<text class="f20"></text>
<text class="f30">{{ item.price }}</text>
<text class="count ml20 fs0 c999 f24">销量{{ item.sales }}</text>
</view>
<view @click.stop="sendProduct(item)" class="btn ti warmHollow plr20">去咨询</view>
</view>
</view>
</view> </view>
</scroll-view>
</view> </view>
</template> </template>
<style lang="scss" scoped></style> <style scoped lang="scss"></style>

View File

@ -1,63 +1,62 @@
<script setup> <script setup>
// //
import uQRCode from '@/common/js/uqrcode.js' import uQRCode from '@/common/js/uqrcode.js'
import { import {
ref, ref,
reactive, reactive,
computed, computed,
} from 'vue' } from 'vue'
import { import {
useStore, useStore,
} from 'vuex' } from 'vuex'
import { import {
onLoad, onLoad,
} from '@dcloudio/uni-app' } from '@dcloudio/uni-app'
// vuex //
const store = useStore() import util from '@/common/js/util';
// // vuex
const userinfo = computed(() => { const store = useStore()
//
const userinfo = computed(() => {
let result = store.state.userinfo let result = store.state.userinfo
return result return result
}) })
// //
const qrcodeSize = ref(300) const qrcodeSize = ref(300)
// //
const qrUrl = ref('') const qrUrl = ref('')
onLoad(() => { onLoad(() => {
init() init()
}) })
// //
function init() { function init() {
uni.showLoading({ uni.showLoading({
title: '二维码生成中', title: '二维码生成中',
mask: true mask: true
}) })
// let url = `${util.config.host}/#/pages/news/addFriend?account=${userinfo.value.account}`
const content = { console.log(url);
key: 'user',
userId: userinfo.value.userId,
userNickname: userinfo.value.userNickname,
}
uQRCode.make({ uQRCode.make({
canvasId: 'qrcode', canvasId: 'qrcode',
text: JSON.stringify(content), text: url,
size: qrcodeSize.value, size: qrcodeSize.value,
margin: 10, margin: 10,
success: res => { success: res => {
qrUrl.value = res qrUrl.value = res
console.log('qrcodeSrc ', qrUrl.value); // console.log('qrcodeSrc ', qrUrl.value);
}, },
complete: () => { complete: () => {
uni.hideLoading() uni.hideLoading()
} }
}) })
} }
</script> </script>
<template> <template>
@ -65,13 +64,13 @@
<!-- --> <!-- -->
<view class="container ver mtb30 mlr30 tac"> <view class="container ver mtb30 mlr30 tac">
<!-- 二维码插件 width height设置宽高 --> <!-- 二维码插件 width height设置宽高 -->
<canvas canvas-id="qrcode" :style="{width: `${qrcodeSize}px`, height: `${qrcodeSize}px`}" /> <canvas canvas-id="qrcode" :style="{ width: `${qrcodeSize}px`, height: `${qrcodeSize}px` }" />
<view class="user mtb30 df aic"> <view class="user mtb30 df aic">
<view class="avatar"> <view class="avatar">
<image class="wh80 cir" :src="userinfo.userPortrait" mode="aspectFill" /> <image class="wh80 cir" :src="userinfo.userPortrait" mode="aspectFill" />
</view> </view>
<view class="nickname f1 ml20 c333 f32">{{userinfo.userNickname}}</view> <view class="nickname f1 ml20 c333 f32">{{ userinfo.userNickname }}</view>
</view> </view>
<view class="hint mtb30 tac c999">扫一扫添加我为好友</view> <view class="hint mtb30 tac c999">扫一扫添加我为好友</view>
@ -80,5 +79,4 @@
</template> </template>
<style lang="scss"> <style lang="scss">
// // </style>
</style>

View File

@ -5,6 +5,7 @@ import uni from '@dcloudio/vite-plugin-uni';
// let target = 'http://91f.xyz:8080' // let target = 'http://91f.xyz:8080'
let target = 'https://b433d23.r24.cpolar.top/' let target = 'https://b433d23.r24.cpolar.top/'
// let target = 'http://hvw2rn.natappfree.cc'
export default defineConfig({ export default defineConfig({

View File

@ -8,20 +8,21 @@ export default {
// //
const token = uni.getStorageSync('token') const token = uni.getStorageSync('token')
// //
const userinfo = uni.getStorageSync('userinfo') const userinfo = JSON.parse(uni.getStorageSync('userinfo'))
// //
if (token) { if (token) {
// //
if (userinfo) store.commit('setState', { if (userinfo) {
store.commit('setState', {
key: 'userinfo', key: 'userinfo',
value: userinfo value: userinfo
}) })
// // im
// util.getUserinfo().then(rs => { // IM
// util.loginTencent(userinfo) // util.loginTencent(userinfo)
// }) }
} else { } else {
// //
uni.redirectTo({ uni.redirectTo({

View File

@ -35,7 +35,8 @@ const login = {
userLoginOut(param) { userLoginOut(param) {
return util.request({ return util.request({
url: '/user/customerService/logout', url: '/user/customerService/logout',
data: param.data, method: 'POST',
query: param,
load: true, load: true,
}) })
}, },

View File

@ -2,7 +2,7 @@
const config = { const config = {
// 接口域名 // 接口域名
// #ifdef H5 // #ifdef H5
host: 'http://localhost:5173', host: 'http://localhost:8888',
// #endif // #endif
// #ifndef H5 // #ifndef H5
// host: 'http://91f.xyz:8080', // host: 'http://91f.xyz:8080',

View File

@ -1433,31 +1433,33 @@ const util = {
// 登录腾讯聊天 // 登录腾讯聊天
loginTencent(userinfo) { loginTencent(userinfo) {
api.login.getIMToken({}).then(rs => { api.login.getIMToken({}).then(rs => {
// console.log(rs);
const imSig = rs.msg const imSig = rs.msg
// #ifdef APP
// 音视频登录
const loginParams = {
SDKAppID: util.config.TChat.SDKAppID,
userID: userinfo.id + '',
userSig: imSig,
}
uni.$TUICallKit.login(loginParams, res => {
if (res.code === 0) {
console.log('[TUICallKit] login success.');
} else {
console.error('[TUICallKit] login failed, failed message = ', res.msg, params);
}
})
// #endif
uni.$chat.login({ uni.$chat.login({
userID: userinfo.id + '', userID: userinfo.serviceId + '',
userSig: imSig, userSig: imSig,
}).then(rs => { }).then(rs => {
console.log('im login success', rs) console.log('im login success', rs)
}) })
// // #ifdef APP
// // 音视频登录
// const loginParams = {
// SDKAppID: util.config.TChat.SDKAppID,
// userID: userinfo.id + '',
// userSig: imSig,
// }
// uni.$TUICallKit.login(loginParams, res => {
// if (res.code === 0) {
// console.log('[TUICallKit] login success.');
// } else {
// console.error('[TUICallKit] login failed, failed message = ', res.msg, params);
// }
// })
// // #endif
}) })
}, },
@ -1545,10 +1547,13 @@ const util = {
*/ */
logout(cb) { logout(cb) {
// 用户信息 // 用户信息
const userinfo = store.state.userinfo const userinfo = JSON.parse(uni.getStorageSync('userinfo'))
console.log(userinfo.serviceId);
// 用户id // 用户id
if (userinfo.id) { if (userinfo.serviceId) {
uni.$emit('logout') // 触发自定义事件监听 uni.$emit('logout') // 触发自定义事件监听
// tim登出 // tim登出
@ -1558,7 +1563,7 @@ const util = {
console.log('tim logout error:', rs); console.log('tim logout error:', rs);
}); });
api.login.userLoginOut().then(rs => { api.login.userLoginOut({ serviceId: userinfo.serviceId }).then(rs => {
setTimeout(() => { setTimeout(() => {
uni.navigateTo({ uni.navigateTo({
url: '/pages/login/login', url: '/pages/login/login',

View File

@ -17,31 +17,28 @@ import {
} from '@dcloudio/uni-app' } from '@dcloudio/uni-app'
// //
import util from '@/common/js/util.js' import util from '@/common/js/util.js'
//
import TencentCloudChat from '@tencentcloud/chat';
const chatList = reactive([{ const chatList = reactive([])
id: 1,
avatar: 'https://p3-flow-imagex-sign.byteimg.com/user-avatar/9f4488a87a17f6f31b9716331e14fe26~tplv-a9rns2rl98-icon-tiny.jpeg?rk3s=98c978ad&x-expires=1740537084&x-signature=OrjX8tZaafN4XJE2o8QzZDs3Q20%3D',
name: '客户 A',
lastMessage: '您好,商品什么时候发货?',
dot: 1,
},
{
id: 2,
avatar: 'https://p3-flow-imagex-sign.byteimg.com/user-avatar/9f4488a87a17f6f31b9716331e14fe26~tplv-a9rns2rl98-icon-tiny.jpeg?rk3s=98c978ad&x-expires=1740537084&x-signature=OrjX8tZaafN4XJE2o8QzZDs3Q20%3D',
name: '客户 B',
lastMessage: '这个商品有优惠吗?',
dot: '',
}
])
// //
const userinfo = JSON.parse(uni.getStorageSync('userinfo')) const userinfo = JSON.parse(uni.getStorageSync('userinfo'))
//
console.log(userinfo); const rightOption = [{
text: '删除',
style: {
backgroundColor: '#F85050'
},
fn: (item) => delMsg(item)
}, {
text: '设为已读',
style: {
backgroundColor: '#00ADEE'
},
fn: (item) => setRead(item)
},]
onMounted(() => { onMounted(() => {
getList() getList()
@ -74,7 +71,27 @@ function getList() {
} }
}).then(rs => { }).then(rs => {
if (rs.code == 200) { if (rs.code == 200) {
// list.data = handleList(rs.data); chatList.push(...rs.data.map(item => {
item.callbackData = JSON.parse(item.callbackJson)
if (item.callbackData.callback_json.length) {
let msgType = item.callbackData.callback_json[0].MsgType;
if (msgType == TencentCloudChat.TYPES.MSG_TEXT) {
item.chatText = item.callbackData.callback_json[0].MsgContent.Text
} else if (msgType == TencentCloudChat.TYPES.MSG_IMAGE) {
item.chatText = '[图片]'
} else if (msgType == TencentCloudChat.TYPES.MSG_AUDIO) {
item.chatText = '[语音]'
} else if (msgType == TencentCloudChat.TYPES.MSG_VIDEO) {
item.chatText = '[视频]'
} else if (msgType == TencentCloudChat.TYPES.MSG_CUSTOM) {
if (item.callbackData.callback_json[0].businessType == 'redPacket') {
item.chatText = `[红包] ${item.callbackData.blessing}`
}
}
}
return item
}))
return return
} }
util.alert({ util.alert({
@ -84,26 +101,23 @@ function getList() {
}) })
} }
// /**
// *
// * @param {Number} item
// */
// function handleChat(item) {
// //
// }
// /**
// *
/** // * @param {String} url
* 去聊天 // */
* @param {Number} item 聊天对象 // function link(url) {
*/ // uni.navigateTo({
function handleChat(item) { // url,
// // })
} // }
/**
* 跳转
* @param {String} url 路由地址
*/
function link(url) {
uni.navigateTo({
url,
})
}
// 退 // 退
@ -120,6 +134,78 @@ function handleLogout() {
}) })
}) })
} }
/**
* 去聊天
* @param {Object} item
*/
function handleChat(item) {
let param = {};
//
if (item.groupId == null) {
param.type = 'C2C'
param.name = `${item.callbackJson.from_name}`
param.msgId = `${item.callbackJson.from_id}`
} else {
//
param.type = 'GROUP'
param.name = `${item.groupChatDTO.name}`
param.msgId = `${item.groupId}`
param.num = `${item.groupChatDTO.memberCount}`
}
//
util.toChat(param)
}
/**
* 菜单
* @param {Object} ev 默认事件
* @param {Object} item 单项
*/
function handleMenu(ev, item) {
console.log('ev', ev, item)
ev.content.fn(item)
proxy.$refs.swipeAction.closeAll()
}
//
function delMsg(item) {
// sdk
let isReady = uni.$chat.isReady();
if (!isReady) {
setTimeout(function () {
delMsg(item);
}, 200);
return
}
let conversationId = item.groupId == null ? `C2C${item.fromId}` : `GROUP${item.groupId}`;
uni.$chat.deleteConversation(conversationId).then(rs => {
getList()
})
}
//
function setRead(item) {
// sdk
let isReady = uni.$chat.isReady();
if (!isReady) {
setTimeout(function () {
setRead(item);
}, 200);
return
}
let conversationId = item.groupId == null ? `C2C${item.fromId}` : `GROUP${item.groupId}`;
uni.$chat.setMessageRead({
conversationID: conversationId,
}).then(rs => {
getList()
})
}
</script> </script>
<template> <template>
@ -148,7 +234,7 @@ function handleLogout() {
<uni-icons type="right" /> <uni-icons type="right" />
</view> </view>
<view class="list"> <!-- <view class="list">
<view class="item rows ptb20 plr20" v-for="(item, index) in chatList" :key="index" <view class="item rows ptb20 plr20" v-for="(item, index) in chatList" :key="index"
@click="handleChat(item)"> @click="handleChat(item)">
<view class="avatar"> <view class="avatar">
@ -169,6 +255,47 @@ function handleLogout() {
</view> </view>
</view> </view>
</view> </view>
</view> -->
<view class="firendBox pr">
<scroll-view scroll-y="true" class="scroll">
<uni-swipe-action ref="swipeAction">
<view class="list pb30">
<uni-swipe-action-item :right-options="rightOption" v-for="(item, index) in chatList"
:key="index" @click="handleMenu($event, item)">
<view class="item rows ptb20 plr30" @click="handleChat(item)">
<view class="image wh90 pr">
<template v-if="item.groupId == null">
<image class="cir wh90" :src="item.callbackJson.from_url" mode="aspectFill" />
</template>
<template v-else>
<image class="cir wh90" :src="item.groupChatDTO.groupFaceUrl"
mode="aspectFill" />
</template>
<view class="mark pa t0 r0 cfff f22 cir" v-if="item.unreadCount">{{ item.unreadCount
}}
</view>
</view>
<view class="col f1 ml20">
<view class="rows">
<template v-if="item.groupId == null">
<view class="name f1 thd c333 f32">{{ item.callbackJson.from_name }}</view>
</template>
<template v-else>
<view class="name f1 thd c333 f32">{{ item.groupChatDTO.name }}</view>
</template>
<view class="datetime c999 f22">
{{ util.formatTime('MM-dd HH:mm', item.createTime) }}</view>
</view>
<view class="desc thd mt10 c666 f24">{{ item.chatText }}</view>
</view>
</view>
</uni-swipe-action-item>
<view class="mtb20 tac c999 f20">到底啦~</view>
</view>
</uni-swipe-action>
</scroll-view>
</view> </view>
</view> </view>
</template> </template>
@ -194,25 +321,56 @@ function handleLogout() {
} }
} }
// //
.list { .firendBox {
.item { height: 100%;
border-top: 1rpx solid #eee;
.scroll {
height: 100%;
}
//
.list {
//
.mark,
.dot {
background-color: #FF6B17;
text-align: center;
line-height: 30rpx;
}
.mark {
width: 30rpx;
height: 30rpx;
}
.dot { .dot {
padding: 5rpx;
border-radius: 100rpx;
background-color: #f00;
//
.content {
display: flex;
justify-content: center;
align-items: center;
width: 20rpx; width: 20rpx;
height: 20rpx; height: 20rpx;
} }
} }
}
} }
</style>
// //
// .list {
// .item {
// border-top: 1rpx solid #eee;
// .dot {
// padding: 5rpx;
// border-radius: 100rpx;
// background-color: #f00;
// //
// .content {
// display: flex;
// justify-content: center;
// align-items: center;
// width: 20rpx;
// height: 20rpx;
// }
// }
// }
// }</style>

View File

@ -10,7 +10,7 @@ export default defineConfig({
plugins: [uni()], plugins: [uni()],
server: { server: {
host: "0.0.0.0", host: "0.0.0.0",
port: 5173, port: 8888,
proxy: { proxy: {
"/system": { "/system": {
target, target,