• el-menu el-collapse 左右滚动联动,左右展开项联动


    需求:

    1. 左侧menu每次只保持一个子菜单的展开,右侧每次只能展开一个面板(手风琴效果)
    2. 滚动左侧的 menu 菜单,右侧的折叠面板(collapse)会跟随滚动到对应区域
    3. 滚动右侧的折叠面板,左侧的menu 菜单会跟随滚动到对应区域
    4. 展开左侧的menu 菜单,右侧的折叠面板对应的面板展开,滚动到顶部
    5. 点击左侧的 menu 子项item,右侧折叠面板中的二级菜单滚动到顶部
    6. 点击展开右侧的折叠面板,左侧对应的菜单项展开

    遇到的问题:

    1. 左侧menu 的数据获取是一个接口,右侧菜单的子项是根据左侧的一级菜单id获取,每次展开左侧右侧需要去异步获取数据填充到面板中,展开的时候数据没有填充完滚动条还未撑起来滚动位置会出错
    2. 左右侧滚动联动的时候,左侧滚动去滚动右侧,右侧滚动去设置左侧滚动,当左右两侧都设置了对方跟随自己滚动的时候,滚动时会出现卡顿,他们会互相循环调用

    解决问题:

    1. 动态计算前面有多少个兄弟节点,每个节点是固定高度,设置计算后的值
    2. 设置一个拦截标识,左侧滚动的时候禁止右侧去触发左侧的滚动;右侧滚动的时候禁止左侧去触发右侧的滚动

    效果:

    代码实现:

    menu 组件:

    1. <script>
    2. import NavItem from './NavItem.vue'
    3. import { keywordLabels } from '@/api/modules/labelMiddleware.js'
    4. export default {
    5. props: {
    6. navList: {
    7. type: Array,
    8. default: () => []
    9. },
    10. curMenuId: {
    11. type: Array
    12. }
    13. },
    14. watch: {
    15. curMenuId(arr) {
    16. // 折叠面板展开时展开对应的menu
    17. this.scrollToTarget(arr[0])
    18. }
    19. },
    20. components: {
    21. NavItem
    22. },
    23. data() {
    24. return {
    25. keyword: '',
    26. isScroll: false,
    27. // 定时器
    28. scrollTimer: null
    29. }
    30. },
    31. methods: {
    32. // 展开右侧折叠面板的时候当前menu滚动到顶部
    33. scrollToTarget(classificationId) {
    34. // 设置当前为左侧滚动标识,不触发右侧滚动
    35. window.rightScroll = true
    36. window.clearTimeout(this.scrollTimer)
    37. this.scrollTimer = setTimeout(_ => {
    38. // 放开标识
    39. window.rightScroll = false
    40. }, 800)
    41. // 找到目标元素
    42. const id = classificationId
    43. let el = this.$refs['menu_' + id][0]
    44. el = el.$el ? el.$el : el
    45. // 通过计算前面有多少元素来手动计算scrollTop高度
    46. const scrollBox = document.querySelector('#label-mid-el-menu')
    47. const children = Array.from(el.parentNode.children)
    48. const prevSiblings = []
    49. for (const child of children) {
    50. if (child === el) {
    51. break
    52. }
    53. prevSiblings.push(child)
    54. }
    55. const top = prevSiblings.length * 44
    56. this.$nextTick(_ => {
    57. scrollBox.scrollTo({
    58. top: top,
    59. behavior: 'smooth'
    60. })
    61. })
    62. },
    63. // 模糊搜索
    64. async seachData() {
    65. const { data } = await keywordLabels({
    66. keyword: this.keyword
    67. })
    68. return data
    69. },
    70. // 搜索出来选择
    71. handleSelect(label) {
    72. this.$emit('setCurIdArea', label.firstClassificationId)
    73. },
    74. // 键入关键字搜索
    75. async querySeachSync(keyworld, callback) {
    76. const data = await this.seachData()
    77. const res = data.map(item => {
    78. return {
    79. ...item,
    80. value: item.labelName
    81. }
    82. })
    83. callback(res)
    84. },
    85. // 设置菜单默认选中项为第一个
    86. setDefaultActive(list) {
    87. while (true) {
    88. if (Array.isArray(list)) {
    89. list = list[0]
    90. continue
    91. }
    92. if (list.childList && list.childList.length > 0) {
    93. list = list.childList
    94. continue
    95. }
    96. break
    97. }
    98. this.defaultActive = list.classificationId
    99. },
    100. // 点击item
    101. hanleClickNavItem(key) {
    102. },
    103. // 展开某个菜单列表
    104. handleOpenMenu(key, keyPath) {
    105. // console.log(key, keyPath, 'openMenu');
    106. this.$emit('setCurIdArea', keyPath, 'menu')
    107. },
    108. // 选择菜单列表菜单
    109. handleSelectMenu(key, keyPath) {
    110. // console.log(typeof key, keyPath, 'itemMenu')
    111. if (keyPath.length === 1) {
    112. // 菜单没有子项,触发menu
    113. this.$emit('setCurIdArea', keyPath, 'menu')
    114. } else {
    115. this.$emit('setCurIdArea', keyPath, 'item')
    116. }
    117. },
    118. // 右侧滚动的时候左侧滚动到目标位置
    119. menuScroll() {
    120. // 右侧如果正在滚动不触发左侧滚动
    121. if (window.rightScroll === true) {
    122. return
    123. }
    124. // 设置左侧正在滚动的标识,此时不触发右侧滚动
    125. window.leftScroll = true
    126. window.clearTimeout(this.scrollTimer)
    127. this.scrollTimer = setTimeout(_ => {
    128. // 左侧滚动结束,放开标识,此时才能触发右侧的滚动
    129. window.leftScroll = false
    130. }, 600)
    131. // 左侧滚动的menu
    132. const menuEl = document.querySelector('#label-mid-el-menu')
    133. // menu的滚动高度
    134. const scrollMenu = menuEl.scrollHeight - menuEl.offsetHeight
    135. // 右侧的折叠面板
    136. const labelContent = document.querySelector('.label-middleware-list-wrapper .content')
    137. // 折叠面板的滚动高度
    138. const labelScroll = labelContent.scrollHeight - labelContent.offsetHeight
    139. // 计算滚动比率
    140. const ratio = scrollMenu / labelScroll
    141. labelContent.scrollTo({
    142. top: menuEl.scrollTop / ratio
    143. })
    144. }
    145. },
    146. mounted() {
    147. this.setDefaultActive(this.navList)
    148. const menuEl = document.querySelector('#label-mid-el-menu')
    149. menuEl.addEventListener('scroll', this.menuScroll)
    150. },
    151. beforeDestroy() {
    152. const menuEl = document.querySelector('#label-mid-el-menu')
    153. menuEl.removeEventListener('scroll', this.menuScroll)
    154. }
    155. }
    156. script>
    157. <style lang="scss" scoped>
    158. .menuList {
    159. height: 100%;
    160. display: flex;
    161. flex-direction: column;
    162. padding-top: 16px;
    163. border-right: solid 1px #e6e6e6;
    164. .search-box {
    165. display: flex;
    166. align-items: center;
    167. width: 208px;
    168. height: 32px;
    169. background: #FFFFFF;
    170. border-radius: 2px;
    171. margin-left: 16px;
    172. margin-bottom: 16px;
    173. .search-input {
    174. flex: 1;
    175. margin-right: -2px;
    176. /deep/ .el-input__inner {
    177. height: 32px;
    178. line-height: 32px;
    179. border-right: none;
    180. }
    181. }
    182. .bth-search {
    183. flex: 0 0 auto;
    184. width: 32px;
    185. height: 32px;
    186. background: #E02D39;
    187. color: #fff;
    188. display: flex;
    189. align-items: center;
    190. justify-content: center;
    191. position: relative;
    192. z-index: 2;
    193. cursor: pointer;
    194. }
    195. }
    196. .el-menu {
    197. flex: 1;
    198. overflow: auto;
    199. border-right: none;
    200. /deep/ {
    201. .is-active:not(.el-submenu) {
    202. color: #e02d39;
    203. position: relative;
    204. background: #F9F9FA;
    205. font-weight: bold;
    206. &::after {
    207. content: "";
    208. position: absolute;
    209. left: 0;
    210. top: 0;
    211. width: 2px;
    212. height: 100%;
    213. background: #e02d39;
    214. }
    215. }
    216. }
    217. }
    218. }
    219. style>

    menu 里面的 item 组件:

    1. <script>
    2. export default {
    3. name: 'NavItem',
    4. props: {
    5. nav: {
    6. type: Object,
    7. default: () => {}
    8. }
    9. }
    10. }
    11. script>
    12. <style lang="scss" scoped>
    13. .el-submenu {
    14. /deep/ {
    15. .el-menu-item,
    16. .el-submenu__title {
    17. height: 44px;
    18. line-height: 44px;
    19. }
    20. // .el-submenu__title {
    21. // padding-right: 32px !important;
    22. // }
    23. // .el-submenu .el-menu-item {
    24. // padding: 0 32px;
    25. // }
    26. .is-active:not(.el-submenu) {
    27. color: #e02d39;
    28. position: relative;
    29. background: #F9F9FA;
    30. font-weight: bold;
    31. &::after {
    32. content: "";
    33. position: absolute;
    34. left: 0;
    35. top: 0;
    36. width: 2px;
    37. height: 100%;
    38. background: #e02d39;
    39. }
    40. }
    41. }
    42. }
    43. /*菜单关闭*/
    44. .el-submenu /deep/ .el-submenu__title .el-submenu__icon-arrow{
    45. -webkit-transform: rotateZ(-90deg);
    46. -ms-transform: rotate(-90deg);
    47. transform: rotateZ(-90deg);
    48. }
    49. /*菜单展开*/
    50. .el-submenu.is-opened /deep/ .el-submenu__title .el-submenu__icon-arrow{
    51. -webkit-transform: rotateZ(0deg);
    52. -ms-transform: rotate(0deg);
    53. transform: rotateZ(0deg);
    54. }
    55. style>

    右侧的 collapse LabelList 组件:

    1. <script>
    2. import { queryLabels } from '@/api/modules/labelMiddleware.js'
    3. import PopoverLabel from './PopoverLabel.vue'
    4. export default {
    5. components: {
    6. PopoverLabel
    7. },
    8. props: {
    9. navList: {
    10. type: Array,
    11. default: () => []
    12. },
    13. selectedLabels: {
    14. type: Array,
    15. default: () => []
    16. },
    17. curIdArea: {
    18. type: Array,
    19. defaut: () => []
    20. },
    21. curAreaType: {
    22. type: String
    23. }
    24. },
    25. data() {
    26. return {
    27. loading: false,
    28. activeItem: 'org',
    29. labelList: [],
    30. childLabels: [],
    31. popoverVisible: {},
    32. // 定时器
    33. scrollTimer: null
    34. }
    35. },
    36. watch: {
    37. // 展开当前区域
    38. async curIdArea(keyPath) {
    39. const classificationId = keyPath[0]
    40. this.activeItem = isNaN(classificationId) ? classificationId : Number(classificationId)
    41. // 如果左侧是展开的菜单
    42. if (this.curAreaType === 'menu') {
    43. await this.openCollapse(classificationId)
    44. this.scrollToTarget()
    45. }
    46. // 如果左侧是点击的item
    47. if (this.curAreaType === 'item') {
    48. const curItemId = keyPath[keyPath.length - 1]
    49. this.scrollToItem(curItemId)
    50. }
    51. }
    52. },
    53. methods: {
    54. // 滚动到目标位置, 点击navItem时
    55. scrollToItem(navId) {
    56. // 设置当前为左侧滚动标识,不触发右侧滚动
    57. window.leftScroll = true
    58. window.clearTimeout(this.scrollTimer)
    59. this.scrollTimer = setTimeout(_ => {
    60. // 放开标识
    61. window.leftScroll = false
    62. }, 800)
    63. let el = this.$refs['collapse_sub_' + navId][0]
    64. el = el.$el ? el.$el : el
    65. const scrollBox = document.querySelector('.label-middleware-list-wrapper .content')
    66. this.$nextTick(_ => {
    67. scrollBox.scrollTo({
    68. top: el.offsetTop - 8,
    69. behavior: 'smooth'
    70. })
    71. })
    72. },
    73. // 滚动到目标位置, 展开menu时
    74. scrollToTarget(classificationId) {
    75. // 设置当前为右侧滚动标识,不触发左侧滚动
    76. window.leftScroll = true
    77. window.clearTimeout(this.scrollTimer)
    78. this.scrollTimer = setTimeout(_ => {
    79. // 放开标识
    80. window.leftScroll = false
    81. }, 800)
    82. // 找到目标元素
    83. const id = classificationId ?? this.curIdArea
    84. let el = this.$refs['collapse_' + id][0]
    85. el = el.$el ? el.$el : el
    86. while (el) {
    87. if (!el.classList.contains('el-collapse-item')) {
    88. el = el.parentNode
    89. } else {
    90. break
    91. }
    92. }
    93. // 通过计算前面有多少元素来手动计算scrollTop高度
    94. const scrollBox = document.querySelector('.label-middleware-list-wrapper .content')
    95. const children = Array.from(el.parentNode.children)
    96. const prevSiblings = []
    97. for (const child of children) {
    98. if (child === el) {
    99. break
    100. }
    101. prevSiblings.push(child)
    102. }
    103. const top = prevSiblings.length * 48
    104. this.$nextTick(_ => {
    105. scrollBox.scrollTo({
    106. top: top,
    107. behavior: 'smooth'
    108. })
    109. })
    110. },
    111. // 添加标签addLabels
    112. addLabels(label) {
    113. this.$emit('addLabels', label)
    114. },
    115. // 关闭popover
    116. closePopover() {
    117. for (let item in this.popoverVisible) {
    118. this.popoverVisible[item] = false
    119. }
    120. },
    121. // 展示特定的popover
    122. showPopover(item) {
    123. this.popoverVisible[item] = true
    124. },
    125. // 获取label列表
    126. async getLabels() {
    127. try {
    128. this.loading = true
    129. const { data } = await queryLabels({
    130. classificationId: Array.isArray(this.activeItem) ? this.activeItem[this.activeItem.length - 1] : this.activeItem
    131. })
    132. this.childLabels = data
    133. this.loading = false
    134. const target = this.labelList.find(item => item.classificationId === this.activeItem)
    135. // 设置数据结构
    136. data.forEach(item => {
    137. if (item.labList) {
    138. item.labList.forEach(label => {
    139. // 最终值
    140. label.tagAttributes = []
    141. label.curRanges = []
    142. // 临时修改的值,点击确定后才赋值给最终的值
    143. label.tempTagAttributes = []
    144. label.tempCurRanges = []
    145. })
    146. }
    147. })
    148. if (target) {
    149. this.$set(target, 'children', data)
    150. }
    151. } catch (err) {
    152. console.log(err)
    153. }
    154. },
    155. // 设置机构标签
    156. async setOrgLabels(id) {
    157. const target = this.labelList.find(() => id === this.activeItem)
    158. const data = [{
    159. classificationId: 'org',
    160. classificationName: "组织机构",
    161. labList: [
    162. {
    163. labelId: "org_label",
    164. labelName: "中台机构",
    165. labelPropType: "org_label",
    166. labelPropList: [],
    167. labelRuleDescription: "",
    168. selected: false,
    169. tagAttributes: [],
    170. curRanges: [],
    171. value: "",
    172. orgLabel: ''
    173. }
    174. ],
    175. selected: false
    176. }]
    177. if (target) {
    178. this.$set(target, 'children', data)
    179. }
    180. },
    181. // 折叠面板展开设置数据
    182. async openCollapse(id) {
    183. if (id) {
    184. // 初始化手动添加的组织机构
    185. if (id === 'org') {
    186. await this.setOrgLabels('org')
    187. } else {
    188. // 获取当前详细labels
    189. await this.getLabels()
    190. }
    191. }
    192. },
    193. // 展开关闭collapse
    194. async handleChangeCollapse(id) {
    195. if (id) {
    196. await this.openCollapse(id)
    197. // 当前展开项的第0或者第一个子元素,由于左侧没有本身子元素所以设为第一个
    198. let classificationId = (this.childLabels[1]?.classificationId ?? this.childLabels[0]?.classificationId) || ''
    199. // 组织机构是手动添加的数据单独处理
    200. classificationId = id === 'org' ? 'org_label' : classificationId
    201. this.$emit('changeCollapse', [String(id), String(classificationId) || String(id)])
    202. // 先将右侧滚动到目标位置
    203. this.scrollToTarget(id)
    204. // 左侧滚动到目标位置
    205. this.labelListScroll()
    206. }
    207. },
    208. // 右侧滚动的时候左侧滚动到目标位置
    209. labelListScroll() {
    210. // 左侧如果正在滚动不触发右侧滚动
    211. if (window.leftScroll === true) {
    212. return
    213. }
    214. // 设置右侧正在滚动的标识,此时不触发左侧滚动
    215. window.rightScroll = true
    216. window.clearTimeout(this.scrollTimer)
    217. this.scrollTimer = setTimeout(_ => {
    218. // 右侧滚动结束,放开标识,此时才能触发左侧的滚动
    219. window.rightScroll = false
    220. }, 600)
    221. // 左侧滚动的menu
    222. const menuEl = document.querySelector('#label-mid-el-menu')
    223. // menu的滚动高度
    224. const scrollMenu = menuEl.scrollHeight - menuEl.offsetHeight
    225. // 右侧的折叠面板
    226. const labelContent = document.querySelector('.label-middleware-list-wrapper .content')
    227. // 折叠面板的滚动高度
    228. const labelScroll = labelContent.scrollHeight - labelContent.offsetHeight
    229. // 计算滚动比率
    230. const ratio = scrollMenu / labelScroll
    231. menuEl.scrollTo({
    232. top: labelContent.scrollTop * ratio
    233. })
    234. }
    235. },
    236. mounted() {
    237. const labelContent = document.querySelector('.label-middleware-list-wrapper .content')
    238. labelContent.addEventListener('scroll', this.labelListScroll)
    239. },
    240. beforeDestroy() {
    241. const labelContent = document.querySelector('.label-middleware-list-wrapper .content')
    242. labelContent.removeEventListener('scroll', this.labelListScroll)
    243. },
    244. created() {
    245. this.labelList = this.navList
    246. this.openCollapse(this.activeItem)
    247. }
    248. }
    249. script>
    250. <style lang="scss" scoped>
    251. .label-middleware-list-wrapper {
    252. height: 100%;
    253. .content {
    254. height: 100%;
    255. overflow: auto;
    256. }
    257. .el-collapse {
    258. position: relative;
    259. }
    260. .el-collapse-item /deep/ .el-collapse-item__content {
    261. border-top: 1px solid #EBEEF5;
    262. padding-bottom: 0;
    263. }
    264. /deep/ .el-collapse-item__header{
    265. font-size: 14px;
    266. font-family: PingFangSC-Regular, PingFang SC;
    267. font-weight: 500;
    268. color: #262626;
    269. }
    270. .sub-box {
    271. padding: 8px 16px 0 12px;
    272. background: #FAFAFA;
    273. .sub-title {
    274. height: 18px;
    275. font-size: 13px;
    276. font-family: PingFangSC-Regular, PingFang SC;
    277. font-weight: 400;
    278. color: #292B33;
    279. line-height: 18px;
    280. margin-bottom: 9px;
    281. }
    282. .label-box {
    283. display: flex;
    284. /deep/ .label-item {
    285. white-space: nowrap;
    286. display: flex;
    287. align-items: center;
    288. height: 28px;
    289. padding: 0 8px;
    290. background: #F1F1F1;
    291. border-radius: 3px;
    292. font-size: 12px;
    293. font-family: PingFangSC-Regular, PingFang SC;
    294. font-weight: 400;
    295. color: #595959;
    296. margin-right: 8px;
    297. margin-bottom: 8px;
    298. cursor: pointer;
    299. }
    300. }
    301. }
    302. }
    303. style>

     menu 和 右侧的 LbelList 组件的父组件:

    1. <script>
    2. import NavList from './NavList.vue'
    3. import LabelList from './LabelList.vue'
    4. import { getClassificationTree } from '@/api/modules/labelMiddleware.js'
    5. export default {
    6. components: {
    7. NavList,
    8. LabelList
    9. },
    10. props: {
    11. visible: {
    12. type: Boolean,
    13. default: false
    14. },
    15. selectedLabels: {
    16. type: Array,
    17. default: () => []
    18. },
    19. total: {
    20. type: Number
    21. },
    22. renderLabelInfo: {
    23. type: Function,
    24. default: () => () => {}
    25. }
    26. },
    27. data() {
    28. return {
    29. navList: [],
    30. search: '',
    31. curIdArea: [],
    32. // 左侧选中的type,展开还是点击item
    33. curAreaType: '',
    34. curMenuId: ['org', 'org_label']
    35. }
    36. },
    37. methods: {
    38. // 添加label
    39. addLabels(label) {
    40. this.$emit('addLabels', label)
    41. },
    42. // 删除label
    43. deleteLabel(label, index) {
    44. this.$emit('deleteLabel', label, index)
    45. },
    46. // 左侧菜单当前展开项
    47. setCurIdArea(keyPath, type) {
    48. this.curIdArea = keyPath
    49. this.curAreaType = type
    50. },
    51. // 获取navList,左侧的menu菜单数据,右侧的面板一级数据
    52. async getNavList() {
    53. const { data } = await getClassificationTree()
    54. this.navList = data || []
    55. this.navList.unshift({
    56. classificationId: 'org',
    57. classificationName: "组织机构",
    58. childList: [
    59. {
    60. childList: null,
    61. classificationId: 'org_label',
    62. classificationName: "组织机构"
    63. }
    64. ]
    65. })
    66. },
    67. // 点击清空重选
    68. handleClickClearAll() {
    69. this.$emit('resetSelectLabels')
    70. },
    71. // 点击确定
    72. handleClickSubmit() {
    73. this.$emit('getTableData')
    74. this.handleClose()
    75. },
    76. // 关闭dialog
    77. handleClose() {
    78. this.$emit('closeDialog')
    79. },
    80. // 修改了折叠面板,设置当前展开想的父级和当前id
    81. changeCollapse(idArr) {
    82. this.curMenuId = idArr
    83. }
    84. },
    85. mounted() {
    86. this.getNavList()
    87. }
    88. }
    89. script>
    90. <style lang="scss" scoped>
    91. .dialog {
    92. /deep/ .el-dialog{
    93. margin-top: 8vh !important;
    94. }
    95. /deep/ .el-dialog__body {
    96. padding: 0;
    97. }
    98. .left-nav {
    99. height: 100%;
    100. width: 240px;
    101. }
    102. .content {
    103. display: flex;
    104. border: 1px solid rgba(0, 0, 0, 0.1);
    105. border-right: none;
    106. border-left: none;
    107. margin-bottom: 8px;
    108. height: 556px;
    109. padding: 0;
    110. padding-right: 16px;
    111. .label-collapse {
    112. flex: 1;
    113. overflow: auto;
    114. /deep/ {
    115. .el-collapse-item__header {
    116. padding-left: 20px;
    117. }
    118. }
    119. }
    120. }
    121. .selected-label {
    122. margin-bottom: 18px;
    123. padding: 0 16px;
    124. .title {
    125. height: 20px;
    126. font-size: 14px;
    127. font-family: PingFangSC-Medium, PingFang SC;
    128. font-weight: 500;
    129. color: #262626;
    130. line-height: 20px;
    131. margin-bottom: 12px;
    132. }
    133. .labels-box {
    134. display: flex;
    135. min-height: 50px;
    136. max-height: 76px;
    137. overflow: auto;
    138. flex: 1;
    139. flex-wrap: wrap;
    140. .label-item {
    141. display: flex;
    142. align-items: center;
    143. height: 28px;
    144. background: rgba(224, 45, 57, 0.06);
    145. border-radius: 3px;
    146. padding: 4px 11px 4px 8px;
    147. margin-right: 8px;
    148. margin-bottom: 8px;
    149. white-space: nowrap;
    150. .text {
    151. display: flex;
    152. align-items: center;
    153. white-space: nowrap;
    154. font-size: 14px;
    155. font-family: PingFangSC-Regular, PingFang SC;
    156. font-weight: 400;
    157. color: #595959;
    158. margin-right: 24px;
    159. .value-item:not(:last-child){
    160. margin-right: 8px;
    161. }
    162. }
    163. .delete-label {
    164. color: #8C8C8C;
    165. cursor: pointer;
    166. font-size: 16px;
    167. }
    168. }
    169. }
    170. }
    171. .footer {
    172. display: flex;
    173. justify-content: space-between;
    174. align-items: center;
    175. .tip {
    176. font-size: 12px;
    177. font-family: PingFangSC-Regular, PingFang SC;
    178. font-weight: 400;
    179. color: #595959;
    180. line-height: 17px;
    181. .number {
    182. font-size: 12px;
    183. font-family: PingFangSC-Regular, PingFang SC;
    184. font-weight: 400;
    185. color: #E02D39;
    186. line-height: 17px;
    187. padding: 0 4px;
    188. }
    189. }
    190. .buttons {
    191. display: flex;
    192. align-items: center;
    193. .btn-reset {
    194. width: 72px;
    195. height: 28px;
    196. display: flex;
    197. align-items: center;
    198. justify-content: center;
    199. border-radius: 3px;
    200. border: 1px solid #E02D39;
    201. font-size: 12px;
    202. font-family: PingFangSC-Medium, PingFang SC;
    203. font-weight: 500;
    204. color: #E02D39;
    205. margin-right: 8px;
    206. cursor: pointer;
    207. }
    208. .btn-confirm {
    209. height: 28px;
    210. display: flex;
    211. align-items: center;
    212. justify-content: center;
    213. width: 60px;
    214. background: #E02D39;
    215. border-radius: 3px;
    216. font-size: 12px;
    217. font-family: PingFangSC-Medium, PingFang SC;
    218. font-weight: 500;
    219. color: #FFFFFF;
    220. cursor: pointer;
    221. }
    222. }
    223. }
    224. }
    225. style>

  • 相关阅读:
    SQLite表添加主键
    SQL Server基础指令(创建与检索)
    泛微E9,独立选择框对应数据库表查询
    RT-Thread移植到STM32单片机过程
    Docker 实用操作文档
    数据结构-红黑树
    【leetcode】有效的回文
    RabbitMQ【RabbitMQ】
    人工智能学习与实训笔记(四):神经网络之NLP基础—词向量
    js serialport 串口通讯
  • 原文地址:https://blog.csdn.net/MFWSCQ/article/details/126381359