Merge branch 'v4.7.0dev' of https://gitee.com/ZhongBangKeJi/CRMEB into v4.7.0dev

This commit is contained in:
吴昊天 2023-03-04 10:18:02 +08:00
commit dcf1ede517
22 changed files with 903 additions and 543 deletions

View File

@ -0,0 +1,280 @@
<?php
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
namespace app\services\system;
use app\dao\system\SystemMenusDao;
use app\services\BaseServices;
use app\services\system\admin\SystemRoleServices;
use crmeb\exceptions\AdminException;
use crmeb\services\FormBuilder as Form;
use crmeb\utils\Arr;
/**
* 权限菜单
* Class SystemMenusServices
* @package app\services\system
* @method save(array $data) 保存数据
* @method get(int $id, ?array $field = []) 获取数据
* @method update($id, array $data, ?string $key = null) 修改数据
* @method getSearchList() 主页搜索
* @method getColumn(array $where, string $field, ?string $key = '') 主页搜索
* @method getVisitName(string $rule) 根据访问地址获得菜单名
*/
class SystemLangServices extends BaseServices
{
/**
* 初始化
* SystemMenusServices constructor.
* @param SystemMenusDao $dao
*/
public function __construct(SystemMenusDao $dao)
{
$this->dao = $dao;
}
/**
* 获取菜单没有被修改器修改的数据
* @param $menusList
* @return array
*/
public function getMenusData($menusList)
{
$data = [];
foreach ($menusList as $item) {
$data[] = $item->getData();
}
return $data;
}
/**
* 获取后台权限菜单和权限
* @param $rouleId
* @param int $level
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getMenusList($rouleId, int $level)
{
/** @var SystemRoleServices $systemRoleServices */
$systemRoleServices = app()->make(SystemRoleServices::class);
$rules = $systemRoleServices->getRoleArray(['status' => 1, 'id' => $rouleId], 'rules');
$rulesStr = Arr::unique($rules);
$menusList = $this->dao->getMenusRoule(['route' => $level ? $rulesStr : '']);
$unique = $this->dao->getMenusUnique(['unique' => $level ? $rulesStr : '']);
return [Arr::getMenuIviewList($this->getMenusData($menusList)), $unique];
}
/**
* 获取后台菜单树型结构列表
* @param array $where
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getList(array $where)
{
$menusList = $this->dao->getMenusList($where);
$menusList = $this->getMenusData($menusList);
return get_tree_children($menusList);
}
/**
* 获取form表单所需要的所要的菜单列表
* @return array[]
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
protected function getFormSelectMenus()
{
$menuList = $this->dao->getMenusRoule(['is_del' => 0], ['id', 'pid', 'menu_name']);
$list = sort_list_tier($this->getMenusData($menuList), '0', 'pid', 'id');
$menus = [['value' => 0, 'label' => '顶级按钮']];
foreach ($list as $menu) {
$menus[] = ['value' => $menu['id'], 'label' => $menu['html'] . $menu['menu_name']];
}
return $menus;
}
/**
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
protected function getFormCascaderMenus(int $value = 0)
{
$menuList = $this->dao->getMenusRoule(['is_del' => 0], ['id as value', 'pid', 'menu_name as label']);
$menuList = $this->getMenusData($menuList);
if ($value) {
$data = get_tree_value($menuList, $value);
} else {
$data = [];
}
return [get_tree_children($menuList, 'children', 'value'), array_reverse($data)];
}
/**
* 创建权限规格生表单
* @param array $formData
* @return mixed
* @throws \FormBuilder\Exception\FormBuilderException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function createMenusForm(array $formData = [])
{
$field[] = Form::input('menu_name', '按钮名称', $formData['menu_name'] ?? '')->required('按钮名称必填');
// $field[] = Form::select('pid', '父级id', $formData['pid'] ?? 0)->setOptions($this->getFormSelectMenus())->filterable(1);
$field[] = Form::input('menu_path', '路由名称', $formData['menu_path'] ?? '')->placeholder('请输入前台跳转路由地址')->required('请填写前台路由地址');
$field[] = Form::input('unique_auth', '权限标识', $formData['unique_auth'] ?? '')->placeholder('不填写则后台自动生成');
$params = $formData['params'] ?? '';
// $field[] = Form::input('params', '参数', is_array($params) ? '' : $params)->placeholder('举例:a/123/b/234');
$field[] = Form::frameInput('icon', '图标', $this->url('admin/widget.widgets/icon', ['fodder' => 'icon']), $formData['icon'] ?? '')->icon('md-add')->height('505px')->modal(['footer-hide' => true]);
$field[] = Form::number('sort', '排序', (int)($formData['sort'] ?? 0))->precision(0);
$field[] = Form::radio('auth_type', '类型', $formData['auth_type'] ?? 1)->options([['value' => 2, 'label' => '接口'], ['value' => 1, 'label' => '菜单(包含页面按钮)']]);
$field[] = Form::radio('is_show', '状态', $formData['is_show'] ?? 1)->options([['value' => 0, 'label' => '关闭'], ['value' => 1, 'label' => '开启']]);
$field[] = Form::radio('is_show_path', '是否为前端隐藏菜单', $formData['is_show_path'] ?? 0)->options([['value' => 1, 'label' => '是'], ['value' => 0, 'label' => '否']]);
[$menuList, $data] = $this->getFormCascaderMenus((int)($formData['pid'] ?? 0));
$field[] = Form::cascader('menu_list', '父级id', $data)->data($menuList)->filterable(true);
return $field;
}
/**
* 新增权限表单
* @return array
* @throws \FormBuilder\Exception\FormBuilderException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function createMenus()
{
return create_form('添加权限', $this->createMenusForm(), $this->url('/setting/save'));
}
/**
* 修改权限菜单
* @param int $id
* @return array
* @throws \FormBuilder\Exception\FormBuilderException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function updateMenus(int $id)
{
$menusInfo = $this->dao->get($id);
if (!$menusInfo) {
throw new AdminException(100026);
}
return create_form('修改权限', $this->createMenusForm($menusInfo->getData()), $this->url('/setting/update/' . $id), 'PUT');
}
/**
* 获取一条数据
* @param int $id
* @return mixed
*/
public function find(int $id)
{
$menusInfo = $this->dao->get($id);
if (!$menusInfo) {
throw new AdminException(100026);
}
$menu = $menusInfo->getData();
$menu['pid'] = (int)$menu['pid'];
$menu['auth_type'] = (int)$menu['auth_type'];
$menu['is_header'] = (int)$menu['is_header'];
$menu['is_show'] = (int)$menu['is_show'];
$menu['is_show_path'] = (int)$menu['is_show_path'];
if (!$menu['path']) {
[$menuList, $data] = $this->getFormCascaderMenus($menu['pid']);
$menu['path'] = $data;
} else {
$menu['path'] = explode('/', $menu['path']);
if (is_array($menu['path'])) {
$menu['path'] = array_map(function ($item) {
return (int)$item;
}, $menu['path']);
}
}
return $menu;
}
/**
* 删除菜单
* @param int $id
* @return mixed
*/
public function delete(int $id)
{
if ($this->dao->count(['pid' => $id])) {
throw new AdminException(400613);
}
return $this->dao->delete($id);
}
/**
* 获取添加身份规格
* @param $roles
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getMenus($roles): array
{
$field = ['menu_name', 'pid', 'id'];
$where = ['is_del' => 0];
if (!$roles) {
$menus = $this->dao->getMenusRoule($where, $field);
} else {
/** @var SystemRoleServices $service */
$service = app()->make(SystemRoleServices::class);
$roles = is_string($roles) ? explode(',', $roles) : $roles;
$ids = $service->getRoleIds($roles);
$menus = $this->dao->getMenusRoule(['rule' => $ids] + $where, $field);
}
return $this->tidyMenuTier(false, $menus);
}
/**
* 组合菜单数据
* @param bool $adminFilter
* @param $menusList
* @param int $pid
* @param array $navList
* @return array
*/
public function tidyMenuTier(bool $adminFilter = false, $menusList, int $pid = 0, array $navList = []): array
{
foreach ($menusList as $k => $menu) {
$menu = $menu->getData();
$menu['title'] = $menu['menu_name'];
unset($menu['menu_name']);
if ($menu['pid'] == $pid) {
unset($menusList[$k]);
$menu['children'] = $this->tidyMenuTier($adminFilter, $menusList, $menu['id']);
if ($pid == 0 && !count($menu['children'])) continue;
if ($menu['children']) $menu['expand'] = true;
$navList[] = $menu;
}
}
return $navList;
}
}

View File

@ -57,8 +57,16 @@ class LangCountryServices extends BaseServices
{
if ($id) $info = $this->dao->get($id);
$field = [];
$field[] = Form::input('name', '所属地区', $info['name'] ?? '')->required('请填写所属地区');
$field[] = Form::input('code', '语言码', $info['code'] ?? '')->required('请填写语言码');
$field[] = Form::input('name', '所属地区', $info['name'] ?? '')->required('请填写所属地区')->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => '例如:中国、香港、德国']
]);
$field[] = Form::input('code', '语言识别码', $info['code'] ?? '')->required('请填写浏览器语言识别码')->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => '浏览器语言识别码']
]);
/** @var LangTypeServices $langTypeServices */
$langTypeServices = app()->make(LangTypeServices::class);
$list = $langTypeServices->getColumn(['is_del' => 0, 'status' => 1], 'language_name,file_name,id', 'id');
@ -69,7 +77,11 @@ class LangCountryServices extends BaseServices
}
return $menus;
};
$field[] = Form::select('type_id', '语言类型', $info['type_id'] ?? 0)->setOptions(Form::setOptions($setOption))->filterable(true);
$field[] = Form::select('type_id', '关联语言', $info['type_id'] ?? 0)->setOptions(Form::setOptions($setOption))->filterable(true)->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => '请选择关联语言,语言类型是由您自行添加的']
]);
return create_form($id ? '修改语言地区' : '新增语言地区', $field, Url::buildUrl('/setting/lang_country/save/' . $id), 'POST');
}
@ -103,4 +115,4 @@ class LangCountryServices extends BaseServices
$this->cacheDriver()->clear();
return true;
}
}
}

View File

@ -46,7 +46,11 @@ class LangTypeServices extends BaseServices
if ($id) $info = $this->dao->get($id);
$field = [];
$field[] = Form::input('language_name', '语言名称', $info['language_name'] ?? '')->required('请填写语言名称');
$field[] = Form::input('file_name', '语言标识', $info['file_name'] ?? '')->required('请填写语言标识');
$field[] = Form::input('file_name', '语言标识', $info['file_name'] ?? '')->required('请填写语言标识')->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => '请选择或输入浏览器标识']
]);
$field[] = Form::radio('is_default', '是否默认', $info['is_default'] ?? 0)->options([['label' => '开启', 'value' => 1], ['label' => '关闭', 'value' => 0]]);
$field[] = Form::radio('status', '状态', $info['status'] ?? 1)->options([['label' => '开启', 'value' => 1], ['label' => '关闭', 'value' => 0]]);
return create_form($id ? '修改语言类型' : '新增语言类型', $field, Url::buildUrl('/setting/lang_type/save/' . $id), 'POST');
@ -128,4 +132,4 @@ class LangTypeServices extends BaseServices
$this->setDefaultLangName();
return true;
}
}
}

View File

@ -1,7 +1,12 @@
<template>
<div class="custom-bread-crumb">
<Breadcrumb :style="{ fontSize: `${fontSize}px` }">
<BreadcrumbItem v-for="(item,index) in list" :key="`${item.path}`" :to="index !== 1 ? item.path : ''" v-if="listLast[0].path !== homePath">
<BreadcrumbItem
v-for="(item, index) in list"
:key="`${item.path}`"
:to="index !== 1 ? item.path : ''"
v-if="listLast[0].path !== homePath"
>
<common-icon style="margin-right: 4px" :type="item.icon || ''" />
{{ item.title }}
</BreadcrumbItem>
@ -65,6 +70,7 @@ export default {
</script>
<style lang="less">
.ivu-breadcrumb-item-link {
font-weight: 400;
.ivu-icon {
line-height: 14px;
}

View File

@ -43,6 +43,7 @@
import mixin from './mixin';
import itemMixin from './item-mixin';
import { findNodeUpperByClasses } from '@/libs/util';
import settings from '@/setting';
export default {
name: 'CollapsedMenu',
@ -72,7 +73,12 @@ export default {
this.$emit('on-click', name, this.activeMenuPath);
},
handClick(name) {
console.log(name, this.activeMenuPath);
this.$emit('on-click', name, this.activeMenuPath);
// if (name == settings.routePre + '/home/') {
// this.$emit('on-click', name, this.activeMenuPath);
// }
},
handleMousemove(event, children) {
const { pageY } = event;
@ -91,7 +97,7 @@ export default {
@import './side-menu.less';
/deep/ .collased-menu-dropdown {
width: 100%;
width: @side-width;
}
.child-menu {
@ -108,7 +114,6 @@ export default {
font-size: 14px;
line-height: 14px;
padding: 14px 20px;
}
.ivu-dropdown-menu /deep/ .ivu-dropdown-item {
width: 140px !important;

View File

@ -1,7 +1,7 @@
<template>
<div class="side-menu-wrapper">
<!-- <sider-trigger :collapsed="collapsed" @on-change="handleCollpasedChange"></sider-trigger> -->
<div class="side-menu-box" v-show="!collapsed">
<div class="side-menu-box" v-if="!collapsed">
<div class="parent-menu">
<slot></slot>
<Menu
@ -23,7 +23,7 @@
</template>
</Menu>
</div>
<div class="child-menu" v-show="sider.length">
<div class="child-menu" v-if="sider.length">
<div class="cat-name">{{ oneMenuName }}</div>
<Menu
ref="childMenu"
@ -63,7 +63,7 @@
</div>
</div>
<div class="menu-collapsed" v-show="collapsed">
<div class="menu-collapsed" v-if="collapsed">
<slot></slot>
<template v-for="item in menusName">
<collapsed-menu
@ -229,6 +229,7 @@ export default {
@import './side-menu.less';
.ivu-layout-sider {
overflow: unset !important;
transition: all 0.3s ease !important;
}
.ivu-menu {
.side-menu-wrapper {
@ -350,8 +351,10 @@ export default {
}
}
.child-menu {
z-index: 999;
z-index: 9;
box-shadow: 2px 0px 4px 0px rgba(0, 0, 0, 0.06);
transition: width .2s ease .2s;
overflow: hidden;
.child-menus {
width: @side-child-width !important;
}
@ -415,6 +418,7 @@ export default {
left: 95px !important;
}
.menu-collapsed {
width: @side-width;
.side-menu-wrapper a.drop-menu-a {
display: flex;
align-items: center;

View File

@ -11,16 +11,15 @@
height: 100%;
}
.tag-nav-wrapper {
// height: 10px;
background: unset;
width: 100%;
margin: 0 15px 0 0px;
margin: 0px;
//overflow: hidden;
padding: 0;
height: 42px;
margin-bottom: 14px;
background-color: #fff;
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.06);
z-index: 8;
}
.tags-nav {
position: relative;

View File

@ -1,7 +1,7 @@
<template>
<div class="tags-nav">
<div class="close-con">
<Dropdown transfer @on-click="handleTagsOption" style="margin-top: 7px">
<Dropdown transfer @on-click="handleTagsOption" style="margin-top: 10px">
<Button size="small" type="text">
<Icon :size="18" type="ios-close-circle-outline" />
</Button>
@ -184,8 +184,8 @@ export default {
}
this.visible = true;
const offsetLeft = this.$el.getBoundingClientRect().left;
this.contextMenuLeft = e.clientX - offsetLeft + 10;
this.contextMenuTop = e.clientY - 64;
this.contextMenuLeft = e.clientX - offsetLeft;
this.contextMenuTop = e.clientY - 34;
},
closeMenu() {
this.visible = false;

View File

@ -303,7 +303,7 @@ export default {
}
}
.main-warper {
min-height: calc(~'100vh - 166px');
min-height: calc(~'100vh - 196px');
}
.all-desk {
height: 100vh !important;
@ -314,8 +314,5 @@ export default {
.content-wrapper {
height: 100vh !important;
}
.content-wrapper {
padding: 0;
}
}
</style>

View File

@ -92,11 +92,13 @@
</Select>
</FormItem>
<FormItem label="消息内容:" prop="content" v-if="formValidate.type === 'text'">
<textarea
<Input
v-model="formValidate.data.content"
placeholder="请填写消息内容"
style="width: 90%"
></textarea>
type="textarea"
:rows="4"
></Input>
</FormItem>
<FormItem label="选取图文:" v-if="formValidate.type === 'news'">
<Button type="info" @click="changePic">选择图文消息</Button>
@ -208,7 +210,7 @@ export default {
formatVoice: ['mp3', 'wma', 'wav', 'amr'],
header: {},
formValidate: {
status: 1,
status: -1,
type: '',
key: this.$route.params.key || '',
data: {
@ -285,6 +287,10 @@ export default {
}
keywordsinfoApi(url, data)
.then(async (res) => {
if (res.data.info.data instanceof Array) {
this.formValidate.status = 0;
return;
}
let info = res.data.info || {};
let data = info.data || {};
this.formValidate = {

View File

@ -156,7 +156,7 @@
type="info"
ghost
style="color: #1890ff; border-color: #1890ff"
v-if="item.refund_type == 1 || item.refund_type == 5"
v-if="item.refund_status == 1"
@click.stop="orderRecord(item.id)"
>退款</Button
>

View File

@ -457,7 +457,7 @@ export default {
},
// 聊天表情转换
replace_em(str) {
str = str.replace(/\[em-([\s\S]*)\]/g, "<span class='em em-$1'/></span>");
str = str.replace(/\[([^\[\]]+)\]/g, "<span class='em $1'/></span>");
return str;
},
// 获取是否游客

View File

@ -30,7 +30,7 @@
<Select
placeholder="请选择"
clearable
style="width: 150px"
style="width: 200px"
v-model="tableFrom.is_show"
@on-change="userSearchs"
>

View File

@ -1792,6 +1792,7 @@ export default {
padding: 20px;
background-color: #fff;
border-radius: 5px;
min-height: 600px;
}
.iview-video-style {

View File

@ -69,7 +69,7 @@
</template>
</Table>
<div class="acea-row row-right page">
<Page :total="total" show-elevator show-total @on-change="pageChange" :page-size="labelFrom.limit" />
<Page :total="total" :model-value="labelFrom.page" show-elevator show-total @on-change="pageChange" :page-size="labelFrom.limit" />
</div>
</Card>
</Col>
@ -191,7 +191,6 @@ export default {
.then((res) => {
this.$Message.success(res.msg);
this.labelLists.splice(num, 1);
this.labelFrom.page = 1;
this.getList();
})
.catch((res) => {
@ -283,7 +282,7 @@ export default {
}
.left-wrapper {
height: 904px;
height: 920px;
background: #fff;
border-right: 1px solid #f2f2f2;
}

View File

@ -1,7 +1,7 @@
<template>
<div>
<Card :bordered="false" dis-hover class="ivu-mt listbox">
<Tabs @on-click="onClickTab" class="mb20">
<Tabs @on-click="onClickTab" class="mb30">
<TabPane :label="item.name" :name="item.type" v-for="(item, index) in headeNum" :key="index" />
</Tabs>
<Form
@ -12,53 +12,41 @@
@submit.native.prevent
>
<Row :gutter="16">
<Col span="18">
<Col span="24">
<Col span="20">
<FormItem label="用户搜索:" label-for="nickname">
<Input v-model="userFrom.nickname" placeholder="请输入用户" element-id="nickname" clearable>
<Select v-model="field_key" slot="prepend" style="width: 80px">
<Option value="all">全部</Option>
<Option value="uid">UID</Option>
<Option value="phone">手机号</Option>
<Option value="nickname">用户昵称</Option>
</Select>
</Input>
</FormItem>
</Col>
</Col>
<Col v-bind="grid">
<FormItem label="用户搜索:" label-for="nickname">
<Input v-model="userFrom.nickname" placeholder="请输入用户" element-id="nickname" clearable>
<Select v-model="field_key" slot="prepend" style="width: 80px">
<Option value="all">全部</Option>
<Option value="uid">UID</Option>
<Option value="phone">手机号</Option>
<Option value="nickname">用户昵称</Option>
</Select>
</Input>
</FormItem>
</Col>
<Col span="12" class="ivu-text-left userFrom" v-if="!collapse">
<FormItem>
<Button type="primary" icon="ios-search" label="default" class="mr15" @click="userSearchs">搜索</Button>
<Button class="ResetSearch" @click="reset('userFrom')">重置</Button>
<a class="ivu-ml-8 font14 ml10" @click="collapse = !collapse">
<template v-if="!collapse"> 展开 <Icon type="ios-arrow-down" /> </template>
<template v-else> 收起 <Icon type="ios-arrow-up" /> </template>
</a>
</FormItem>
</Col>
<template v-if="collapse">
<Col span="18">
<Col v-bind="grid">
<FormItem label="用户等级:" label-for="level">
<Select v-model="level" placeholder="请选择用户等级" element-id="level" clearable>
<Option value="all">全部</Option>
<Option :value="item.id" v-for="(item, index) in levelList" :key="index">{{ item.name }}</Option>
</Select>
</FormItem>
</Col>
<Col v-bind="grid">
<FormItem label="用户分组:" label-for="group_id">
<Select v-model="group_id" placeholder="请选择用户分组" element-id="group_id" clearable>
<Option value="all">全部</Option>
<Option :value="item.id" v-for="(item, index) in groupList" :key="index">{{
item.group_name
}}</Option>
</Select>
</FormItem>
</Col>
<Col v-bind="grid">
<FormItem label="用户标签:" label-for="label_id">
<div class="labelInput acea-row row-between-wrapper" @click="openSelectLabel">
<div style="width: 90%">
<div v-if="selectDataLabel.length">
<Tag
:closable="false"
v-for="(item, index) in selectDataLabel"
@on-close="closeLabel(item)"
:key="index"
>{{ item.label_name }}</Tag
:closable="false"
v-for="(item, index) in selectDataLabel"
@on-close="closeLabel(item)"
:key="index"
>{{ item.label_name }}</Tag
>
</div>
<span class="span" v-else>选择用户关联标签</span>
@ -67,50 +55,37 @@
</div>
</FormItem>
</Col>
</Col>
<Col span="18">
<Col v-bind="grid">
<FormItem label="付费会员:" label-for="isMember">
<!-- <Select
v-model="userFrom.isMember"
placeholder="请选择付费会员"
element-id="isMember"
clearable
@on-change="changeMember"
>
<Option :value="1">是</Option>
<Option :value="0">否</Option>
</Select> -->
<RadioGroup v-model="userFrom.isMember" type="button">
<Radio label="">
<span>全部</span>
</Radio>
<Radio label="1">
<span>是</span>
</Radio>
<Radio label="0">
<span>否</span>
</Radio>
</RadioGroup>
</FormItem>
</Col>
<Col v-bind="grid">
<FormItem label="国家:" label-for="country">
<Select
v-model="userFrom.country"
placeholder="请选择国家"
element-id="country"
clearable
@on-change="changeCountry"
>
<Option value="domestic">中国</Option>
<Option value="abroad">外国</Option>
<FormItem label="下单次数:" label-for="pay_count">
<Select v-model="pay_count" placeholder="请选择下单次数" element-id="pay_count" clearable>
<Option value="all">全部</Option>
<Option value="-1">0次</Option>
<Option value="0">1次以上</Option>
<Option value="1">2次以上</Option>
<Option value="2">3次以上</Option>
<Option value="3">4次以上</Option>
<Option value="4">5次以上</Option>
</Select>
</FormItem>
</Col>
<Col v-bind="grid" v-if="userFrom.country === 'domestic'">
<FormItem label="省份:">
<Cascader :data="addresData" :value="address" v-model="address" @on-change="handleChange"></Cascader>
</Col>
<Col span="18">
<Col v-bind="grid">
<FormItem label="用户分组:" label-for="group_id">
<Select v-model="group_id" placeholder="请选择用户分组" element-id="group_id" clearable>
<Option value="all">全部</Option>
<Option :value="item.id" v-for="(item, index) in groupList" :key="index">{{
item.group_name
}}</Option>
</Select>
</FormItem>
</Col>
<Col v-bind="grid">
<FormItem label="用户等级:" label-for="level">
<Select v-model="level" placeholder="请选择用户等级" element-id="level" clearable>
<Option value="all">全部</Option>
<Option :value="item.id" v-for="(item, index) in levelList" :key="index">{{ item.name }}</Option>
</Select>
</FormItem>
</Col>
</Col>
@ -148,6 +123,31 @@
</RadioGroup>
</FormItem>
</Col>
<Col v-bind="grid">
<FormItem label="付费会员:" label-for="isMember">
<!-- <Select
v-model="userFrom.isMember"
placeholder="请选择付费会员"
element-id="isMember"
clearable
@on-change="changeMember"
>
<Option :value="1">是</Option>
<Option :value="0">否</Option>
</Select> -->
<RadioGroup v-model="userFrom.isMember" type="button">
<Radio label="">
<span>全部</span>
</Radio>
<Radio label="1">
<span>是</span>
</Radio>
<Radio label="0">
<span>否</span>
</Radio>
</RadioGroup>
</FormItem>
</Col>
</Col>
<Col span="18">
<Col v-bind="grid">
@ -180,21 +180,29 @@
</Col>
<Col span="18">
<Col v-bind="grid">
<FormItem label="下单次数:" label-for="pay_count">
<Select v-model="pay_count" placeholder="请选择下单次数" element-id="pay_count" clearable>
<Option value="all">全部</Option>
<Option value="-1">0次</Option>
<Option value="0">1次以上</Option>
<Option value="1">2次以上</Option>
<Option value="2">3次以上</Option>
<Option value="3">4次以上</Option>
<Option value="4">5次以上</Option>
<FormItem label="地区:" label-for="country">
<Select
v-model="userFrom.country"
placeholder="请选择国家"
element-id="country"
clearable
@on-change="changeCountry"
>
<Option value="domestic">中国</Option>
<Option value="abroad">外国</Option>
</Select>
</FormItem>
</Col>
<Col v-bind="grid" v-if="userFrom.country === 'domestic'">
<FormItem label="省份:">
<Cascader :data="addresData" :value="address" v-model="address" @on-change="handleChange"></Cascader>
</FormItem>
</Col>
</Col>
</template>
<Col span="6" class="ivu-text-right userFrom">
</Row>
<Row v-if="collapse">
<Col span="13" class="ivu-text-right userFrom">
<FormItem>
<Button type="primary" icon="ios-search" label="default" class="mr15" @click="userSearchs">搜索</Button>
<Button class="ResetSearch" @click="reset('userFrom')">重置</Button>
@ -209,11 +217,11 @@
<Divider dashed />
<Row type="flex" justify="space-between" class="mt20">
<Col span="24">
<Button v-auth="['admin-user-save']" type="primary" class="mr20" @click="edit({ uid: 0 })">添加用户</Button>
<Button v-auth="['admin-user-coupon']" class="mr20" @click="onSend">发送优惠券</Button>
<Button v-auth="['admin-user-save']" type="primary" class="mr10" @click="edit({ uid: 0 })">添加用户</Button>
<Button v-auth="['admin-user-coupon']" class="mr10" @click="onSend">发送优惠券</Button>
<Button
v-auth="['admin-wechat-news']"
class="greens mr20"
class="greens mr10"
size="default"
@click="onSendPic"
v-if="userFrom.user_type === 'wechat'"
@ -221,9 +229,9 @@
<Icon type="md-list"></Icon>
发送图文消息
</Button>
<Button v-auth="['admin-user-group_set']" class="mr20" @click="setGroup">批量设置分组</Button>
<Button v-auth="['admin-user-set_label']" class="mr20" @click="setLabel">批量设置标签</Button>
<Button class="mr20" icon="ios-share-outline" @click="exportList">导出</Button>
<Button v-auth="['admin-user-group_set']" class="mr10" @click="setGroup">批量设置分组</Button>
<Button v-auth="['admin-user-set_label']" class="mr10" @click="setLabel">批量设置标签</Button>
<Button class="mr10" icon="ios-share-outline" @click="exportList">导出</Button>
<!-- <Button v-auth="['admin-user-synchro']" class="mr20" @click="synchro">同步公众号用户</Button> -->
</Col>
@ -236,7 +244,7 @@
<Table
:columns="columns"
:data="userLists"
class="mt25"
class="mt10"
ref="table"
highlight-row
:loading="loading"

View File

@ -8,14 +8,14 @@
// | Author: CRMEB Team <admin@crmeb.com>
// +---------------------------------------------------------------------
import setting from '@/setting'
import setting from '@/setting';
let routePre = setting.routePre;
const pre = 'kefu_';
export default [
// 登录
{
path: routePre+'/login',
path: routePre + '/login',
name: 'login',
meta: {
title: '登录',
@ -25,13 +25,16 @@ export default [
},
// 客服
{
path: '/kefu',
path: routePre + '/kefu',
name: `${pre}index`,
meta: {
auth: true,
title: '客服管理',
kefu: true,
},
redirect: {
name: `setting_service`,
},
component: () => import('@/pages/kefu/index'),
},
{

View File

@ -9,7 +9,7 @@
// +---------------------------------------------------------------------
import BasicLayout from '@/components/main';
import setting from '@/setting'
import setting from '@/setting';
let routePre = setting.routePre;
const meta = {
@ -19,11 +19,11 @@ const meta = {
const pre = 'setting_';
export default {
path: routePre+'/setting',
path: routePre + '/setting',
name: 'setting',
header: 'setting',
redirect: {
name: `${pre}systemRole`,
name: `${pre}setSystem`,
},
component: BasicLayout,
children: [
@ -385,6 +385,14 @@ export default {
},
component: () => import('@/pages/setting/themeStyle/index'),
},
{
path: 'pages',
name: `${pre}page`,
header: 'setting',
redirect: {
name: `${pre}devise`,
},
},
{
path: 'pages/devise',
name: `${pre}devise`,

View File

@ -537,7 +537,10 @@ body {
font-size: 20px;
}
.main .content-wrapper {
padding-top: 0;
padding: 16px;
height: calc(100% - 80px);
overflow: auto;
background-color: #f5f7f9;
}
.left-wrapper{
height: calc(100vh - 120px);

View File

@ -416,7 +416,7 @@
},
// 聊天表情转换
replace_em(str) {
str = str.replace(/\[em-([\s\S]*)\]/g, "<span class='em em-$1' style='background-image:url(" + this
str = str.replace(/\[([^\[\]]+)\]/g, "<span class='em $1' style='background-image:url(" + this
.httpUrl + ")'></span>");
return str;
},

View File

@ -320,7 +320,7 @@
})
},
replace_em(str) {
str = str.replace(/\[em-([a-z_]*)\]/g, "<span class='em em-$1'/></span>");
str = str.replace(/\[([^\[\]]+)\]/g, "<span class='em $1'/></span>");
return str;
},
goChat(id) {

View File

@ -1,408 +1,433 @@
<template>
<view :style="colorStyle">
<view class='collectionGoods' v-if="collectProductList.length">
<view class="title-admin">
<view>{{$t(`当前共`)}} <text class="text"> {{count}} </text> {{$t(`件商品`)}}</view>
<view class="admin" @click="showRadio">{{checkbox_show?$t(`取消`):$t(`管理`)}}</view>
</view>
<checkbox-group @change="checkboxChange">
<view class='item acea-row' v-for="(item,index) in collectProductList" :key="index">
<view class="left">
<checkbox v-show="checkbox_show" :value="item.pid.toString()" :checked="item.checked" />
<view class='pictrue'>
<image :src="item.image"></image>
</view>
</view>
<view class='text acea-row row-column-between' @click="jump(item)">
<view class='name line2'>{{item.store_name}}</view>
<view class='acea-row row-between-wrapper'>
<view class='money font-color'>{{$t(`¥`)}}{{item.price}}</view>
<!-- <view class='delete' @click.stop='delCollection(item.pid,index)'>删除</view> -->
</view>
</view>
</view>
<view class='loadingicon acea-row row-center-wrapper'>
<text class='loading iconfont icon-jiazai' :hidden='loading==false'></text>{{loadTitle}}
</view>
</checkbox-group>
</view>
<view class='noCommodity' v-else-if="!collectProductList.length && page > 1">
<view class='pictrue'>
<image :src="imgHost + '/statics/images/noCollection.png'"></image>
</view>
<recommend :hostProduct="hostProduct"></recommend>
</view>
<view class='footer acea-row row-between-wrapper' v-if="checkbox_show && collectProductList.length">
<view>
<checkbox-group @change="checkboxAllChange">
<checkbox value="all" :checked="!!isAllSelect" />
<text class='checkAll'>{{$t(`全选`)}}({{ids.length}})</text>
</checkbox-group>
</view>
<view class='button acea-row row-middle'>
<button class='bnt' formType="submit" @click="subDel">{{$t(`取关`)}}</button>
</view>
</view>
<!-- #ifdef MP -->
<!-- <authorize @onLoadFun="onLoadFun" :isAuto="isAuto" :isShowAuth="isShowAuth" @authColse="authColse"></authorize> -->
<!-- #endif -->
<!-- #ifndef MP -->
<home></home>
<!-- #endif -->
</view>
</template>
<script>
import {
getCollectUserList,
getProductHot,
collectDel
} from '@/api/store.js';
import {
mapGetters
} from "vuex";
import {
toLogin
} from '@/libs/login.js';
import recommend from '@/components/recommend';
// #ifdef MP
import authorize from '@/components/Authorize';
// #endif
import home from '@/components/home';
import colors from '@/mixins/color.js';
import {HTTP_REQUEST_URL} from '@/config/app';
export default {
components: {
recommend,
// #ifdef MP
authorize,
// #endif
home
},
mixins: [colors],
data() {
return {
imgHost:HTTP_REQUEST_URL,
ids: [],
hostProduct: [],
checkbox_show: false,
loadTitle: this.$t(`加载更多`),
loading: false,
loadend: false,
collectProductList: [],
count: 0,
limit: 15,
page: 1,
isAuto: false, //没有授权的不会自动授权
isShowAuth: false, //是否隐藏授权
hotScroll: false,
hotPage: 1,
hotLimit: 10,
isAllSelect: false, //全选
};
},
computed: mapGetters(['isLogin']),
onLoad() {
if (this.isLogin) {
this.loadend = false;
this.page = 1;
this.collectProductList = [];
this.getUserCollectProduct();
} else {
toLogin();
}
},
onShow() {
this.loadend = false;
this.page = 1;
this.$set(this, 'collectProductList', []);
this.getUserCollectProduct();
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function() {
this.getUserCollectProduct();
},
methods: {
showRadio() {
this.checkbox_show = !this.checkbox_show
},
checkboxChange(e) {
if (e.detail.value.length < this.ids.length) {
this.$set(this, 'isAllSelect', false);
} else if (e.detail.value.length === this.collectProductList.length) {
this.$set(this, 'isAllSelect', true);
}
this.$set(this, 'ids', e.detail.value);
},
subDel() {
let that = this
if (this.ids.length) {
collectDel(that.ids).then(res => {
that.loadend = false;
that.$util.Tips({
title: res.msg
});
that.page = 1;
that.collectProductList = [];
this.getUserCollectProduct();
this.ids.length = '';
});
} else {
return that.$util.Tips({
title: that.$t(`请选择商品`)
});
}
},
checkboxAllChange(event) {
let value = event.detail.value;
if (value.length > 0) {
this.setAllSelectValue(1)
} else {
this.setAllSelectValue(0)
}
},
setAllSelectValue(status) {
let that = this;
let selectValue = [];
let valid = that.collectProductList;
if (valid.length > 0) {
let newValid = valid.map(item => {
if (status) {
item.checked = true;
selectValue.push(item.pid);
that.isAllSelect = true;
} else {
item.checked = false;
that.isAllSelect = false;
}
return item;
});
that.$set(that, 'collectProductList', newValid);
that.$set(that, 'ids', selectValue);
}
},
jump(item) {
uni.navigateTo({
url: "/pages/goods_details/index?id=" + item.pid
})
},
/**
* 授权回调
*/
onLoadFun: function() {
this.loadend = false;
this.page = 1;
this.$set(this, 'collectProductList', []);
this.getUserCollectProduct();
// this.get_host_product();
},
// 授权关闭
authColse(e) {
this.isShowAuth = e
},
/**
* 获取收藏产品
*/
getUserCollectProduct() {
let that = this;
if (this.loading) return;
if (this.loadend) return;
that.loading = true;
that.loadTitle = "";
getCollectUserList({
page: that.page,
limit: that.limit
}).then(res => {
this.count = res.data.count;
let collectProductList = res.data.list;
collectProductList.map(e => {
e.checked = false
})
let loadend = collectProductList.length < that.limit;
that.collectProductList = that.$util.SplitArray(collectProductList, that
.collectProductList);
that.$set(that, 'collectProductList', that.collectProductList);
that.loadend = loadend;
that.loadTitle = loadend ? that.$t(`我也是有底线的`) : that.$t(`加载更多`);
if (!that.collectProductList.length && that.page == 1) this.get_host_product();
that.page = that.page + 1;
that.loading = false;
}).catch(err => {
that.loading = false;
that.loadTitle = that.$t(`加载更多`);
});
},
/**
* 获取我的推荐
*/
get_host_product() {
let that = this;
if (that.hotScroll) return
getProductHot(
that.hotPage,
that.hotLimit,
).then(res => {
that.hotPage++
that.hotScroll = res.data.length < that.hotLimit
that.hostProduct = that.hostProduct.concat(res.data)
});
}
},
onReachBottom() {
this.getUserCollectProduct();
},
// 滚动监听
onPageScroll(e) {
// 传入scrollTop值并触发所有easy-loadimage组件下的滚动监听事件
uni.$emit('scroll');
},
}
</script>
<style scoped lang="scss">
.collectionGoods {
background-color: #fff;
border-top: 1rpx solid #eee;
}
.collectionGoods .item {
margin-left: 30rpx;
border-bottom: 1rpx solid #eee;
height: 180rpx;
display: flex;
align-items: center;
flex-wrap: nowrap;
}
.left {
display: flex;
align-items: center;
margin-right: 20rpx;
}
.collectionGoods .item .pictrue {
width: 130rpx;
height: 130rpx;
margin-left: 20rpx;
}
.collectionGoods .item .pictrue image {
width: 100%;
height: 100%;
border-radius: 6rpx;
}
.collectionGoods .item .text {
height: 130rpx;
flex: 1;
font-size: 28rpx;
<template>
<view :style="colorStyle">
<view class='collectionGoods' v-if="collectProductList.length">
<view class="title-admin">
<view>{{$t(`当前共`)}} <text class="text"> {{count}} </text> {{$t(`件商品`)}}</view>
<view class="admin" @click="showRadio">{{checkbox_show?$t(`取消`):$t(`管理`)}}</view>
</view>
<checkbox-group @change="checkboxChange">
<view class='item acea-row' v-for="(item,index) in collectProductList" :key="index">
<view class="left">
<checkbox v-show="checkbox_show" :value="item.pid.toString()" :checked="item.checked" />
<view class='pictrue'>
<image :src="item.image"></image>
<view class="invalid acea-row row-center-wrapper" v-if="!item.is_show">
已下架
</view>
</view>
</view>
<view class='text acea-row row-column-between' @click="jump(item)">
<view class='name line2'>{{item.store_name}}</view>
<view class='acea-row row-between-wrapper'>
<view class='money font-color'>{{$t(`¥`)}}{{item.price}}</view>
<!-- <view class='delete' @click.stop='delCollection(item.pid,index)'>删除</view> -->
</view>
</view>
</view>
<view class='loadingicon acea-row row-center-wrapper'>
<text class='loading iconfont icon-jiazai' :hidden='loading==false'></text>{{loadTitle}}
</view>
</checkbox-group>
</view>
<view class='noCommodity' v-else-if="!collectProductList.length && page > 1">
<view class='pictrue'>
<image :src="imgHost + '/statics/images/noCollection.png'"></image>
</view>
<recommend :hostProduct="hostProduct"></recommend>
</view>
<view class='footer acea-row row-between-wrapper' v-if="checkbox_show && collectProductList.length">
<view>
<checkbox-group @change="checkboxAllChange">
<checkbox value="all" :checked="!!isAllSelect" />
<text class='checkAll'>{{$t(`全选`)}}({{ids.length}})</text>
</checkbox-group>
</view>
<view class='button acea-row row-middle'>
<button class='bnt' formType="submit" @click="subDel">{{$t(`取关`)}}</button>
</view>
</view>
<!-- #ifdef MP -->
<!-- <authorize @onLoadFun="onLoadFun" :isAuto="isAuto" :isShowAuth="isShowAuth" @authColse="authColse"></authorize> -->
<!-- #endif -->
<!-- #ifndef MP -->
<home></home>
<!-- #endif -->
</view>
</template>
<script>
import {
getCollectUserList,
getProductHot,
collectDel
} from '@/api/store.js';
import {
mapGetters
} from "vuex";
import {
toLogin
} from '@/libs/login.js';
import recommend from '@/components/recommend';
// #ifdef MP
import authorize from '@/components/Authorize';
// #endif
import home from '@/components/home';
import colors from '@/mixins/color.js';
import {
HTTP_REQUEST_URL
} from '@/config/app';
export default {
components: {
recommend,
// #ifdef MP
authorize,
// #endif
home
},
mixins: [colors],
data() {
return {
imgHost: HTTP_REQUEST_URL,
ids: [],
hostProduct: [],
checkbox_show: false,
loadTitle: this.$t(`加载更多`),
loading: false,
loadend: false,
collectProductList: [],
count: 0,
limit: 15,
page: 1,
isAuto: false, //没有授权的不会自动授权
isShowAuth: false, //是否隐藏授权
hotScroll: false,
hotPage: 1,
hotLimit: 10,
isAllSelect: false, //全选
};
},
computed: mapGetters(['isLogin']),
onLoad() {
if (this.isLogin) {
this.loadend = false;
this.page = 1;
this.collectProductList = [];
this.getUserCollectProduct();
} else {
toLogin();
}
},
onShow() {
this.loadend = false;
this.page = 1;
this.$set(this, 'collectProductList', []);
this.getUserCollectProduct();
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function() {
this.getUserCollectProduct();
},
methods: {
showRadio() {
this.checkbox_show = !this.checkbox_show
},
checkboxChange(e) {
if (e.detail.value.length < this.ids.length) {
this.$set(this, 'isAllSelect', false);
} else if (e.detail.value.length === this.collectProductList.length) {
this.$set(this, 'isAllSelect', true);
}
this.$set(this, 'ids', e.detail.value);
},
subDel() {
let that = this
if (this.ids.length) {
collectDel(that.ids).then(res => {
that.loadend = false;
that.$util.Tips({
title: res.msg
});
that.page = 1;
that.collectProductList = [];
this.getUserCollectProduct();
this.ids.length = '';
});
} else {
return that.$util.Tips({
title: that.$t(`请选择商品`)
});
}
},
checkboxAllChange(event) {
let value = event.detail.value;
if (value.length > 0) {
this.setAllSelectValue(1)
} else {
this.setAllSelectValue(0)
}
},
setAllSelectValue(status) {
let that = this;
let selectValue = [];
let valid = that.collectProductList;
if (valid.length > 0) {
let newValid = valid.map(item => {
if (status) {
item.checked = true;
selectValue.push(item.pid);
that.isAllSelect = true;
} else {
item.checked = false;
that.isAllSelect = false;
}
return item;
});
that.$set(that, 'collectProductList', newValid);
that.$set(that, 'ids', selectValue);
}
},
jump(item) {
if (item.is_show) {
uni.navigateTo({
url: "/pages/goods_details/index?id=" + item.pid
})
} else {
this.$util.Tips({
title: that.$t(`该商品已下架`)
})
}
},
/**
* 授权回调
*/
onLoadFun: function() {
this.loadend = false;
this.page = 1;
this.$set(this, 'collectProductList', []);
this.getUserCollectProduct();
// this.get_host_product();
},
// 授权关闭
authColse(e) {
this.isShowAuth = e
},
/**
* 获取收藏产品
*/
getUserCollectProduct() {
let that = this;
if (this.loading) return;
if (this.loadend) return;
that.loading = true;
that.loadTitle = "";
getCollectUserList({
page: that.page,
limit: that.limit
}).then(res => {
this.count = res.data.count;
let collectProductList = res.data.list;
collectProductList.map(e => {
e.checked = false
})
let loadend = collectProductList.length < that.limit;
that.collectProductList = that.$util.SplitArray(collectProductList, that
.collectProductList);
that.$set(that, 'collectProductList', that.collectProductList);
that.loadend = loadend;
that.loadTitle = loadend ? that.$t(`我也是有底线的`) : that.$t(`加载更多`);
if (!that.collectProductList.length && that.page == 1) this.get_host_product();
that.page = that.page + 1;
that.loading = false;
}).catch(err => {
that.loading = false;
that.loadTitle = that.$t(`加载更多`);
});
},
/**
* 获取我的推荐
*/
get_host_product() {
let that = this;
if (that.hotScroll) return
getProductHot(
that.hotPage,
that.hotLimit,
).then(res => {
that.hotPage++
that.hotScroll = res.data.length < that.hotLimit
that.hostProduct = that.hostProduct.concat(res.data)
});
}
},
onReachBottom() {
this.getUserCollectProduct();
},
// 滚动监听
onPageScroll(e) {
// 传入scrollTop值并触发所有easy-loadimage组件下的滚动监听事件
uni.$emit('scroll');
},
}
</script>
<style scoped lang="scss">
.collectionGoods {
background-color: #fff;
border-top: 1rpx solid #eee;
}
.collectionGoods .item {
margin-left: 30rpx;
border-bottom: 1rpx solid #eee;
height: 180rpx;
display: flex;
align-items: center;
flex-wrap: nowrap;
}
.left {
display: flex;
align-items: center;
margin-right: 20rpx;
}
.collectionGoods .item .pictrue {
width: 130rpx;
height: 130rpx;
margin-left: 20rpx;
position: relative;
.invalid {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, 0.4);
backdrop-filter: blur(3px);
color: #fff;
}
}
.collectionGoods .item .pictrue image {
width: 100%;
height: 100%;
border-radius: 6rpx;
}
.collectionGoods .item .text {
height: 130rpx;
flex: 1;
font-size: 28rpx;
color: #282828;
}
.collectionGoods .item .text .name {
width: max-contnet;
}
.collectionGoods .item .text .money {
font-size: 26rpx;
}
.collectionGoods .item .text .delete {
font-size: 26rpx;
color: #282828;
width: 144rpx;
height: 46rpx;
border: 1px solid #bbb;
border-radius: 4rpx;
text-align: center;
line-height: 46rpx;
}
.noCommodity {
background-color: #fff;
padding-top: 1rpx;
border-top: 0;
}
.title-admin {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx;
border-bottom: 1px solid #f2f2f2;
.text {
color: var(--view-theme);
}
.admin {
color: var(--view-theme);
}
}
.footer {
z-index: 999;
width: 100%;
height: 96rpx;
background-color: #fafafa;
position: fixed;
padding: 0 30rpx;
box-sizing: border-box;
border-top: 1rpx solid #eee;
bottom: 0;
}
.footer.on {
// #ifndef H5
bottom: 0rpx;
// #endif
// #ifdef MP || APP-PLUS
bottom: 100rpx;
bottom: calc(100rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
bottom: calc(100rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
// #endif
}
.footer .checkAll {
font-size: 28rpx;
color: #282828;
margin-left: 16rpx;
}
// .shoppingCart .footer checkbox .wx-checkbox-input{background-color:#fafafa;}
.footer .money {
font-size: 30rpx;
}
.footer .placeOrder {
color: #fff;
font-size: 30rpx;
width: 226rpx;
height: 70rpx;
border-radius: 50rpx;
text-align: center;
line-height: 70rpx;
margin-left: 22rpx;
}
.footer .button .bnt {
font-size: 28rpx;
color: #999;
border-radius: 50rpx;
border: 1px solid #999;
width: 160rpx;
height: 60rpx;
text-align: center;
line-height: 60rpx;
}
.footer .button form~form {
margin-left: 17rpx;
}
padding-right: 20rpx;
}
.collectionGoods .item .text .name {
width: max-contnet;
}
.collectionGoods .item .text .money {
font-size: 26rpx;
}
.collectionGoods .item .text .delete {
font-size: 26rpx;
color: #282828;
width: 144rpx;
height: 46rpx;
border: 1px solid #bbb;
border-radius: 4rpx;
text-align: center;
line-height: 46rpx;
}
.noCommodity {
background-color: #fff;
padding-top: 1rpx;
border-top: 0;
}
.title-admin {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx;
border-bottom: 1px solid #f2f2f2;
.text {
color: var(--view-theme);
}
.admin {
color: var(--view-theme);
}
}
.footer {
z-index: 999;
width: 100%;
height: 96rpx;
background-color: #fafafa;
position: fixed;
padding: 0 30rpx;
box-sizing: border-box;
border-top: 1rpx solid #eee;
bottom: 0;
}
.footer.on {
// #ifndef H5
bottom: 0rpx;
// #endif
// #ifdef MP || APP-PLUS
bottom: 100rpx;
bottom: calc(100rpx + constant(safe-area-inset-bottom)); ///兼容 IOS<11.2/
bottom: calc(100rpx + env(safe-area-inset-bottom)); ///兼容 IOS>11.2/
// #endif
}
.footer .checkAll {
font-size: 28rpx;
color: #282828;
margin-left: 16rpx;
}
// .shoppingCart .footer checkbox .wx-checkbox-input{background-color:#fafafa;}
.footer .money {
font-size: 30rpx;
}
.footer .placeOrder {
color: #fff;
font-size: 30rpx;
width: 226rpx;
height: 70rpx;
border-radius: 50rpx;
text-align: center;
line-height: 70rpx;
margin-left: 22rpx;
}
.footer .button .bnt {
font-size: 28rpx;
color: #999;
border-radius: 50rpx;
border: 1px solid #999;
width: 160rpx;
height: 60rpx;
text-align: center;
line-height: 60rpx;
}
.footer .button form~form {
margin-left: 17rpx;
}
</style>