1.创建组件

components/FilterBar/FilterBar.vue

<template>
<div class="filterbar" :style="{'top': top + 'px'}">
<div class="container">
<div class="row">
<div
class="col"
:class="{'selected': index == selectedIndexMenu}"
@click="handleShowDialog(barMenu, index)"
v-for="(barMenu, index) in barMenus"
:key="index"
>
{{barMenu.name}}<span :class="index == selectedIndexMenu ? barMenu.selectIcon : barMenu.defaultIcon"></span>
</div>
</div>
<filter-bar-pop
:filterTop="top"
:show-dialog="isShow"
:hasTabHeader="hasTabHeader"
:menu="selectedMenu"
@changeTab="handleChangeTab"
@changeMainItem="handleChangeMainItem"
@changeSelect="changeSelect"
@closeDialog="handleCloseDialog"
></filter-bar-pop>
</div>
</div>
</template> <script>
import FilterBarPop from './FilterBarPop'
export default {
props: {
barMenus: {
type: Array,
required: true,
validator: function (value) {
//TODO:验证数据有效性
return true;
}
},
top: String
},
data() {
return {
isShow: false,
hasTabHeader: false,
selectedMenu: {},
selectedIndexMenu: undefined
}
},
methods: {
handleShowDialog(menu, index) {
this.isShow = true;
this.selectedMenu = menu;
this.selectedIndexMenu = index;
if (menu.showTabHeader) {
this.hasTabHeader = true;
} else {
this.hasTabHeader = false;
}
let _menu = JSON.parse(JSON.stringify(menu));
_menu.tabs = {};
this.$emit('showDialog', _menu);
},
handleChangeTab(tab) {
this.$emit('changeTab', tab.index);
},
handleChangeMainItem(mainItem) {
let _mainItem = JSON.parse(JSON.stringify(mainItem));
this.$emit('changeMainItem', _mainItem);
},
handleCloseDialog() {
this.isShow = false;
this.selectedIndexMenu = -1;
this.$emit('closeDialog');
},
changeSelect() {
var selectData = [];
this.barMenus.forEach(function (barMenu, index, arr) {
let _selectBarData = {};
// console.log("barMenu.name: " + barMenu.name);
_selectBarData.name = barMenu.name;
_selectBarData.value = barMenu.value;
_selectBarData.tab = {};
let tab = barMenu.tabs[barMenu.selectIndex];
// console.log("tab.name: " + tab.name);
_selectBarData.tab.name = tab.name;
_selectBarData.tab.value = tab.value;
let mainItem = tab.detailList[tab.selectIndex];
_selectBarData.tab.mainItem = {}
// console.log("mainItem.name: " + mainItem.name);
_selectBarData.tab.mainItem.name = mainItem.name;
_selectBarData.tab.mainItem.value = mainItem.vaule;
let subItem = false;
if (mainItem.list) {
subItem = mainItem.list[mainItem.selectIndex];
_selectBarData.tab.mainItem.subItem = {};
// console.log("subItem.name: " + subItem.name);
_selectBarData.tab.mainItem.subItem.name = subItem.name;
_selectBarData.tab.mainItem.subItem.value = subItem.value;
} else {
_selectBarData.tab.mainItem.subItem = subItem;
}
selectData.push(_selectBarData);
});
this.$emit('changeSelect', selectData);
}
},
components: {
'filter-bar-pop': FilterBarPop
}
}
</script> <style lang="scss">
.filterbar {
width: 100%;
background: #fff;
position: fixed;
top: 0;
left: 0;
right: 0;
.container {
width: 100%;
outline: 1px solid #DBDCDE;
position: relative;
.row {
display: flex;
display: -ms-flexbox;
display: -moz-box;
display: -webkit-box;
display: -webkit-flex;
flex-direction: row;
-webkit-flex-direction: row;
justify-content: space-around;
-webkit-box-pack: space-around;
-moz-box-pack: space-around;
-ms-flex-pack: space-around;
width: 90%;
height: 40px;
margin: 0 auto;
line-height: 40px;
.selected {
color: orange;
}
.col {
span {
margin-left: 5px;
vertical-align: middle;
}
}
}
}
}
</style>

components/FilterBar/FilterBarPop.vue

<template>
<transition name="fade">
<div class="filterbarpop-wrap" v-if="visible" :style="{'top': bgTop + 'px'}">
<div class="filterbarpop-bg" @click="closeDialog" :style="{'top': bgTop + 'px'}"></div>
<div class="filterbarpop">
<div class="tab-bar" v-show="hasTabHeader">
<a href="javascript:;" :style="{'flex': column}" role="button" @click="clickTab(tab, index)" v-for="(tab, index) in menu.tabs"
:class="{'selected': selectIndexTab == index}"><span :class="tab.icon"></span>{{tab.name}}</a>
</div>
<div class="main">
<div class="main-sidebar" :class="{'full-line': !items,'bg-style':items,'line-style':!items,}">
<div v-if="menu.type !== 'filter'" class="item" @click="clickSidebar(sidemenu, index)" v-for="(sidemenu, index) in sideMenus.detailList"
:class="{'selected': currentSelectIndex == index}">
<span :class="sidemenu.icon"></span>{{ sidemenu.name }}
</div>
<div v-if="menu.type == 'filter'" v-for="(sm, _index) in menu.tabs">
<div class="filter-name">{{sm.name}}</div>
<div class="filter-item">
<span v-for="(sidemenu, index) in sm.detailList" class="item-operation" @click="clickFilterbar(sm, _index, index)" :class="{'multi-selected': sidemenu.selectIndex == index}">
{{ sidemenu.name }}
</span>
</div>
</div>
<div v-if="menu.type == 'filter'" class="filter-btns">
<a href="javascript:;" role="button" @click="handleClean">取消</a>
<a href="javascript:;" role="button" @click="handleEnsure">确认</a>
</div>
</div>
<div class="main-list line-style" v-if="items">
<span class="item" @click="clickItem(item, index)" v-for="(item, index) in items.list" :class="{'selected': currentSelectIndex == sideMenus.selectIndex && items.selectIndex == index}">{{item.name}}</span>
</div>
</div>
</div>
</div>
</transition>
</template> <script>
export default {
props: {
menu: {
type: Object
},
showDialog: {
type: Boolean,
default: true
},
hasTabHeader: {
type: Boolean,
default: true
},
filterTop: {
type: String
}
},
data() {
return {
selectIndexTab: 0,
currentSelectIndex: 0,
sideMenus: {},
items: {},
column: '',
visible: false,
top: 1,
bgTop: 0,
range: {}
}
},
mounted() {
this.bgTop = document.querySelector('.filterbar').offsetHeight + this.filterTop / 1;
},
watch: {
showDialog(v) {
this.visible = v;
if (v) {
//初始化数据
this.initData();
}
},
menu(m) {
//根据tabs数量计算列宽
this.column = '0 0 ' + 100 / m.tabs.length + '%';
//初始化数据
this.initData();
}
},
methods: {
//初始化数据
initData(tabIndex) {
var tmpTabIndx = 0;
tabIndex === undefined ? tmpTabIndx = this.menu.selectIndex : tmpTabIndx = tabIndex
//判断tabindex的范围是否在数组内
if (tmpTabIndx >= 0 && tmpTabIndx < this.menu.tabs.length) {
this.selectIndexTab = tmpTabIndx;
} else {
this.selectIndexTab = 0;
}
//确认选中tab的一级列表
this.sideMenus = this.menu.tabs[this.selectIndexTab];
//如果当前选中tab是对应选中结果的tab
// debugger;
if (this.selectIndexTab == this.menu.selectIndex) {
this.currentSelectIndex = this.sideMenus.selectIndex;
}
// else{
// this.sideMenus.selectIndex = -1;
// this.currentSelectIndex = -1;
// }
//判断是否包含二级列表,包含则赋值
//如果一级列表的选中状态正确,则查询二级列表
if (this.currentSelectIndex >= 0 && this.currentSelectIndex < this.sideMenus.detailList.length) {
//判断是否有二级列表
if (this.sideMenus.detailList[this.currentSelectIndex].list) {
this.items = this.sideMenus.detailList[this.currentSelectIndex];
} else {
//不显示二级列表
this.items = false;
}
} else { //如果一级列表选中状态不正确,按第一项的的数据判断
//判断是否有二级列表
if (this.sideMenus.detailList[0].list) {
//显示空的二级列表
this.items = [];
} else {
//不显示二级列表
this.items = false;
}
}
},
//修改选项
changeSelect(index) {
//记录tabIndex
this.menu.selectIndex = this.selectIndexTab;
//记录一级列表选项
this.sideMenus.selectIndex = this.currentSelectIndex;
if (this.items) {
//确认二级列表选项
this.items.selectIndex = index;
//显示名称
this.menu.name = this.items.list[this.items.selectIndex].name;
this.menu.value = this.items.list[this.items.selectIndex].value;
} else {
//显示名称
this.menu.name = this.sideMenus.detailList[this.sideMenus.selectIndex].name;
this.menu.value = this.sideMenus.detailList[this.sideMenus.selectIndex].value;
}
this.$emit('changeSelect');
this.closeDialog();
},
// 帅选修改选项
changeRangeSelect() {
this.menu.name = '筛选';
for(var i in this.range){
if(Object.keys(this.range[i].value).length == 0){
delete this.range[i]
}
} this.menu.value = Object.keys(this.range).length > 0 ? this.range : '';
this.$emit('changeSelect');
this.closeDialog();
},
// 选择Tab菜单
clickTab(tab, index) {
if (index !== this.selectIndexTab) {
//根据选中的tab初始化数据
this.initData(index);
this.$emit('changeTab', {
tab,
index
})
}
},
// 筛选方法
clickFilterbar(v, I, i) {
v.detailList[i].selectIndex = i;
// debugger
if(!this.range[I]){
this.range[I] = {name: v.name, value: {}};
this.range[I].value[i] = v.detailList[i].value;
} else {
if(!this.range[I].value[i]){
this.range[I].value[i] = v.detailList[i].value;
} else {
delete this.range[I].value[i];
v.detailList[i].selectIndex = -1;
}
}
},
// 点击左侧列表
clickSidebar(v, i) {
if (this.currentSelectIndex !== i) {
this.currentSelectIndex = i;
//存在二级列表
if (this.sideMenus.detailList[this.currentSelectIndex].list) {
this.items = this.sideMenus.detailList[this.currentSelectIndex];
} else {
//只有一级列表,记录选项,退出
this.changeSelect();
}
this.$emit('changeMainItem', {
v,
i
});
}
},
// 点击右侧列表
clickItem(v, i) {
//只有一级列表,记录选项,退出
this.changeSelect(i);
},
// 关闭弹框
closeDialog() {
this.visible = false;
this.$emit('closeDialog');
},
// 提交已选内容
handleEnsure() {
this.changeRangeSelect();
this.$emit('changeMainItem', this.range);
// this.closeDialog();
},
// 清除已选内容
handleClean() {
this.menu.tabs.map(item => {
item.detailList.map(_item => {
_item.selectIndex = -1;
})
});
this.range = {};
}
}
}
/**
TODOS:
1. 需要一个属性去辨别帅选项
2. 多选
3. 添加多选框 */
</script> <style lang="scss">
.fade-enter-active,
.fade-leave-active {
transition: opacity .5s
}
.fade-enter,
.fade-leave-active {
opacity: 0
}
.filterbarpop-wrap {
position: fixed;
width: 100%;
top: 0;
bottom: 0;
left: 0;
overflow: hidden;
max-height: 100%;
.filterbarpop-bg {
position: fixed;
top: 0;
bottom: 0;
left: 0;
width: 100%;
background: rgba(0, 0, 0, .6);
}
.filterbarpop {
position: absolute;
width: 100%;
border-top: 1px solid #ccc;
.tab-bar {
width: 100%;
display: flex;
display: -ms-flexbox;
display: -moz-box;
display: -webkit-box;
display: -webkit-flex;
flex-directives: row;
-webkit-flex-direction: row;
align-items: center;
-webkit-align-items: center;
-webkit-box-align: center;
-moz-box-align: center;
-ms-flex-align: center;
height: 40px;
.selected {
border-bottom: 2px solid orange;
box-sizing: border-box;
}
a {
background: #fff;
height: 100%;
line-height: 40px;
text-decoration: none;
color: #323232;
text-align: center;
}
}
.main {
display: flex;
display: -webkit-flex;
flex-direction: row;
-webkit-flex-direction: row;
height: 250px;
background: #fff;
.main-sidebar {
flex: 0 0 50%;
overflow: auto;
width: 100%;
}
.full-line {
flex: 0 0 100%;
div {
text-align: left; // text-indent: 1.5em;
}
}
.item-operation {
display: inline-block;
padding: 10px 4px 10px 4px;
border: 1px solid rgb(91, 149, 255);
border-radius: 3px;
height: 0;
line-height: 1px;
}
.multi-selected {
background: rgb(91, 149, 255);
color: #fff !important;
}
.filter-item {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
padding: 13px 0 5px 10px;
span {
margin-right: 8px;
margin-bottom: 8px;
}
}
.filter-name {
padding: 10px 0 10px 10px;
}
.filter-btns {
display: flex;
display: -webkit-flex;
flex-direction: row;
-webkit-flex-direction: row;
justify-content: space-around;
-webkit-box-pack: space-around;
-moz-box-pack: space-around;
-ms-flex-pack: space-around;
position: absolute;
bottom: -40px;
width: 100%;
line-height: 40px;
z-index: 100;
background: #fff;
a {
display: block;
width: 100%;
text-align: center;
text-decoration: none;
color: #ccc;
border-top: 1px solid #ccc;
&:last-child {
background: #39f;
color: #fff;
}
}
}
.main-list {
flex: 0 0 50%;
overflow: auto;
span:active {
background: #f5f5f5;
}
}
.line-style {
.item {
text-align: left;
margin-left: 10px;
padding-left: 15px;
border-bottom: 1px solid #ccc;
position: relative;
&.selected {
color: orange;
border-color: orange;
span {
color: orange;
}
}
.checkbox {
position: absolute;
right: 50px;
top: 10px;
}
}
}
.bg-style {
.item {
background-color: #f5f5f5;
&.selected {
background-color: #FFF;
}
}
}
.item {
display: inline-block;
height: 40px;
background: #fff;
line-height: 40px;
width: 100%;
text-decoration: none;
color: #444;
span {
font-size: 14px;
color: #888;
margin-right: 10px;
vertical-align: middle;
}
&:active {
color: #fff;
}
}
}
}
}
</style>

2.页面调用

pages/FilterBarTest

<!-- 移动端筛选条件 测试页 -->
<template>
<div>
<!-- 标题栏 -->
<x-header title="移动端筛选条件 测试页"></x-header>
<!-- 内容部分 -->
<FilterBar
top="40"
:barMenus="barMenus"
@showDialog="handleShowDialog"
@closeDialog="handleCloseDialog"
@changeTab="handleChangeTab"
@changeMainItem="handleChangeMainItem"
@changeSelect="changeData">
</FilterBar>
</div>
</template> <script>
import { XHeader } from 'vux'
// 引入组件
import FilterBar from '../../components/FilterBar/FilterBar.vue'
// 引入假数据
import barMenus from './data.js'; export default {
name: 'FilterBarTest',
components: {
XHeader,
FilterBar,
},
data(){
return {
barMenus: barMenus
}
},
methods: {
handleShowDialog(v) {
// console.log(v);
},
handleCloseDialog(v) {
// console.log(v);
},
handleChangeTab(v) {
// console.log(v);
},
handleChangeMainItem(v) {
// console.log(v)
},
changeData(v) {
console.log(v);
}
}
}
</script> <style lang="scss" scoped>
//
</style>

data.js

export default [
{
name: '附近',
icon: '',
value: 'area',
showTabHeader: true,
defaultIcon: '',
selectIcon: '',
selectIndex: 0,
tabs: [
{
icon: '',
name: '商圈',
selectIndex: 0,
detailList: [
{
name: '附近',
icon: '',
selectIndex: 0,
list: [{
name: '默认',
value: 'all'
}, {
name: '500米',
value: '500'
}, {
name: '1000米',
value: '1000'
}]
},
{
name: '朝阳区',
icon: '',
selectIndex: 1,
list: [{
name: '全部',
value: 'all'
}, {
name: '建国门',
value: 'jianguomen'
}, {
name: '亚运村',
value: 'yayuncun'
}]
},
{
name: '海淀区',
icon: '',
selectIndex: 2,
list: [{
name: '全部',
value: 'all'
}, {
name: '中关村',
value: 'zhongguancun'
}, {
name: '五道口',
value: 'wudaokou'
}]
}
]
},
{
icon: '',
name: '地铁沿线',
selectIndex: 1,
detailList: [
{
name: '1号线',
icon: '',
selectIndex: 0,
list: [{
name: '平果圆',
value: 'pingguoyuan'
}, {
name: '古城',
value: 'gucheng'
}, {
name: '八角游乐园',
value: 'bajiaoyouleyuan'
}]
},
{
name: '2号线',
icon: '',
selectIndex: 1,
list: [{
name: '积水潭',
value: 'jishuitan'
}, {
name: '鼓楼大街',
value: 'guloudajie'
}, {
name: '安定门',
value: 'andingmen'
}]
},
{
name: '4号线',
icon: '',
selectIndex: 2,
list: [{
name: '安和桥北',
value: 'anheqiaobei'
}, {
name: '北宫门',
value: 'beigongmen'
}, {
name: '西宛',
value: 'xiwan'
}]
}
]
}
]
},
{
name: '菜系',
icon: '',
value: 'food',
showTabHeader: false,
defaultIcon: '',
selectIcon: '',
selectIndex: 0,
tabs: [
{
icon: '',
name: '',
selectIndex: 0,
detailList: [
{
name: '全部',
icon: '',
value: '全部',
selectIndex: 0,
list: [{
name: "全部",
value: 'all'
}]
},
{
name: '中餐馆',
icon: '',
value: '中餐馆',
selectIndex: 1,
list: [{
name: '全部',
value: 'all'
}, {
name: '火锅',
value: 'hot pot'
}, {
name: '川菜',
value: 'Sichuan cuisine'
}]
},
{
name: '西餐馆',
icon: '',
value: '西餐管',
selectIndex: 2,
list: [{
name: '全部',
value: 'all'
}, {
name: '披萨',
value: 'pizza'
}, {
name: '牛排',
value: 'steak'
}]
}
]
}
]
},
{
name: '排序',
icon: '',
value: 'compositor',
showTabHeader: false,
defaultIcon: '',
selectIcon: '',
selectIndex: 0,
tabs: [
{
icon: '',
name: '',
selectIndex: 0,
detailList: [
{
name: '只能排序',
icon: '',
value: '0',
selectIndex: 0
},
{
name: '离我最近',
icon: '',
value: '1',
selectIndex: 1
},
{
name: '评价最好',
icon: '',
value: '2',
selectIndex: 2
}
]
}
]
},
{
name: '筛选',
icon: '',
value: 'filter',
type: 'filter',
showTabHeader: false,
defaultIcon: '',
selectIcon: '',
selectIndex: 0,
tabs: [
{
icon: '',
name: '价格',
selectIndex: 0,
detailList: [
{
name: '0-50',
value: '0-50',
selectIndex: -1
},
{
name: '50-100',
value: '50-100',
selectIndex: -1
},
{
name: '100-150',
value: '100-150',
selectIndex: -1
},
{
name: '150-200',
value: '150-200',
selectIndex: -1
},
{
name: '200-250',
value: '200-250',
selectIndex: -1
},
{
name: '300-350',
value: '300-350',
selectIndex: -1
}
]
},{
icon: '',
name: '入住类型',
selectIndex: 1,
detailList: [
{
name: '不限',
value: 'all',
selectIndex: -1
}, {
name: '全日房',
value: 'daily',
selectIndex: -1
}, {
name: '钟点房',
value: 'time',
selectIndex: -1
},
{
name: '支持团购',
value: 'group buy',
selectIndex: -1
}
]
}
]
}]

3.效果图

  

.

vue 自定义 移动端筛选条件的更多相关文章

  1. 基于SqlSugar的开发框架循序渐进介绍(20)-- 在基于UniApp+Vue的移动端实现多条件查询的处理

    在做一些常规应用的时候,我们往往需要确定条件的内容,以便在后台进行区分的进行精确查询,在移动端,由于受限于屏幕界面的情况,一般会对多个指定的条件进行模糊的搜索,而这个搜索的处理,也是和前者强类型的条件 ...

  2. vue的data的数据进行指定赋值,用于筛选条件的清空,或者管理系统添加成功后给部分数据赋值为空

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. 基于Vue.js PC桌面端弹出框组件|vue自定义弹层组件|vue模态框

    vue.js构建的轻量级PC网页端交互式弹层组件VLayer. 前段时间有分享过一个vue移动端弹窗组件,今天给大家分享一个最近开发的vue pc端弹出层组件. VLayer 一款集Alert.Dia ...

  4. Vue.js 桌面端自定义滚动条组件|vue美化滚动条VScroll

    基于vue.js开发的小巧PC端自定义滚动条组件VScroll. 前段时间有给大家分享一个vue桌面端弹框组件,今天再分享最近开发的一个vue pc端自定义滚动条组件. vscroll 一款基于vue ...

  5. C# linq根据自定义筛选条件和所对应的数值进行筛选

    在软件应用中有时候会出现这样的界面:上面是利用多选框和下拉框组合的筛选条件.下面表格展示筛选后的数据.如下图 上面是筛选条件,表格是根据筛选条件筛选的结果. 如果表格不支持筛选功能.可以利用Linq对 ...

  6. vue自定义长按指令

    1.前言 在word中,当我们需要删除一大段文本的时候,我们按一下键盘上的退格键,就会删除一个字,当我们长按住退格键时,就会连续不停的删除,这就是键盘按键的长按功能.那么我们也想在网页中让一个按钮也具 ...

  7. Vue自定义指令使用场景

    当你第一次接触vue的时候,一定会使用到其中的几个指令,比如:v-if.v-for.v-bind...这些都是vue为我们写好的,用起来相当的爽.如果有些场景不满足,需要我们自己去自定义,那要怎么办呢 ...

  8. keep-alive实现返回保留筛选条件及筛选结果

    实现页面返回时,保留筛选条件和筛选结果 说明 . keep-alive 是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM 实现 结合router实现部分页面缓存 模板应用 ...

  9. vue 自定义指令(directive)实例

    一.内置指令 1.v-bind:响应并更新DOM特性:例如:v-bind:href  v-bind:class  v-bind:title  v-bind:bb 2.v-on:用于监听DOM事件: 例 ...

随机推荐

  1. c++如何使用全局变量

    在xxxx.h文件中使用extern声明变量: extern int i; 在xxxx.cpp文件中定义变量: int i; 声明和定义都只需一次.

  2. Eclipse 下载 开源项目 maven依赖丢失和 Deployment Assembly 丢失

    周末下载了最新的jeecg的源码来瞅瞅,但是下载后发现,pom文件中定义的依赖都丢失了. 如下图 上网搜索了一下啊,发现需要先给这个项目这个项目 disable maven nature 然后再添加上 ...

  3. JavaSE-03 Java选择结构

    学习要点 if选择结构 switch选择结构 if选择结构 单分支if选择结构 语法结构 应用场合 问题:如果王小强的Java考试成绩大于98分,小强就能获得一个iphone8作为奖励. 复杂条件下的 ...

  4. 关于inet_ntop、inet_pton中的n和p分别代表的意义

    函数名中的p和n非别代表表达(presentation)和数值(numeric).地址的表达格式通常是ASCII字符串,数值格式则是存放到套接字地址结构中的二进制值. 参考自:https://blog ...

  5. bzoj4951 [Wf2017]Money for Nothing

    题目描述 题解: 答案显然是$max((q-p)*(e-d))$ 依然先贪心. 对于工厂,我们倾向于$pi<pj,di<dj$的; 对于买家,我们倾向于$qi>qj,ei>ej ...

  6. phpStrom+xdebug调试php

    1>xdebug下载 1.1>xdebug官网可以根据phpinfo()源代码来提供对应版本的xdebug,地址:https://xdebug.org/wizard.php 如下截图 1. ...

  7. 快速部署jumpserver堡垒机

    jumpserver版本:Version 1.4.1-2 (社区版) 主机IP地址:10.0.0.105 准备环境1.安装依赖yum -y install wget sqlite-devel xz g ...

  8. 在docker中部署nginx

    1端口映射 大写P  为容器暴漏的所有端口进行映射   -p ,--publish-all=true    docker run -P -it centos  /bin/bash 小写p  指定哪些容 ...

  9. 在ubuntu16上搭建rabbitMQ环境

    在ubuntu16上搭建rabbitMQ环境 安装rabbitMQ apt-cache pkgnames | grep rabbitmq apt-get install rabbitmq-server ...

  10. 【HIHOCODER 1037】 数字三角形

    链接 问题描述 小Hi和小Ho在经历了螃蟹先生的任务之后被奖励了一次出国旅游的机会,于是他们来到了大洋彼岸的美国.美国人民的生活非常有意思,经常会有形形色色.奇奇怪怪的活动举办,这不,小Hi和小Ho刚 ...