vue表单筛选

目录

筛选

HTML

scss*

filterComp

排序

表格

自定义数据样式

inner-table

分页

删除

default-modal

自定义元素的插槽-占位符


.search-wrap {
  height: 60px;
  display: flex;
  align-items: center;
  overflow: hidden;
  padding: 0 20px;

  .selected-options-wrap {
    flex: 1;

    .clear-btn {
      display: inline-block;
      text-align: center;
      color: #dd2100;
      margin-left: 12px;
      padding: 0 6px;
      border-radius: 4px;
      background-color: rgba(221, 33, 0, .1);
      cursor: pointer;
    }
  }

  .mds-tag {
    padding-right: 0;
    margin-left: 8px;
    border-radius: 4px;
    border: 1px solid #d9ecff;
    cursor:default;

    .mds-btn {
      height: auto;
    }
  }

  .mds-input-search {
    width: 240px;

    ::v-deep .mds-input {
      border-radius: 4px;
    }
  }

  .filter-btn {
    margin-left: 12px;
    position: relative;
    
    .mds-btn {
      padding: 0;
      width: 32px;
      height: 32px;
    }

    .filter-count {
      width: 18px;
      height: 18px;
      line-height: 18px;
      text-align: center;
      position: absolute;
      top: -9px;
      right: -9px;
      color: #fff;
      background-color: #0364ff;
      border-radius: 50%;
    }

    .filter-icon {
      width: 28px;
      height: 28px;
      object-fit: cover;
      position: relative;
      top: 1px;
    }

    .filter-num {
      position: absolute;
      top: -10px;
      right: -2px;
      width: 16px;
      height: 16px;
      border-radius: 50%;
      background-color: #1564ff;
      color: #fff;
      font-size: 12px;
      line-height: 16px;
    }
  }
}

filterComp

<template>
  <mds-drawer
    title="条件筛选"
    :visibility="visibility"
    size="720px"
    @close="cancelFilterDrawer"
  >
    <mds-form label-width="100px" :model="filterList" label-position="right">
      <mds-form-item label="发布状态">
        <mds-select placeholder="发布状态" style="width: 100%" clearable v-model="filterList.releStat">
          <mds-option label="未发布" value="0" />
          <mds-option label="已发布" value="1" />
        </mds-select>
      </mds-form-item>
...

      <mds-form-item label="更新时间">
        <mds-date-picker
          v-model="timeArr"
          type="daterange"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          format="yyyy-MM-dd"
          value-format="yyyy-MM-dd"
          @change="changeTime"
        ></mds-date-picker>
      </mds-form-item>
    </mds-form>

    <template slot="footer">
      <mds-button @click="cancelFilterDrawer">取消</mds-button>
      <mds-button type="primary" @click="saveFilter">确认</mds-button>
    </template>
  </mds-drawer>
</template>

<script lang="ts">
import { Component, Vue, Prop } from 'vue-property-decorator'

@Component({
  components: {}
})
export default class FilterComp extends Vue {
  @Prop({ required: true }) private visibility!: boolean

  timeArr = []

  filterList: any = {
    moduTyp: '', // 模块
    releStat: "", //发布状态
    updateStartDate: '',
    updateEndDate: ''
  }

  // 修改时间
  changeTime(val: any) {
    this.filterList.updateStartDate = val ? val[0] : ''
    this.filterList.updateEndDate = val ? val[1] : ''
  }

  // 清除选项
  clearOptions(option: string) {
    if (option === 'all') {
      this.filterList = {}
      this.timeArr = []
    } else if (option === 'time') {
      this.filterList.updateStartDate = ''
      this.filterList.updateEndDate = ''
      this.timeArr = []
    } else {
      this.filterList[option] = ''
    }

    this.saveFilter()
  }

  // 取消筛选
  cancelFilterDrawer() {
    this.$emit('update:visibility', false)
  }

  // 保存筛选
  saveFilter() {
    const data = {
      ...this.filterList
    }

    this.$emit('changeFilter', data)
    this.cancelFilterDrawer()
  }
}
</script>

<mds-option label="未发布" value="0" />  string

<mds-option label="未发布" :value="0" /> number

排序

<el-table :data="tableData" header-row-class-name="table-header" @sort-change="sortChange">
....
</el-table>
 confirmpageQuery() {
    this.loading = true
    const params = {
      pageNum: this.pageInfo.currentPage,
      pageSize: this.pageInfo.pageSize,
      moduTyp: '',
      releStat: "",
      fuzzySearch: this.searchVal,
      updateStartDate: "",
      // updateEndDate: "",
      updateEndDate: "",
      ...this.filterData,
      ...this.sortProps
    }

    confirmpageQuery(params).then((res: any) => {
      if (res && res.code == 200) {
        this.pageInfo.total = res.data.totalElements
        this.tableData = res.data.data || []
        this.permissionMap = res.data.permissionMap || {}
      }
    }).catch((e: any) => {
      this.$message.error(e && e.msg)
    }).finally(() => {
      this.loading = false
    })
  }

class YourClass {
  // 定义 sortProps 对象,用于存储排序属性的状态
  sortProps: any = {
    versionNumSort: '',
    releStatSort: '',
    updateDateSort: ''
  }

  // sortChange 方法用于处理排序变化
  sortChange(arguments: any) {
    const { column, prop, order } = arguments

    // 定义 orderVal 对象,用于存储排序方式的值(升序和降序)
    const orderVal: any = {
      ascending: 1,
      descending: 0
    }

    // 定义 propName 对象,用于映射排序属性和 sortProps 对象的属性名
    const propName: any = {
      versionNum: 'versionNumSort',
      releStat: 'releStatSort',
      updTm: 'updateDateSort'
    }

    // 将 sortProps 对象中所有属性的值初始化为空,以便重新设置排序状态
    for (let key in this.sortProps) {
      this.sortProps[key] = ''
    }

    // 根据传入的排序属性和排序方式,更新 sortProps 对象中对应的属性值
    this.sortProps[propName[prop]] = orderVal[order]

    // 调用 confirmpageQuery 方法,可能是用于触发其他逻辑或执行查询等操作
    this.confirmpageQuery()
  }

  // 定义 confirmpageQuery 方法,可能是其他逻辑处理的入口
  confirmpageQuery() {
    // 在这里执行其他逻辑或查询操作
    // ...
  }
}

表格

      <el-table :data="tableData" header-row-class-name="table-header" @sort-change="sortChange">
        <!-- 展开 -->
        <el-table-column width="30" type="expand" class-name="expend-row">
          <!-- 自定义样式slot-scope="scope" {{ scope_sub.row.confmVersion }} -->
          <template slot-scope="scope">
            <el-table :data="scope.row.confmReleVOS" style="width: 100%;margin: 0;" class="inner-table">
              <!-- 缩进 -->
              <el-table-column width="30"></el-table-column>
              <el-table-column prop="confmVersion" label="版本号" width="120">
                <template slot-scope="scope_sub">
                  <div>
                    {{ scope_sub.row.confmVersion }}
                    <span v-if="scope_sub.row.isCurrentVersion" class="version-current">当前版本</span>
                  </div>
                </template>
              </el-table-column>

              <el-table-column prop="name" label="生效区间" width="220">
                <template slot-scope="scope_sub">
                  {{ scope_sub.row.effectiveDateRange }}
                </template>
              </el-table-column>

              <el-table-column prop="releName" label="发布名称" />
              <!-- show-overflow-tooltip在用户将鼠标悬停在容器上时显示一个工具提示,以显示溢出的内容 -->
              <el-table-column prop="releDesc" label="发布说明" show-overflow-tooltip />

              <el-table-column label="操作" width="150">
                <template slot-scope="scope_sub">
                  <!-- <span v-if="permissionMap.hasWorkbenchPageReleaseViewPer" class="table-operate" @click="toDetail(scope.row, scope_sub.row)">查看</span> -->
                  <span class="table-operate" @click="toDetail(scope.row, scope_sub.row)">查看</span>
                </template>
              </el-table-column>
            </el-table>
          </template>
        </el-table-column>

        <el-table-column prop="confmNm" label="数据确认版本名称" min-width="120" show-overflow-tooltip />
        <el-table-column prop="moduTyp" label="模块" width="170" />

        <el-table-column prop="releStat" label="当前状态" sortable="custom" width="120">
          <template slot-scope="scope">
            <div :class="{ 'status-published': scope.row.releStat === 1, 'status-unpublished': scope.row.releStat === 0 }">
              {{ scope.row.releStatNm }}
            </div>
            <!-- <div class="status-published" v-if="scope.row.releStat === 1">{{ scope.row.releStatNm }}</div>
            <div class="status-unpublished" v-if="scope.row.releStat === 0">{{ scope.row.releStatNm }}</div> -->
          </template>
        </el-table-column>

        <el-table-column prop="versionNum" label="版本数" sortable="custom" width="90" />
        <el-table-column prop="creator" label="创建人" width="120" />
        <el-table-column prop="updTm" label="更新时间" width="180" sortable="custom" />

        <!-- <el-table-column label="操作" width="220">
          <template slot-scope="scope">
            <span v-if="permissionMap.hasWorkbenchPageConfigEditPer" class="table-operate" @click="toEdit(scope.row)">编辑</span>
            <span v-if="permissionMap.hasWorkbenchPageConfigReleasePer" class="table-operate" @click="handlePublish(scope.row)">{{ scope.row.releStat === 0 ? '发布' : scope.row.releStat === 1 ? '再次发布' : '' }}</span>
            <span v-if="permissionMap.hasWorkbenchPageConfigDeletePer" class="table-operate" @click="handleDelete(scope.row)">删除</span>
          </template>
        </el-table-column> -->

        <el-table-column label="操作" width="220">
          <template slot-scope="scope">
            <span class="table-operate" @click="toEdit(scope.row)">编辑</span>
            <span class="table-operate" @click="handlePublish(scope.row)">{{ scope.row.releStat === 0 ? '发布' : scope.row.releStat === 1 ? '再次发布' : '' }}</span>
            <span class="table-operate" @click="handleDelete(scope.row)">删除</span>
          </template>
        </el-table-column>
      </el-table>

自定义数据样式

        <el-table-column prop="releStat" label="当前状态" sortable="custom" width="120">
          <template slot-scope="scope">
            <div :class="{ 'status-published': scope.row.releStat === 1, 'status-unpublished': scope.row.releStat === 0 }">
              {{ scope.row.releStatNm }}
            </div>
        </el-table-column>

inner-table

分页

删除

loading

 

 添加slot=footer覆盖原有样式

 

default-modal

<template>
  <mds-modal
    class="confirm-delete-modal"
    :class="{ 'confirm-delete-modal-warning': type === 'warning' }"
    :visibility="visibility"
    :title="title"
    :width="width"
    :show-close="false"
  >
    <div v-if="content" class="content">{{ content }}</div>
    <slot></slot>

    <span slot="footer" class="mds-dialog-footer">
      <mds-button @click="footActionClick('cancel')">{{ cancelText }}</mds-button>
      <mds-button
        type="primary"
        :loading="loading"
        @click="footActionClick('confirm')"
      >
        <mds-icon v-if="loading" type="line-sync" class="mds-btn-right" spin />
        {{ confirmText }}
      </mds-button>
    </span>
  </mds-modal>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator'

@Component({
  components: {}
})
export default class defaultModal extends Vue {
  @Prop({ required: true }) private visibility!: boolean
  // ! 表示非空断言,告诉 TypeScript 该属性不会为 null 或 undefined
  @Prop({ required: true }) private title!: string
  // ?: string 表示 content 是一个可选的属
  @Prop() private content?: string
  @Prop({ default: '420px' }) private width!: string
  @Prop({ default: false }) private showClose!: boolean
  @Prop({ default: '确定' }) private confirmText!: string
  @Prop({ default: '取消' }) private cancelText!: string
  @Prop({ default: 'normal' }) private type!: string
  @Prop({
    default: () => {
      return (cb: any) => {
        cb && cb()
      }
    }
  })
  private confirmCb!: any

  @Prop({
    default: () => {
      return (cb: any) => {
        cb && cb()
      }
    }
  })
  private cancelCb!: any

  private loading = false

  private loadingIns = {
    start: this.changeLoading.call(this, true),
    end: this.changeLoading.call(this, false)
  }

  private changeLoading(bool = false): any {
    return () => {
      this.loading = bool
    }
  }

  private footActionClick(type = 'cancel'): void {
    if (this.loading) return
    const cb = () => {
      this.$emit('update:visibility', false)
    }
    if (type === 'cancel') {
      this.cancelCb(cb, this.loadingIns)
    }
    if (type === 'confirm') {
      this.confirmCb(cb, this.loadingIns)
    }
  }

  private handleClose(done: any): void {
    if (this.loading) return
    this.$emit('update:visibility', false)
  }
}
</script>

<style lang="scss" scoped>
// ::v-deep .mds-modal-mask, .mds-modal-wrap {
//   z-index: 2000;
// }
.confirm-delete-modal {
  ::v-deep {
    .mds-modal-title {
      display: flex;
      align-content: center;
      // &::before {
      //   content: '\EBD2';
      //   color: #3370ff;
      //   display: inline-block;
      //   font-family: 'mdsicon';
      //   font-size: 22px;
      //   margin-right: 16px;
      // }
    }

    .mds-modal-bottom {
      border: none;
    }
  }

  .content {
    padding-left: 38px;
  }
}

.confirm-delete-modal-warning {
  // ::v-deep .mds-modal-title {
  //   &::before {
  //     content: '\EBC9';
  //     color: #f80;
  //   }
  // }

  .mds-dialog-footer {
    margin-top: 16px;
    font-size: 14px;
    text-align: right;

    // .mds-btn {
    //   font-size: 12px;
    //   height: 28px;
    //   line-height: 20px;
    //   min-width: 48px;
    //   padding: 3px 7px;
    //   color: #383c41;

    //   &:hover {
    //     background-color: #eee;
    //     border-color: #d9d9d9;
    //   }

    //   &:last-child {
    //     color: #f54a45;
    //     border-color: #f54a45;

    //     &:hover {
    //       background-color: rgb(255, 233, 233);
    //     }
    //   }
    // }

    .mds-btn-loading {
      background-color: transparent;
    }
  }
}

::v-deep .mds-modal-body {
  min-height: 0;
}
</style>

自定义元素的插槽-占位符

<!-- 自定义元素定义 -->
<custom-element>
  <h1><slot></slot></h1>
  <p>This is some default content.</p>
</custom-element>

<!-- 使用自定义元素 -->
<custom-element>
  Hello, I am inserted into the slot!
</custom-element>

 

<!-- 删除二次确认弹窗 -->
    <default-modal :visibility.sync="defaultModalInfo.visibility" :type="defaultModalInfo.type"
      :title="defaultModalInfo.title" :content="defaultModalInfo.content" :confirm-text="defaultModalInfo.confirmText"
      :cancel-text="defaultModalInfo.cancelText" :confirm-cb="defaultModalInfo.confirmCb">
      <div>
        <mds-icon type="fill-solid-exclamation-circle" style="color:#e6a23c;font-size:18px" />
        确定要删除数据吗?
      </div>
    </default-modal>
// 删除
handleDelete(row: any) {
  // 创建一个对象来设置模态框的信息
  this.defaultModalInfo = {
    visibility: true,     // 设置模态框可见性为true,即显示模态框
    type: 'warning',      // 设置模态框类型为警告,可以根据需要修改为其他类型
    title: '提示',        // 设置模态框标题为'提示'
    content: '',          // 设置模态框内容为空,可以根据需要填充具体的提示信息
    confirmText: '确定',  // 设置确认按钮文本为'确定'
    cancelText: '取消',   // 设置取消按钮文本为'取消'
    // @ts-ignore: 不可达代码错误(这里是为了忽略可能出现的编译错误,因为后面的 confirmCb 函数在当前环境下可能无法触发)
    confirmCb: (...args: any) => this.confirmDelete(row.id, ...args) // 设置确认按钮点击后的回调函数,传入当前行的id以及可能的其他参数
  };
}

// 确认删除
private async confirmDelete(id: number, cb: any, loadingIns: any) {
  // 如果loadingIns存在并且具有start方法,则调用它,用于开始加载状态
  loadingIns && loadingIns.start && loadingIns.start();

  // 调用服务器端接口执行删除操作,传入id参数
  const res: any = await confirmpageDelete(id);

  // 如果loadingIns存在并且具有end方法,则调用它,用于结束加载状态
  loadingIns && loadingIns.end && loadingIns.end();

  // 如果服务器返回结果为空或者code不等于200,则删除失败,不做任何操作
  if (!res || res.code != 200) {
    // 可以根据需要,使用某种方式显示删除失败的提示信息,这里是注释掉的代码
    // this.$message.error(res && res.msg)
    return;
  }

  // 如果传入了回调函数cb,则执行回调函数
  cb && cb();

  // 使用消息框提示删除成功
  this.$message.success('删除成功');

  // 调用刷新列表的方法,以更新数据
  this.confirmpageQuery();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/53517.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

绝对定位的遮挡

<ul class"slide-nav leftfix"><li><!-- 一级菜单 --><a href"#">手机/运营商/数码</a><!-- 二级菜单 --><div class"second-menu"></div></li><li><a href"#">电…

TCP三次握手和四次挥手以及11种状态(二)

11种状态 1、一开始&#xff0c;建立连接之前服务器和客户端的状态都为CLOSED&#xff1b; 2、服务器创建socket后开始监听&#xff0c;变为LISTEN状态&#xff1b; 3、客户端请求建立连接&#xff0c;向服务器发送SYN报文&#xff0c;客户端的状态变味SYN_SENT&#xff1b; 4、…

操作系统_进程与线程(四)

目录 4. 死锁 4.1 死锁的概念 4.1.1 死锁的定义 4.1.2 死锁产生的原因 4.1.3 死锁的处理策略 4.2 死锁预防 4.3 死锁避免 4.3.1 系统安全状态 4.3.2 银行家算法 4.3.2.1 数据结构描述 4.3.2.2 银行家算法描述 4.3.2.3 安全性算法 4.3.3 安全性算法举例 4.3.4 银行…

【网络】应用层——HTTP协议

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《网络》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; &#x1f3c0;认识HTTP协议 上篇文章中&#xff0c;本喵带着大家对HTTP有了一个初步的认识&#xff0…

大家做性能测试都用什么工具

在进行测试时&#xff0c;选择适合的测试工具至关重要&#xff0c;因为优秀的测试工具能够显著提高工作效率。对于性能测试和自动化测试而言&#xff0c;大多数人会选择传统的JMeter等工具&#xff0c;然而这些工具存在学习成本高、使用门槛高的问题。 因此&#xff0c;我在这…

Mr. Cappuccino的第52杯咖啡——Mybatis环境搭建与使用

Mybatis环境搭建与使用 Mybatis介绍Mybatis环境搭建与使用基于XML方式-原生方式开发创建数据库表项目准备项目结构项目代码实体类中添加有参构造方法产生的问题 基于XML方式-mapper代理开发项目准备项目结构项目代码SQL映射文件中namespace未设置为接口全限定名产生的问题 基于…

IO进程线程day3(2023.7.31)

一、Xmind整理&#xff1a; 文件描述符概念&#xff1a; 二、课上练习&#xff1a; 练习1&#xff1a;用fread和fwrite实现文件拷贝 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <head.h> int main(int argc, const char…

Chapter 9: Lists | Python for Everybody 讲义笔记_En

文章目录 Python for Everybody课程简介ListsA list is a sequenceLists are mutableTraversing a listList operationsList slicesList methodsDeleting elementsLists and functionsLists and stringsParsing linesObjects and valuesAliasingList argumentsDebuggingGlossar…

Windows10系统还原操作

哈喽&#xff0c;大家好&#xff0c;我是雷工&#xff01; 复制了下虚拟机的Win10系统&#xff0c;但其中有一些软件&#xff0c;想实现类似手机的格式化出厂操作&#xff0c;下面记录Windows10系统的还原操作。 一、系统环境&#xff1a; 虚拟机内的Windows10&#xff0c;64…

R730服务器用光盘安装系统(Esxi系统)

准备阶段&#xff1a;dell R730服务器&#xff0c;本教程一般适用于dell所有服务器&#xff0c;移动光盘&#xff0c;光碟做好镜像系统。在这里我安装的系统是Esxi系统&#xff0c;其他操作系统类似&#xff0c;只是安装的步骤不一样而已。 1、将系统盘插入光驱(移动光盘)&…

测试|自动化测试(了解)

测试|自动化测试&#xff08;了解&#xff09; 1.什么是自动化测试☆☆☆☆ 自动化测试相当于把人工测试手段进行转换&#xff0c;让代码执行。 2.自动化测试的分类☆☆☆☆ 注&#xff1a;这里只是常见的自动化测试&#xff0c;并不全部罗列。 1.单元自动化测试 其中Java…

3分钟学会设计模式 -- 单例模式

►单例模式 ►使用场景 在编写软件时&#xff0c;对于某些类来说&#xff0c;只有一个实例很重要。例如&#xff0c;一个系统中可以存在多个打印任务&#xff0c;但是只能有一个正在工作的任务&#xff1b;一个系统中可以多次查询数据库&#xff0c;但是只需要一个连接&#x…

Rust vs Go:常用语法对比(九)

题图来自 Golang vs Rust - The Race to Better and Ultimate Programming Language 161. Multiply all the elements of a list Multiply all the elements of the list elements by a constant c 将list中的每个元素都乘以一个数 package mainimport ( "fmt")func …

4通道高速数据采集卡推荐哪些呢

FMC141是一款基于VITA57.4标准的4通道2.8GSPS/2.5GSPS/1.6GSPS采样率16位DA播放FMC子卡&#xff0c;该板卡为FMC标准&#xff0c;符合VITA57.4与VITA57.1规范&#xff0c;16通道的JESD204B接口通过FMC连接器连接至FPGA的高速串行端口。 该板卡采用TI公司的DAC39J84芯片&#x…

重生之我要学C++第六天

这篇文章的主要内容是const以及权限问题、static关键字、友元函数和友元类&#xff0c;希望对大家有所帮助&#xff0c;点赞收藏评论支持一下吧&#xff01; 更多优质内容跳转&#xff1a; 专栏&#xff1a;重生之C启程(文章平均质量分93) 目录 const以及权限问题 1.const修饰…

DP-GAN-生成器代码

在train文件中&#xff0c;对生成器和判别器分别进行更新&#xff0c;根据loss的不同&#xff0c;分别计算对于的损失&#xff1a; loss_G, losses_G_list model(image, label, "losses_G", losses_computer)loss_D, losses_D_list model(image, label, "los…

给初学嵌入式的菜鸟一点建议.学习嵌入式linux

学习嵌入式&#xff0c;我认为两个重点&#xff0c;cpu和操作系统&#xff0c;目前市场是比较流行arm&#xff0c;所以推荐大家学习arm。操作系统很多&#xff0c;我个人对开始学习的人&#xff0c;特别不是计算机专业的&#xff0c;推荐学习ucos。那是开源的&#xff0c;同时很…

ALLEGRO之Place

本文主要讲述了ALLEGRO的Place菜单。 &#xff08;1&#xff09;Manually&#xff1a;手动放置&#xff0c;常用元器件放置方法&#xff1b; &#xff08;2&#xff09;Quickplace&#xff1a;快速放置&#xff1b; &#xff08;3&#xff09;Autoplace&#xff1a;自动放置&a…

Linux6.16 Docker consul的容器服务更新与发现

文章目录 计算机系统5G云计算第四章 LINUX Docker consul的容器服务更新与发现一、consul 概述1.什么是服务注册与发现2.什么是consul 二、consul 部署1.consul服务器2.registrator服务器3.consul-template4.consul 多节点 计算机系统 5G云计算 第四章 LINUX Docker consul的…

Linux虚拟机安装tomcat(图文详解)

目录 第一章、xshell工具和xftp的使用1.1&#xff09;xshell下载与安装1.2&#xff09;xshell连接1.3&#xff09;xftp下载安装和连接 第二章、安装tomcat1.1&#xff09;关闭防火墙&#xff0c;传输tomcat压缩包到Linux虚拟机12&#xff09;启动tomcat 第一章、xshell工具和xf…