zoukankan      html  css  js  c++  java
  • 报警界面

    //实时报警
    <template>
    <div style="padding:0 10px;position: relative;height:100%;">
    <div>
    <Button type="primary" @click="addRow" style="position:fixed;top:100px;z-index:100">插入信息按钮</Button>
    </div>
    <div class="conv-notificat">
    <div style="float:left;">
    <Button shape="circle" icon="md-barcode" @click="alarm_bottom_show = !alarm_bottom_show">
    <span
    :title="+stationCode ? initform.cd_station[stationCode] : ''"
    style="display:inline-block;max-160px;vertical-align: middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap"
    >{{+stationCode ? initform.cd_station[stationCode] : ''}}</span>
    今天总报警数:{{alarmNum_list.Num}}
    </Button>
    <Tag color="volcano" v-show="alarm_bottom_show">未处理数:{{alarmNum_list.unhandleNum}}</Tag>
    <Tag color="volcano" v-show="alarm_bottom_show">已处理数:{{alarmNum_list.handleNum}}</Tag>
    <Tag color="volcano" v-show="alarm_bottom_show">影响打印:{{alarmNum_list.affectNum}}</Tag>
    <Tag color="volcano" v-show="alarm_bottom_show">不影响打印:{{alarmNum_list.unaffectNum}}</Tag>
    </div>
    <div class="btn-bell" @click="HistorySearch">
    <Tooltip content="历史数据查询">
    <i class="ivu-icon ivu-icon-ios-archive" style="font-size:26px;"></i>查询
    </Tooltip>
    </div>
    <div class="btn-bell" style="position:relative;">
    <Tooltip content="筛选">
    <span @click.stop="filterIcon">
    <i
    v-bind:class="[(selStatus.name !=0 || selType.name !=0 || selStation.name !=0) ? 'color_blue' : '', 'ivu-icon', 'ivu-icon-ios-funnel']"
    style="font-size:26px;"
    ></i>筛选
    </span>
    </Tooltip>
    <transition-group name="fade">
    <div
    style="position:absolute;left:-300px;background:rgb(248, 248, 249);z-index: 1001;"
    v-show="showModel"
    :key="1"
    >
    <Card :padding="0" shadow style=" 540px;padding:4px 10px;overflow:auto;">
    <p style="line-height:30px;">
    <a href="#" class="filter_title" style="background: #2d8cf0;"></a>状态
    </p>
    <div style="line-height:0;max-height: 200px;overflow:auto;">
    <Tag
    v-for="item in alarmStatusList"
    type="dot"
    :key="item.name"
    @click.native="tagClick(item,'status')"
    :color="isCurrentTag(item,'status') ? 'success' : 'default'"
    >{{item.title}}</Tag>
    </div>
    <p style="line-height:30px;">
    <a href="#" class="filter_title" style="background: #f00;"></a>站点
    </p>
    <div style="line-height:0;max-height: 200px;overflow:auto;">
    <Tag
    v-for="item in stationList"
    type="dot"
    :key="item.name"
    @click.native="tagClick(item,'station')"
    :color="isCurrentTag(item,'station') ? 'success' : 'default'"
    >{{item.title}}</Tag>
    </div>
    <p style="line-height:30px;">
    <a href="#" class="filter_title" style="background: #19be6b;"></a>类型
    </p>
    <div style="line-height:0;max-height: 200px;overflow:auto;">
    <Tag
    v-for="item in alarmTypeList"
    type="dot"
    :key="item.name"
    @click.native="tagClick(item,'type')"
    :color="isCurrentTag(item,'type') ? 'success' : 'default'"
    >
    {{item.title}}
    <icon
    type="md-flag"
    v-show="initform.cd_EffectPrint[item.name]==1"
    title="影响打印报告"
    ></icon>
    </Tag>
    </div>
    <Divider dashed style="margin:4px 0;"/>
    <div>
    <Button type="primary" shape="circle" @click.stop="filterSearch(1)">查询</Button>
    </div>
    </Card>
    </div>
    </transition-group>
    </div>
    <div style="float: right;cursor: pointer;margin-right: 20px;">
    <Input
    search
    placeholder="按关键字检索"
    v-model="selVlpn"
    style=" 180px;margin-right:5px;margin-top:4px;"
    @on-search="vlpnSearch"
    />
    </div>
    <div class="btn-bell">
    <RadioGroup v-model="selStatus.name" type="button" @on-change="filterSearch(0)">
    <Radio :label="item.name" v-for="item in alarmStatusList" :key="item.name">
    <span>{{item.title}}</span>
    </Radio>
    </RadioGroup>
    </div>
    </div>
    <Row ref="convDiv" :gutter="8" class="conv-detail-main">
    <transition-group appear v-show="hasData" class="conv-detail">
    <Col
    :xs="12"
    :sm="8"
    :md="6"
    :lg="4"
    v-for="(item,index) in alarmList"
    :key="index"
    style="min-300px;max-500px;"
    >
    <div style="cursor:pointer;">
    <Card style="margin:5px 0;" :class="addClass(item.AlarmType,item.AlarmDeal)">
    <p slot="title">
    <span
    @click="handleClick(item)"
    :title="item.IUSTA"
    style="float:left;max-180px;font-size:15px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"
    >{{item.IUSTA}}</span>
    <Poptip
    v-show="item.AlarmDeal=='01' && initform.cd_EffectPrint[item.AlarmType]"
    placement="bottom"
    confirm
    title="是否确定发送监管指令,强制要求工控机停检?"
    @on-ok="stopCheck(item)"
    style="float:right;"
    >
    <Button type="primary" size="small" v-show="showCommand(item)" title="">停检指令</Button>
    </Poptip>
    </p>
    <div @click="handleClick(item)" class="cart-content" :height="height">
    <Row>
    <div class="cart_row">
    <Col :xs="24" :lg="8">
    <span
    :style="setVLPNColor(item.VLPNColor)"
    :title="item.VLPN"
    @click.stop="vlpnClick(item.VLPN)"
    >{{item.VLPN}}</span>
    </Col>
    <Col :xs="24" :sm="12" :lg="8">
    <span
    v-bind:class="[(item.AlarmDeal=='01' || item.IsAlarm=='0') ? 'color_red' : 'color_blue']"
    >{{item.AlarmDeal=='01' ? initform.cd_state[item.AlarmDeal] : initform.cd_isAlarm[item.IsAlarm]}}</span>
    </Col>
    </div>
    </Row>
    <Row>
    <div class="cart_row">{{item.AlarmTime | dataFormat("yyyy-MM-dd hh:mm:ss") }}</div>
    </Row>
    <Row>
    <div class="cart_row">{{initform.cd_alarmType[item.AlarmType] || ''}}</div>
    </Row>
    <Row>
    <div class="cart_row" :title="item.AlarmRecord">
    <p class="record_div" style="line-height:20px;">{{item.AlarmRecord}}</p>
    </div>
    </Row>
    </div>
    </Card>
    </div>
    </Col>
    </transition-group>
    <Col class="demo-spin-col" span="8" v-show="hasData">
    <Spin fix>
    <Icon type="ios-loading" size="18" class="demo-spin-icon-load"></Icon>
    <div>加载中</div>
    </Spin>
    </Col>
    <div v-show="!hasData" style="font-size:28px;text-align:center;">暂无数据</div>
    <Modal
    class="model_div"
    v-model="editModel"
    :title="(AlarmForm.AlarmType ? (initform.cd_alarmType[AlarmForm.AlarmType] || '') : ' ')+'——报警信息'"
    >
    <Form ref="AlarmForm" :model="AlarmForm" label-position="right" :label-width="80">
    <FormItem label="车架号:">{{AlarmForm.VIN}}</FormItem>
    <FormItem label="受理编号:">{{AlarmForm.InspectionNum}}</FormItem>
    <FormItem label="站点名称:">{{AlarmForm.IUSTA}}</FormItem>
    <FormItem label="报警内容:">{{AlarmForm.AlarmRecord}}</FormItem>
    <FormItem
    v-show="AlarmForm.AlarmDeal=='02'"
    label="处理时间:"
    >{{AlarmForm.HandleTime | dataFormat("yyyy-MM-dd hh:mm:ss")}}</FormItem>
    <FormItem
    label="是否报警:"
    v-show="AlarmForm.AlarmDeal=='02'"
    >{{initform.cd_isAlarm[AlarmForm.IsAlarm]}}</FormItem>
    <FormItem label="备注">
    <Input
    v-model="AlarmForm.Remark"
    type="textarea"
    :autosize="{minRows: 2,maxRows: 4}"
    placeholder="备注..."
    ></Input>
    </FormItem>
    </Form>
    <div slot="footer">
    <Button type="text" size="large" @click="closeModel()">取消</Button>
    <Button type="primary" size="large" v-show="hasDisabled" @click="submit()">保存</Button>
    <Button type="primary" size="large" v-show="!hasDisabled" @click="submit(1)">不报警</Button>
    <Button type="primary" size="large" v-show="!hasDisabled" @click="submit(0)">报警</Button>
    </div>
    </Modal>
    </Row>
    </div>
    </template>
    <script>
    import { getCDData } from "@/modules/exhaust/utils/utils";
    import { objDeepCopy } from "@/utils/tools";
    import config from "@/../public/config/config";
    const socket = require("socket.io-client")(config.socket_conf);
    export default {
    name: "stationalarm",
    data() {
    return {
    userInfo: this.$store.getters.getUserInfo, //登陆的用户信息
    stationCode: 0,
    alarm_bottom_show: false,
    hasData: true,
    height: 0,
    editModel: false,
    showModel: false,
    selVlpn: "",
    selStatus: { title: "全部", name: "3" }, //选中报警状态
    selType: { title: "全部", name: "0" }, //选中报警类型
    selStation: { title: "全部", name: "0" }, //选中站点
    alarmList: [],
    AlarmForm: {},
    selectData: {}, //当前选中的节点
    hasDisabled: false, //已处理则不可点击
    alarmStatusList: [
    { title: "全部", name: "0" },
    { title: "未处理", name: "1" },
    { title: "已处理", name: "2" },
    { title: "影响打印", name: "3" },
    { title: "不影响打印", name: "4" }
    ],
    alarmTypeList: [{ title: "全部", name: "0" }],
    stationList: [{ title: "全部", name: "0" }],
    initform: {
    cd_state: { "01": "未处理", "02": "已处理" },
    cd_isAlarm: { "0": "报警", "1": "不报警" },
    cd_EffectPrint: {}
    },
    alarmNum_list: {},
    dataCount: 0,
    pageSize: 30,
    pageIndex: 1 //默认当前为第一页
    };
    },
    computed: {
    showCommand() {
    return function(item){
    var limitStopTime=this.$config.limitStopTime || 10*60*1000;
    return new Date( this.$options.filters.dataFormat(item.AlarmTime,"yyyy-MM-dd hh:mm:ss")).getTime()+limitStopTime>new Date().getTime();
    }
    },
    },
    components: {},
    methods: {
    vlpnClick(vlpn) {
    this.$router.push({
    name: "hj_home_supervise",
    params: {
    searchValue: vlpn
    }
    });
    },
    stopCheck(item) {
    if(!item.StationCode) return;
    const keys=`fwd/ljfw/alarm${item.StationCode}`;
    const SceneCode=item.SceneCode;
    const value={ID:item.InspectionNum,CODE:0,INFO:item.AlarmRecord};
    //推送
    socket.emit(keys,`${SceneCode}#${JSON.stringify(value)}`);
    },
    filterIcon() {
    this.showModel = !this.showModel;
    },
    filterSearch(s) {
    this.pageSize = 30;
    this.pageIndex = 1; //默认当前为第一页
    this.alarmList = [];
    this.loadData();
    if (s) this.showModel = !this.showModel;
    },
    setVLPNColor(VLPNColor) {
    if (!this.$config.vlpn_c[VLPNColor]) return "";
    const vlpn_c = this.$config.vlpn_c[VLPNColor];
    return `display: inline-block;
    margin: -2 auto;
    border-radius: 6px;
    border-style: double;
    text-align: center;
    padding: 0px 2px;
    line-height:20px;
    background: ${vlpn_c.Background};
    color:${vlpn_c.TextColor};
    border-color:${vlpn_c.BorderColor};
    font-size: 8pt;
    overflow:hidden;
    text-overflow:ellipsis;
    white-space:nowrap`;
    },
    submit(isAlarm) {
    const _this = this;
    if (isAlarm == 0 || isAlarm == 1) {
    this.AlarmForm.AlarmDeal = "02";
    this.AlarmForm.IsAlarm = isAlarm;
    }
    const param = {
    ID: this.AlarmForm.ID,
    alarmDeal: this.AlarmForm.AlarmDeal,
    isAlarm: this.AlarmForm.IsAlarm,
    remark: this.AlarmForm.Remark,
    handle: this.$store.state.user.userInfo.userName,
    handleTime: new Date()
    };
    const url = "api/SaveAlarmData";
    this.saveInfo(url, param).then(function(res) {
    if (res.state) {
    //已处理后赋值时间和处理人
    if (_this.AlarmForm.AlarmDeal) {
    _this.AlarmForm.Handle = param.handle;
    _this.AlarmForm.HandleTime = param.handleTime;
    }

    //修改原模板视图
    let hasData = _this.alarmList.find(t => t.ID == _this.AlarmForm.ID);
    if (hasData) {
    hasData.AlarmDeal = _this.AlarmForm.AlarmDeal;
    hasData.IsAlarm = _this.AlarmForm.IsAlarm;
    hasData.Remark = _this.AlarmForm.Remark;
    hasData.Handle = _this.AlarmForm.Handle;
    hasData.HandleTime = _this.AlarmForm.HandleTime;
    }

    //if (_this.initform.cd_EffectPrint[hasData.AlarmType] == 1) //影响打印报告才减少
    if(isAlarm == 0 || isAlarm == 1) _this.$store.commit('editUnProcessAlarm',-1);
     
    _this.editModel = false;
    } else {
    _this.$Message.error("保存失败!");
    }
    });
    },
    HistorySearch() {
    this.$router.push({ name: "hj_alarm_search" });
    },
    vlpnSearch(value) {
    this.alarmList = [];
    this.selVlpn = value;
    this.loadData();
    },
    closeModel() {
    this.editModel = false;
    },
    loadCDData() {
    const _this = this;
    getCDData(this, [
    {
    tableName: "CD_AlarmType",
    columns: "CodeValue,CodeName,EffectInspectionPrint",
    where: "where IsAvailable=1 order by EffectInspectionPrint desc"
    },
    {
    tableName: "CD_FuelType",
    columns: "CodeValue,CodeName",
    where: "where IsAvailable=1"
    },
    {
    tableName: "CD_City",
    columns: "CodeValue,CodeName",
    where: "where IsAvailable=1"
    },
    {
    tableName: "StationInfo",
    columns: "StationCode as CodeValue,StationName as CodeName",
    where: ""
    }
    ]).then(function(res) {
    if (res.state) {
    const CD_Name = [
    "cd_alarmType",
    "cd_fuelType",
    "cd_city",
    "cd_station"
    ];
    res.data.map((items, index) => {
    _this.initform[CD_Name[index]] = {};
    items.forEach(item => {
    _this.initform[CD_Name[index]][item.CodeValue] = item.CodeName;
    });
    if (CD_Name[index] == "cd_alarmType") {
    items.forEach(item => {
    _this.initform.cd_EffectPrint[item.CodeValue] =
    item.EffectInspectionPrint;
    _this.alarmTypeList.push({
    title: item.CodeName,
    name: item.CodeValue
    });
    });
    }
    if (CD_Name[index] == "cd_station") {
    items.forEach(item => {
    _this.stationList.push({
    title: item.CodeName,
    name: item.CodeValue
    });
    });
    }
    });
    }
    });
    },
    loadData() {
    const _this = this;
    const param = {
    areaCode:this.userInfo.areaCode,
    dpid_admin:this.userInfo.dpid_admin,
    selStation: this.selStation.name,
    selStatus: this.selStatus.name,
    selType: this.selType.name,
    selVlpn: this.selVlpn,
    pageIndex: this.pageIndex,
    pageSize: this.pageSize,
    alarmTime: this.$options.filters.dataFormat(
    new Date(),
    "yyyy-MM-dd 00:00:00"
    )
    };
    let url = "api/getAlarmData";
    this.saveInfo(url, param).then(function(res) {
    if (res.state) {
    if (res.data.alarmList.length == 0) _this.hasData = false;
    else _this.hasData = true;

    if (res.data.alarmList.length > 0)
    _this.alarmList = _this.alarmList.concat(res.data.alarmList);
    if (res.data.dataCount.length > 0)
    _this.dataCount = res.data.dataCount[0].Num;
    if (res.data.alarm_count.length > 0)
    _this.alarmNum_list = res.data.alarm_count[0];

    //当前检测站赋值
    _this.stationCode = _this.selStation.name;
    } else {
    _this.$Message.error("查询失败!");
    }
    });
    },
    //请求封装
    saveInfo(url, param) {
    const _this = this;
    return new Promise(function(resolve, reject) {
    _this.$SkyForm
    .fxPost(url, param)
    .then(res => {
    resolve(res);
    })
    .catch(err => {
    reject(err);
    _this.$Message.error("操作失败!");
    });
    });
    },
    handleClick(item) {
    item.IsAlarm = item.IsAlarm + ""; //修改为字符串类型
    if (item.AlarmDeal == "02") this.hasDisabled = true;
    else this.hasDisabled = false;
    this.selectData = item;
    this.AlarmForm = { ...item };
    this.editModel = true;
    },
    addRow(data) {
    if(this.userInfo.dpid_admin!=0 && this.userInfo.areaCode !=''){
    if(data.AreaCode !=this.userInfo.areaCode) return;
    this.alarmList.unshift(data);
    }
    },
    addClass(AlarmType, AlarmDeal) {
    if (AlarmDeal == "02") return "alarmA";
    if (this.initform.cd_EffectPrint[AlarmType]) return "alarmB";
    else return "alarmC";
    },
    setHeight() {},
    scrollFn() {
    let isLoading = false;
    // 距离底部200px时加载一次
    let bottomOfWindow =
    document.querySelector(".conv-detail").offsetHeight -
    document.querySelector(".conv-detail-main").scrollTop -
    window.innerHeight <=
    100;
    const c_offsetHeight =
    document.querySelector(".conv-detail").offsetHeight > 0;
    if (bottomOfWindow && isLoading == false && c_offsetHeight) {
    if (this.pageIndex * this.pageSize > this.dataCount) {
    this.$Notice.info({
    title: `当前是最后一页`
    });
    return true;
    }
    this.$Notice.info({
    title: `正在加载第${this.pageIndex + 1}页`
    });

    isLoading = true;
    this.pageIndex++;
    this.loadData();
    }
    },
    throttle(func, wait, mustRun) {
    //简单的节流函数
    var timeout,
    startTime = new Date();

    return function() {
    var context = this,
    args = arguments,
    curTime = new Date();

    clearTimeout(timeout);
    // 如果达到了规定的触发时间间隔,触发 handler
    if (curTime - startTime >= mustRun) {
    func.apply(context, args);
    startTime = curTime;
    // 没达到触发间隔,重新设定定时器
    } else {
    timeout = setTimeout(func, wait);
    }
    };
    },
    isCurrentTag(item, type) {
    if (type == "status") {
    if (item.name == this.selStatus.name) return true;
    return false;
    } else if (type == "type") {
    if (item.name == this.selType.name) return true;
    return false;
    } else if (type == "station") {
    if (item.name == this.selStation.name) return true;
    return false;
    }
    },
    tagClick(item, type) {
    if (type == "status") this.selStatus = { ...item };
    else if (type == "type") this.selType = { ...item };
    else if (type == "station") this.selStation = { ...item };
    },
    subscribeSocket() {
    //订阅socket
    const _this = this;
    this.saveInfo("api/alarmSubscribe").then(function(res) {
    if (res.state) {
    socket.on("fwd/ljfw/alarm", msg => {
    _this.addRow(JSON.parse(msg));
    });
    }
    });
    },
    },
    created() {
    this.loadCDData();
    },
    mounted() {
    this.loadData();
    this.subscribeSocket();
    window.addEventListener("resize", this.setHeight);
    this.setHeight();
    document
    .querySelector(".conv-detail-main")
    .addEventListener("scroll", this.throttle(this.scrollFn, 1000, 1500));
    }
    };
    </script>
    <style scoped>
    /* loading样式 */
    .demo-spin-icon-load {
    animation: ani-demo-spin 1s linear infinite;
    }
    @keyframes ani-demo-spin {
    from {
    transform: rotate(0deg);
    }
    50% {
    transform: rotate(180deg);
    }
    to {
    transform: rotate(360deg);
    }
    }
    .demo-spin-col {
    100%;
    height: 30px;
    position: relative;
    }
    .ivu-spin-fix{
    background-color: transparent;
    }

    .v-enter,
    .v-leave-to {
    opacity: 0;
    transform: translateY(-80px);
    }
    .v-enter-active,
    .v-leave-active {
    transition: all 1s ease;
    }
    /*添加进场效果*/

    /* .v-move {
    transition: all 2s ease;
    } */
    .v-leave-active {
    position: absolute;
    }
    /*三板斧记住以后理解*/

    .fade-enter,
    .fade-leave-to {
    opacity: 0;
    }
    .fade-enter-to,
    .fade-leave {
    opacity: 1;
    }
    .fade-enter-active,
    .fade-leave-active {
    transition: all 3s;
    }

    .alarmA /deep/ .ivu-card-head {
    border-top: 3px solid #b7b7b7;
    }
    .alarmB /deep/ .ivu-card-head {
    border-top: 3px solid #ed4014;
    }

    .alarmC /deep/ .ivu-card-head {
    border-top: 3px solid #ff9900;
    }

    .filter_title {
    10px;
    height: 10px;
    background: #2d8cf0;
    margin: 0 4px;
    display: inline-block;
    border-radius: 5px;
    }

    .color_blue {
    color: #5353ff;
    }

    .color_red {
    color: #f00;
    }
    .color_green {
    color: #568000d9;
    }

    .color_yellow {
    color: #a0a011;
    }
    .cart-content {
    height: 160px;
    overflow: auto;
    }
    </style>
    <style scoped>
    /* 消息通知栏 */
    .conv-notificat {
    position: relative;
    height: 50px;
    line-height: 50px;
    padding: 0 40px;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    border-bottom: 1px solid #e6e5e6;
    background: #fff;
    }

    .conv-notificat .btn-bell {
    float: right;
    cursor: pointer;
    margin-right: 15px;
    margin-top: 12px;
    line-height: 30px;
    }

    .conv-detail-main {
    position: absolute;
    top: 50px;
    bottom: 0px;
    left: 8px;
    right: 8px;
    overflow: auto;
    background: #f3f3f3;
    }

    .conv-detail-main /deep/ .ivu-form-item-label {
    color: #a0a0a0;
    }

    .conv-detail-main /deep/ .ivu-card-head {
    border-bottom: none;
    padding: 2px 15px;
    }
    .conv-detail-main /deep/ .ivu-card-head p,
    .ivu-card-head-inner {
    line-height: 34px;
    height: 34px;
    }

    .conv-detail-main /deep/ .ivu-card-body {
    padding: 4px 10px;
    }
    .conv-detail-main /deep/ .ivu-form-item {
    margin-bottom: 0px;
    }

    .conv-detail-main /deep/ .ivu-form-item-label {
    font-size: 12px;
    padding: 6px 12px 6px 0;
    }

    .conv-detail-main /deep/ .ivu-form-item-content {
    font-size: 12px;
    line-height: 24px;
    }

    .conv-detail {
    display: block;
    overflow: hidden;
    }

    .model_div /deep/ .ivu-form-item {
    margin-bottom: 4px;
    }
    .model_div /deep/ .ivu-form-item-error-tip {
    padding-top: 0;
    }

    .record_div {
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    }

    .cart_row {
    font-size: 12px;
    line-height: 24px;
    }
    </style>
  • 相关阅读:
    微信公众账号第三方平台全网发布源码(java)- 实战测试通过
    程序员常访问的国外技术交流网站
    程序员常访问的国外技术交流网站
    程序员都怎么过端午节?
    程序员都怎么过端午节?
    程序员都怎么过端午节?
    WebApi Ajax 跨域请求解决方法(CORS实现)
    WebApi Ajax 跨域请求解决方法(CORS实现)
    WebApi Ajax 跨域请求解决方法(CORS实现)
    那个学完这个小程序创业课程的小白现在月入17万
  • 原文地址:https://www.cnblogs.com/luoguixin/p/11249264.html
Copyright © 2011-2022 走看看