pull/2/head
张宇 2 years ago
parent 5fa180ef35
commit 1e0c371420

@ -0,0 +1,43 @@
import {
request
} from "@/utils/request";
export default {
userList(data) {
return request({
url: "/admin/user/userList",
method: "GET",
data,
})
},
userItem(data) {
return request({
url: "/admin/user/userItem",
method: "GET",
data,
})
},
getLog(data) {
return request({
url: "/admin/user/getLog",
method: "GET",
data,
})
},
changeInformation(data) {
return request({
url: "/admin/user/changeInformation",
method: "GET",
data,
})
},
};

@ -5,8 +5,8 @@
<scroll-view scroll-y="true" class="scroll-Y" :style="{ height: props.height }" @scrolltolower="lower"> <scroll-view scroll-y="true" class="scroll-Y" :style="{ height: props.height }" @scrolltolower="lower">
<slot :list="list"></slot> <slot :list="list"></slot>
<view v-if="list.length == 0"> <view v-show="firstLoading" v-if="list.length == 0">
<wd-status-tip image="search" tip="当前查询无结果" /> <wd-status-tip image="search" tip="暂无数据 ~" />
</view> </view>
</scroll-view> </scroll-view>
</view> </view>
@ -68,6 +68,9 @@ const query = ref({
/** @type {Ref<boolean>} */ /** @type {Ref<boolean>} */
const loading = ref(false); const loading = ref(false);
/** @type {Ref<boolean>} */
const firstLoading = ref(false);
const total = ref(0) const total = ref(0)
const list = ref([]) const list = ref([])
@ -92,6 +95,7 @@ const getData = async () => {
} }
loading.value = false; loading.value = false;
firstLoading.value = true;
}; };
getData(); getData();

@ -124,6 +124,30 @@
"gestureBack": "YES" "gestureBack": "YES"
} }
} }
},
{
"path": "user/list",
"style": {
"navigationBarTitleText": "用户列表",
"enablePullDownRefresh": false,
"mp-alipay": {
"transparentTitle": "always",
"titlePenetrate": "YES",
"gestureBack": "YES"
}
}
},
{
"path": "user/edit",
"style": {
"navigationBarTitleText": "用户信息",
"enablePullDownRefresh": false,
"mp-alipay": {
"transparentTitle": "always",
"titlePenetrate": "YES",
"gestureBack": "YES"
}
}
} }
] ]
} }

@ -1,8 +1,9 @@
<template> <template>
<view class="myTabbar"> <view class="myTabbar">
<wd-tabbar v-model="tab" shape="round"> <wd-tabbar custom-class="mb-3" fixed safeAreaInsetBottom placeholder v-model="tab" shape="round">
<wd-tabbar-item @click="utils.toUrl('/store/index/index')" name="home" title="首页" icon="home"></wd-tabbar-item> <wd-tabbar-item @click="utils.toUrl('/store/index/index')" name="home" title="首页" icon="home"></wd-tabbar-item>
<!-- <wd-tabbar-item name="cart" title="分类" icon="cart"></wd-tabbar-item> --> <!-- <wd-tabbar-item name="cart" title="分类" icon="cart"></wd-tabbar-item> -->
<wd-tabbar-item name="user" @click="utils.toUrl('/store/user/list')" title="用户管理" icon="user"></wd-tabbar-item>
<wd-tabbar-item @click="utils.toUrl('/store/shop/list')" name="shop" title="门店管理" icon="detection"></wd-tabbar-item> <wd-tabbar-item @click="utils.toUrl('/store/shop/list')" name="shop" title="门店管理" icon="detection"></wd-tabbar-item>
<!-- <wd-tabbar-item name="user" title="我的" icon="user"></wd-tabbar-item> --> <!-- <wd-tabbar-item name="user" title="我的" icon="user"></wd-tabbar-item> -->
</wd-tabbar> </wd-tabbar>

@ -44,9 +44,7 @@
</wd-popover> </wd-popover>
</template> </template>
</wd-search> </wd-search>
<!-- <wd-drop-menu>
<wd-drop-menu-item v-model="shipmentsModel.delivery_company" :options="expressList" />
</wd-drop-menu> -->
<wd-tabs @change="(e) => { <wd-tabs @change="(e) => {
params.status = e.index; params.status = e.index;
search({ value: params.keywords }) search({ value: params.keywords })
@ -70,7 +68,7 @@
<span class="font-bold">({{ status[item.status + 1].content }})</span> <span class="font-bold">({{ status[item.status + 1].content }})</span>
</view> </view>
<view class="title-tip"> <view @click="utils.copy(item.order_no, '已复制单号')" class="title-tip">
<span style="font-size: 24rpx;margin-left: 8px;">单号{{ item.order_no }}</span> <span style="font-size: 24rpx;margin-left: 8px;">单号{{ item.order_no }}</span>
</view> </view>
</view> </view>
@ -97,9 +95,17 @@
( 会员ID{{ item.user.id }} ) ( 会员ID{{ item.user.id }} )
</text> </text>
<view class="bg-gray-100 my-2 p-2"> <view class="bg-gray-100 my-2 p-2 relative">
<view>收货人{{ item.receiver_name }} &nbsp; 电话{{ item.receiver_phone }}</view> <view>收货人{{ item.receiver_name }} &nbsp; 电话{{ item.receiver_phone }}</view>
<view>收货地址{{ item.delivery_address }} {{ item.delivery_address_detail }}</view> <view v-if="item.delivery_address">{{ item.delivery_address }} {{
item.delivery_address_detail }}</view>
<view
@click="utils.copy(`收货人:${item.receiver_name} 电话:${item.receiver_phone} 收货地址:${item.delivery_address}`, '已复制快递信息')"
class="absolute right-2 top-2">
<wd-icon name="file-copy" size="14px"></wd-icon>
</view>
</view> </view>
</view> </view>
@ -158,6 +164,7 @@
</template> </template>
<script setup> <script setup>
import utils from '@/utils/utils.js';
import order from '@/api/store/order.js'; import order from '@/api/store/order.js';
import myList from "/components/myList/index.vue"; import myList from "/components/myList/index.vue";
import { useMessage } from '@/uni_modules/wot-design-uni'; import { useMessage } from '@/uni_modules/wot-design-uni';

@ -31,9 +31,7 @@
<template #footer> <template #footer>
<view class="flex"> <view class="flex">
<wd-button style="margin-right: auto;margin-left: 0;" @click="syncGoods(shop)" size="small">同步商品</wd-button> <wd-button style="margin-right: auto;margin-left: 0;" @click="syncGoods(shop)" size="small">同步商品</wd-button>
<view> <view>
<wd-button @click="changeS(shop)" v-if="shop.status == 1" size="small" plain <wd-button @click="changeS(shop)" v-if="shop.status == 1" size="small" plain
style="margin-right: 8px;">关闭</wd-button> style="margin-right: 8px;">关闭</wd-button>

@ -0,0 +1,281 @@
<template>
<view class="content bg-gray-50">
<kevyloading v-if="loading" type="bsm-loader" color="#618af8" transparent></kevyloading>
<view class="grid">
<wd-card class="rounded-md overflow-hidden" type="rectangle">
<template #title>
<view class="title">
<view>ID{{ userInfo.id }}</view>
<view @click="utils.copy(userInfo.user_merge.mobile)" class="title-tip" v-if="userInfo.user_merge">
{{ userInfo.user_merge.mobile }}
<wd-icon name="file-copy" size="14px"></wd-icon>
</view>
</view>
</template>
<view style="height: 40px;" class="userInfoBox">
<image mode="aspectFill" :src="userInfo.avatar_pic" :alt="userInfo.name"
style="width: 60px;height: 60px;border-radius: 4px; margin-right: 12px;" />
<view>
<view style="color: rgba(0,0,0,0.85); font-size: 16px;">{{ userInfo.nickname }}
</view>
<view style="color: rgba(0,0,0,0.25); font-size: 12px;">
<wd-tag class="mx-1" size="small" :type="originType[userInfo.origin]">
{{ userInfo.origin_text }}
</wd-tag>
</view>
</view>
</view>
<template #footer>
<view v-if="userInfo.user_merge" class="bg-gray-50 p-2 mb-2.5 flex justify-between" style="font-size: 22rpx;">
<view>余额{{ userInfo.user_merge.balance }} </view>
<view>积分{{ userInfo.user_merge.integral }} </view>
<view>佣金{{ userInfo.user_merge.money }} </view>
</view>
<view v-if="userInfo.user_merge" class="flex justify-between items-center">
<view></view>
<view>
<wd-button @click="showActions({ typeAc: 1 })" size="small" style="margin-right: 8px;">编辑余额</wd-button>
<wd-button @click="showActions({ typeAc: 2 })" size="small" style="margin-right: 0px;">编辑积分</wd-button>
</view>
</view>
</template>
</wd-card>
</view>
<view v-if="!loading">
<wd-tabs v-model="tab">
<block v-for="item in 1" :key="item + '余额记录'">
<wd-tab title="余额记录">
<myList height="64vh" v-if="userInfo.id" ref="myListRef" :apiObj="user.getLog"
:params="{ model: 'balance', id: userInfo.id }">
<template #default="{ list }">
<div class="pt-3 bg-gray-50">
<view v-for="item of list" class="bg-gray-50">
<wd-card :title='(item.type == 1 ? "余额增加 + " : "余额减少 - ") + item.change'>
<view class="bg-gray-50 p-2 mb-2.5 flex flex-col justify-between" style="font-size: 22rpx;">
<view class="mb-1">变动时间{{ item.create_time }} </view>
<view class="mb-1">变动前{{ item.before }} </view>
<view class="mb-1">变动后<span>{{ item.after }}</span> </view>
<view class="mb-1">描述{{ item.desc }} </view>
</view>
<template #footer>
<view>
ID{{ item.id }}
</view>
</template>
</wd-card>
</view>
</div>
</template>
</myList>
</wd-tab>
</block>
<block v-for="item in 1" :key="item + '积分记录'">
<wd-tab title="积分记录">
<myList height="64vh" v-if="userInfo.id" ref="myListRef" :apiObj="user.getLog"
:params="{ model: 'integral', id: userInfo.id }">
<template #default="{ list }">
<div class="pt-3 bg-gray-50">
<view v-for="item of list" class="bg-gray-50">
<wd-card :title='(item.type == 1 ? "积分增加 + " : "积分减少 - ") + item.change'>
<view class="bg-gray-50 p-2 mb-2.5 flex flex-col justify-between" style="font-size: 22rpx;">
<view class="mb-1">变动时间{{ item.create_time }} </view>
<view class="mb-1">变动前{{ item.before }} </view>
<view class="mb-1">变动后<span>{{ item.after }}</span> </view>
<view class="mb-1">描述{{ item.desc }} </view>
</view>
<template #footer>
<view>
ID{{ item.id }}
</view>
</template>
</wd-card>
</view>
</div>
</template>
</myList>
</wd-tab>
</block>
</wd-tabs>
</view>
<wd-toast />
<wd-action-sheet v-model="showAc" :actions="actions" @select="select" />
<wd-message-box></wd-message-box>
</view>
</template>
<script setup>
import { ref } from 'vue';
import utils from '@/utils/utils.js';
import user from '@/api/store/user.js';
import myList from "/components/myList/index.vue";
import kevyloading from "@/components/kevy-loading/kevy-loading";
import { useMessage } from '@/uni_modules/wot-design-uni'
const message = useMessage()
import {
onShow, onLoad
} from "@dcloudio/uni-app";
const tab = ref(0)
const model = ref({})
const baseForm = ref({})
const showAc = ref(false)
const typeAc = ref(1)
const userInfo = ref({});
const actions = [
{
name: '增加'
},
{
name: '减少'
}
]
function showActions(e) {
showAc.value = true
typeAc.value = e.typeAc
}
function close() {
showAc.value = false
}
function select({ item, index }) {
let textAc = ''
if (typeAc.value == 1) {
if (item.name == "增加") {
textAc = "增加余额"
} else {
textAc = "减少余额"
}
}
if (typeAc.value == 2) {
if (item.name == "增加") {
textAc = "增加积分"
} else {
textAc = "减少积分"
}
}
message
.prompt({
title: textAc,
})
.then((resp) => {
let model = ''
if (typeAc.value == 1) {
model = 'balance'
}
if (typeAc.value == 2) {
model = 'integral'
}
let type = ''
if (item.name == "增加") {
type = 1
} else {
type = 2
}
loading.value = true
user.changeInformation({
id: userInfo.value.id,
value: resp.value,
type, model
}).then(res => {
loading.value = false
})
})
.catch((error) => {
})
}
const originType = ref({
100: 'success',
101: 'success',
200: 'info',
201: 'danger',
300: 'warning',
})
/**
* @type {Ref<boolean>}
* 控制页面加载状态的 Ref
*/
const loading = ref(false);
//
onShow(() => {
// getuserInfoList();
})
onLoad(async (e) => {
loading.value = true
const res = await user.userItem({
id: e.id
});
userInfo.value = res.data
loading.value = false
})
</script>
<style lang="scss" scoped>
.userInfoBox,
.title {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
.userInfoBox {
justify-content: flex-start;
}
.title {
justify-content: space-between;
}
.title-tip {
color: rgba(0, 0, 0, 0.25);
font-size: 12px;
}
</style>

@ -0,0 +1,289 @@
<template>
<view class="content">
<kevyloading v-if="loading" type="bsm-loader" color="#618af8" transparent></kevyloading>
<!-- <view class="w-full">
<wd-navbar fixed safeAreaInsetTop :leftText="user_info?.info?.name || '商城首页'">
<template #right>
<wd-icon @click="utils.toUrl('/store/setup/index')" name="setting" size="22px"></wd-icon>
</template>
</wd-navbar>
</view> -->
<view class=" bg-white sticky top-0 z-50">
<wd-search @search="search({ value: params.keywords })" @clear="search({ value: params.keywords = '' })"
v-model="params.keywords" hide-cancel>
<template #prefix>
<wd-popover v-model="popover" mode="menu" :content="menu" @menuclick="changeSearchType">
<view class="search-type">
<text>{{ searchType }}</text>
<wd-icon custom-class="icon-arrow" name="fill-arrow-down"></wd-icon>
</view>
</wd-popover>
</template>
</wd-search>
</view>
<div class="grid p-2">
<myList height="90vh" ref="myListRef" :apiObj="user.userList" :params="{ ...params }">
<template #default="{ list: userList }">
<div v-for="user of userList" class="rounded-md overflow-hidden">
<wd-card class="rounded-md overflow-hidden" type="rectangle">
<template #title>
<view class="title">
<view>ID{{ user.id }}</view>
<view @click="utils.copy(user.user_merge.mobile)" class="title-tip" v-if="user.user_merge">
{{ user.user_merge.mobile }}
<wd-icon name="file-copy" size="14px"></wd-icon>
</view>
</view>
</template>
<view style="height: 40px;" class="userBox">
<image mode="aspectFill" :src="user.avatar_pic" :alt="user.name"
style="width: 60px;height: 60px;border-radius: 4px; margin-right: 12px;" />
<view>
<view style="color: rgba(0,0,0,0.85); font-size: 16px;">{{ user.nickname }}
</view>
<view style="color: rgba(0,0,0,0.25); font-size: 12px;">
<wd-tag class="mx-1" size="small" :type="originType[user.origin]">
{{ user.origin_text }}
</wd-tag>
</view>
</view>
</view>
<template #footer>
<view v-if="user.user_merge" class="bg-gray-50 p-2 mb-2.5 flex justify-between" style="font-size: 22rpx;">
<view>余额{{ user.user_merge.balance }} </view>
<view>积分{{ user.user_merge.integral }} </view>
<view>佣金{{ user.user_merge.money }} </view>
</view>
<view class="flex justify-between items-center">
<view></view>
<view>
<!-- <wd-button @click="changeS(user)" v-if="user.status == 1" size="small" plain
style="margin-right: 8px;">关闭</wd-button>
<wd-button @click="changeS(user)" v-if="user.status !== 1" size="small" plain
style="margin-right: 8px;">
开启</wd-button> -->
<wd-button @click="utils.toUrl('/store/user/edit?id=' + user.id)" size="small"
style="margin-right: 0px;">详情</wd-button>
</view>
</view>
</template>
</wd-card>
</div>
</template>
</myList>
</div>
<view class="h-[64px]"></view>
<view class="fixed left-2 right-2 bottom-4 z-50">
<myTabbar tab="user"></myTabbar>
</view>
<wd-toast />
<wd-message-box></wd-message-box>
</view>
</template>
<script setup>
import { ref } from 'vue';
import utils from '@/utils/utils.js';
import user from '@/api/store/user.js';
import myTabbar from "../components/myTabbar/index.vue";
import kevyloading from "@/components/kevy-loading/kevy-loading";
import { useMessage } from '@/uni_modules/wot-design-uni';
import { useToast } from '@/uni_modules/wot-design-uni'
import myList from "/components/myList/index.vue";
import {
onShow,
} from "@dcloudio/uni-app";
const toast = useToast()
const message1 = useMessage();
const originType = ref({
100: 'success',
101: 'success',
200: 'info',
201: 'danger',
300: 'warning',
})
const myListRef = ref(null);
const searchType = ref('昵称');
const popover = ref(false);
const search = ({ value }) => {
if (searchType.value == '昵称') {
myListRef.value.upData({
nickname: params.value.keywords,
mobile: ''
});
}
if (searchType.value == '手机号') {
myListRef.value.upData({
nickname: '',
mobile: params.value.keywords
});
}
};
const menu = ref([
{ content: '昵称' },
{ content: '手机号' },
]);
const params = ref({
nickname: "",
mobile: "",
origin: '',
value: ''
});
/**
* 切换搜索类型
* @param {Object} item - 切换的项
*/
function changeSearchType({ item, index }) {
searchType.value = item.content;
search(params.value.keywords)
}
/**
* @type {Ref<boolean>}
* 控制页面加载状态的 Ref
*/
const loading = ref(false);
/**
* 从本地存储中获取用户信息
*/
const user_info = uni.getStorageSync("user_info");
const userList = ref({});
const changeS = (row) => {
user.editStatus({
id: row.id,
status: [1, 0][row.status],
}).then(res => {
if (res.code == 0) {
toast.success('操作成功')
row.status = [1, 0][row.status]
} else {
showNotify({ type: 'error', message: '出错了' })
}
})
}
const syncGoods = (row) => {
message1
.confirm({
title: '同步商品',
})
.then((resp) => {
toast.loading('请稍后...')
user.synchronousGoods({
id: row.id,
}).then(res => {
if (res.code == 0) {
toast.success('同步成功');
} else {
toast.error('同步失败');
}
});
})
.catch((error) => {
console.log(error);
});
};
/**
* 获取数据的函数
*/
// const getuserList = () => {
// loading.value = true
// user.list().then(res => {
// userList.value = res.data;
// userList.value.ok = true;
// loading.value = false
// });
// };
//
onShow(() => {
// getuserList();
})
</script>
<style lang="scss" scoped>
.search-type {
position: relative;
height: 30px;
line-height: 30px;
padding: 0 8px 0 16px;
font-size: 24rpx;
color: rgba(0, 0, 0, .45);
}
.search-type::after {
position: absolute;
content: '';
width: 1px;
right: 0;
top: 5px;
bottom: 5px;
background: rgba(0, 0, 0, 0.25);
}
.search-type {
:deep(.icon-arrow) {
display: inline-block;
font-size: 20px;
vertical-align: middle;
}
}
.userBox,
.title {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
.userBox {
justify-content: flex-start;
}
.title {
justify-content: space-between;
}
.title-tip {
color: rgba(0, 0, 0, 0.25);
font-size: 12px;
}
</style>

@ -25,7 +25,7 @@ export function request(options) {
url: options.url, url: options.url,
timeout: env.NETWORK_TIME_OUT, timeout: env.NETWORK_TIME_OUT,
// data: { ...options.data, store_id: env.store_id, mini_id: env.mini_id, origin: getOrigin() }, // data: { ...options.data, store_id: env.store_id, mini_id: env.mini_id, origin: getOrigin() },
data: { ...options.data, ...env, origin: getOrigin() }, data: { ...options.data, ...env, },
header: options.header, header: options.header,
method: options.method, method: options.method,
success: (res) => { success: (res) => {
@ -46,20 +46,19 @@ export function request(options) {
default: default:
console.log("请求失败(" + statusCode + ")") console.log("请求失败(" + statusCode + ")")
reject(res) reject(res)
uni.$u.toast(res?.data?.message || "出错了"); uni.showToast({
title: `请求服务器无响应!`,
icon: 'none'
})
break; break;
} }
}, },
fail: (res) => { fail: (res) => {
console.log(res, 'reslogin') uni.showToast({
// #ifdef MP-ALIPAY title: `请求服务器无响应!`,
if (res.statusCode == 401) { icon: 'none'
setTimeout(() => { })
utils.loginOut();
}, 300)
}
// #endif
reject(res.data.data); reject(res.data.data);
}, },
}); });

@ -57,7 +57,10 @@ export default {
uni.setClipboardData({ uni.setClipboardData({
data, data,
success: () => { success: () => {
uni.$u.toast(toast); uni.showToast({
title: toast,
icon: 'none'
})
}, },
}); });
}, },

Loading…
Cancel
Save