【mars3d】基于vue3的marsgis通用UI库 mars-ui 的使用

news2024/11/18 18:39:34

一名脑残程序员的mars-ui心酸使用记录。

通过mars3d的官网我们可以看到,有配套的UI库使用,那么我们如何使用到自己的项目中呢,跟着文章一步一步来吧!

1、引入UI库

① 安装ant-design-vue

cnpm install ant-design-vue --save

② 下载基于vue开发的mars3d的源码,直通车: git clone https://gitee.com/marsgis/mars3d-vue-project.git,如下图所示,将src/components/mars-ui文件夹复制到我们的项目中,复制到src/components/文件夹下.
第一步完成
在这里插入图片描述

2、main.js配置

引入css文件,

  • 注意:mars-ui的引入要放到我们使用的UI框架ant-design-vue下面,以便于我们应用所有的mars-ui的样式(踩坑点)
......
import Antd from 'ant-design-vue'
import 'ant-design-vue/dist/antd.css'

import MarsUIInstall from '@mars/components/mars-ui'
import '@mars/components/mars-ui/common'

const app = createApp(App)
MarsUIInstall(app, {})
......

至此第二步完成

3、vite.config.js配置

① 安装vite-plugin-style-import

cnpm install vite-plugin-style-import --save

② 配置插件

export default defineConfig({
..........
	plugins: [
	    vue(),
	    mars3dPlugin(),
	    createStyleImportPlugin({
	      resolves: [AndDesignVueResolve()]
	  ],
  .......
])

③ 配置less预加载,css与plugins同级

css: {
    preprocessorOptions: {
      less: {
        javascriptEnabled: true,
        additionalData: `@import "${path.resolve(__dirname, 'src/components/mars-ui/base.less')}";`
      }
    }
  }

所以准备工作已经配置完成好了,下边开始使用。

页面使用

为了与其他UI样式做区分,所以mars-ui必须放在类名为mars-main-view下才起作用

① 修改App.vue
 <div id="mars-main-view" class="mars-main-view">
    <router-view />
  </div>
② 修改我们的页面组件
<template>
  <div id="gui-container">
    <mars-dialog :visible="true" right="10" top="100" bottom="50" width="400">
    <div class="ui-container">
      <a-form
        :model="formState"
        :rules="rules"
        :label-col="{ span: 6 }"
        :wrapper-col="{ span: 18 }">
        <a-collapse v-model:activeKey="activeKey" expandIconPosition="right">
          <a-collapse-panel key="1" header="表单控件">
            <a-form-item label="简单文本" name="url">
              <mars-input v-model:value="formState.url" :allowClear="true" @change="onTextChange" />
            </a-form-item>

            <a-form-item label="地图交互" name="extent">
              <a-row :gutter="5">
                <a-col :span="19">
                  <mars-input v-model:value="formState.extent" :allowClear="true"></mars-input>
                </a-col>
                <a-col :span="5">
                  <a-space size="small">
                    <mars-button class="small-btn" @click="onClickDrawExtent">绘制</mars-button>
                  </a-space>
                </a-col>
              </a-row>
            </a-form-item>

            <a-form-item label="数字输入">
              <mars-input-number
                v-model:value="formState.countCar"
                :step="0.1"
                @change="onNumberChange" />
            </a-form-item>

            <a-form-item label="下拉选择">
              <mars-select
                v-model:value="formState.model"
                :options="modelOptions"
                @change="onSelectChange"></mars-select>
            </a-form-item>

            <a-form-item label="日期">
              <mars-date-picker
                v-model:value="formState.date"
                format="YYYY-MM-DD"
                @change="onDateChange" />
            </a-form-item>

            <a-form-item label="滑动条">
              <mars-slider
                v-model:value="formState.brightness"
                :min="-0.5"
                :max="1.5"
                :step="0.05"
                @change="onSliderChange" />
            </a-form-item>

            <a-form-item label="刻度滑动条">
              <mars-slider
                v-model:value="formState.contrast"
                :marks="marks"
                :min="-255"
                :max="255"
                :step="1"
                @change="onMarkSliderChange" />
            </a-form-item>

            <a-form-item label="多选" class="f-push-20-t">
              <a-checkbox-group v-model:value="formState.checkboxVal" @change="onCheckboxChange">
                <a-checkbox value="mars">火星</a-checkbox>
                <a-checkbox value="earth">地球</a-checkbox>
                <a-checkbox value="sun">太阳</a-checkbox>
              </a-checkbox-group>
            </a-form-item>

            <a-form-item label="单选">
              <a-radio-group v-model:value="formState.radioVal">
                <a-radio value="1">2D</a-radio>
                <a-radio value="2">2.5D</a-radio>
                <a-radio value="3">3D</a-radio>
              </a-radio-group>
              <!-- 已选择:{{ formState.radioVal }} -->
            </a-form-item>

            <a-form-item label="鼠标操作">
              <a-space>
                <mars-switch v-model:checked="formState.isScale" @change="onSwitchChange" />
                <span>是否允许</span>
              </a-space>
            </a-form-item>

            <a-form-item label="颜色选择">
              <a-space>
                <mars-color-picker v-model:value="formState.color" />
                <div class="color-state">已选择:{{ formState.color }}</div>
              </a-space>
            </a-form-item>

            <a-form-item label="颜色选择2">
              <a-space>
                <mars-color v-model:value="formState.color" @change="showColor" />
                <div class="color-state">已选择:{{ formState.color }}</div>
              </a-space>
            </a-form-item>

            <div class="f-tac">
              <a-space>
                <mars-button size="middle" @click="onClickMessage">
                  <template #icon><mars-icon icon="alarm" class="icon-vertical-a" /></template>
                  消息
                </mars-button>
                <mars-button size="middle" @click="onClickNotify">
                  <template #icon
                    ><mars-icon icon="download-one" class="icon-vertical-a"
                  /></template>
                  提示
                </mars-button>
                <mars-button size="middle" @click="onClickAlert">
                  <template #icon
                    ><mars-icon icon="download-one" class="icon-vertical-a"
                  /></template>
                  弹窗
                </mars-button>
                <mars-button size="middle" disabled> 禁用 </mars-button>
              </a-space>
            </div>
          </a-collapse-panel>

          <a-collapse-panel key="2" header="表格控件">
            <mars-table
              size="small"
              :customRow="customTableRow"
              :row-selection="rowSelection"
              bordered
              :pagination="{ pageSize: 5 }"
              :columns="columns"
              :dataSource="typhoonList"
              rowKey="id">
              <template #bodyCell="{ column, text }">
                <template v-if="column.dataIndex === 'name'">
                  <a>{{ text }}</a>
                </template>
              </template>
            </mars-table>
          </a-collapse-panel>
          <a-collapse-panel key="3" header="树控件">
            <mars-tree
              checkable
              :tree-data="treeData"
              v-model:expandedKeys="expandedKeys"
              v-model:checkedKeys="checkedKeys"
              @check="onCheckTreeItem">
              <template #title="{ title }">
                <span>{{ title }}</span>
              </template>
            </mars-tree>
          </a-collapse-panel>
        </a-collapse>

        <div class="f-tac">
          <a-space>
            <mars-button size="middle" @click="onClickLoading">
              <template #icon><mars-icon icon="find" class="icon-vertical-a" /></template>
              进度条1
            </mars-button>
            <mars-button size="middle" @click="onClickTopLoading">
              <template #icon><mars-icon icon="planet" class="icon-vertical-a" /></template>
              进度条2
            </mars-button>
          </a-space>
        </div>
      </a-form>
    </div>
  </mars-dialog>
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref, reactive } from 'vue'
import * as mars3d from 'mars3d'
import axios from 'axios'
import { $message } from "@mars/components/mars-ui/index"
import * as mapWork from "./map.js"

const Cesium = mars3d.Cesium
let map

// onMounted(() => {
  
// })

onMounted(() => {
  initMap()
  // 访问后端接口,取台风列表数据
  const url = '//data.mars3d.cn/file/apidemo/typhoon/list_2020.json'
  axios.get(url).then(function (res: any) {
    const data = res.data
    typhoonList.value = data.typhoonList.map((item: any) => ({
      id: item[0],
      name_en: item[1],
      name_cn: item[2],
      typnumber: item[3],
      state: item[7]
    }))
  })
})


const initMap = () => {
  // 初始化 Cesium.Viewer
  var mapOptions = {
    basemaps: [{ name: '天地图', type: 'tdt', layer: 'img_d', show: true }],
    scene: {
      center: { lat: 31.786828, lng: 117.181704, alt: 3393, heading: 38, pitch: -34 }
    }
  }
  map = new mars3d.Map('gui-container', mapOptions)
}


const formState = reactive({
  url: '',
  extent: '',
  countCar: 1,
  model: '',
  date: null,
  brightness: 0,
  contrast: 128,
  checkboxVal: ['mars'],
  radioVal: '3',
  isScale: true,
  color: '#ffff00'
})

const rules = {
  url: [{ required: true, message: '请输入内容', trigger: 'blur' }]
}

// 数字输入框修改事件
const onNumberChange = () => {
  $message('您修改了数字:' + formState.countCar)
}

// 下拉列表数据
const modelOptions = [
  {
    value: 'jingche',
    label: '警车',
    style: { scale: 1, url: '//data.mars3d.cn/gltf/mars/jingche/jingche.gltf' }
  },
  {
    value: 'qiche',
    label: '小汽车',
    style: { scale: 1, url: '//data.mars3d.cn/gltf/mars/qiche.gltf' }
  },
  {
    value: 'dkc',
    label: '大卡车'
  }
]

// 下拉列表切换事件
const onSelectChange = (value: string, data: any) => {
  $message('您选择了:' + data.label)
  console.log('下拉列表切换事件', data)
}

// 日期切换事件
const onDateChange = (data: any, value: any) => {
  $message('您选择了日期:' + value)
}

// 多选框勾选事件
const onCheckboxChange = () => {
  $message('您勾选了:' + formState.checkboxVal)
  console.log('多选框勾选事件', formState.checkboxVal)
}

// 滑动条修改事件
const onSliderChange = () => {
  mapWork.updateBrightness(formState.brightness)
}

const marks: Record<number, any> = {
  '-255': '-255',
  '-125': '-125',
  0: '0',
  125: '125',
  255: '255'
}
// 带刻度滑动条修改事件
const onMarkSliderChange = () => {
  mapWork.updateContrast(formState.contrast) // 调用地图方法
}

// switch切换了
const onSwitchChange = () => {
  mapWork.enableMapMouseController(formState.isScale) // 调用地图方法
}

// 显示消息提示,自动消失
const onClickMessage = () => {
  $message('Message消息提示演示')
}

// 显示提示窗,不影响地图操作,会出现在页面右下角
const onClickNotify = async () => {
  $notify('Notify提示窗', `该窗口会出现在页面右下角,不影响地图交互操作。`)
}

// 显示遮罩提示窗,需要手动关闭
const onClickAlert = async () => {
  // $alert 返回一个Promise
  await $alert(`该窗口需要单击确定按钮进行关闭,会影响地图交互操作。`, 'Alert提示窗')

  $message('点击了确定按钮') // 异步单击确定后提示
}

// 按钮点击事件,演示loading持续三秒
const onClickLoading = async () => {
  $message('演示遮盖loading 持续三秒')

  window.$showLoading()
  setTimeout(() => {
    // 关闭loading
    window.$hideLoading()

    // 默认的信息提示
    $message('演示加载完成提示')
  }, 3000)
}

// 按钮点击事件,演示顶部不遮盖的loading
const onClickTopLoading = () => {
  $message('演示顶部不遮盖的loaing,看上面', 'warning')

  window.$showLoading('top') // top 调用出现在顶部的加载进度
  setTimeout(() => {
    window.$hideLoading('top')

    $message('演示加载失败提示', 'error')
  }, 3000)
}

// ========================= 表格控件相关处理============================

// 表格列头
const columns: TableColumnType[] = [
  {
    title: '台风编号',
    dataIndex: 'typnumber',
    key: 'typnumber'
  },
  {
    title: '台风名(中文)',
    dataIndex: 'name_cn'
  },
  {
    title: '台风名(英文)',
    dataIndex: 'name_en'
  }
]

interface typhoon {
  id: number
  name_en: string
  name_cn: string
  typnumber: string
  state: string
}
const typhoonList = ref<typhoon[]>([]) // 列表数据
onMounted(() => {
  // 访问后端接口,取台风列表数据
  const url = '//data.mars3d.cn/file/apidemo/typhoon/list_2020.json'
  axios.get(url).then(function (res: any) {
    const data = res.data
    typhoonList.value = data.typhoonList.map((item: any) => ({
      id: item[0],
      name_en: item[1],
      name_cn: item[2],
      typnumber: item[3],
      state: item[7]
    }))
  })
})

// 勾选了表格列表的行
const rowSelection: TableProps['rowSelection'] = {
  onSelect: (selectedRow: any, selectedRows: boolean) => {
    if (selectedRows) {
      $message('勾选了行:' + selectedRow.name_cn)
    } else {
      $message('取消了勾选行:' + selectedRow.name_cn)
    }
  }
}

// 点击表格列表的行
const customTableRow = (selectedRow: any) => {
  return {
    onClick: (row: any) => {
      $message('点击表格的行:' + selectedRow.name_cn)
    }
  }
}

// ========================= 树控件相关处理============================

const layersObj: any = {}
const treeData = ref<any[]>([])
const expandedKeys = ref<string[]>([])
const checkedKeys = ref<string[]>([])

function findChild(parent: any, list: any[]) {
  return list
    .filter((item: any) => item.pid === parent.id)
    .map((item: any) => {
      const node: any = {
        title: item.name,
        key: item.id,
        id: item.id,
        pId: item.pid
      }
      const nodeLayer = mapWork.createLayer(item) // 创建图层
      layersObj[item.id] = nodeLayer
      node.children = findChild(node, list)
      expandedKeys.value.push(node.key)
      if (item.isAdded && item.show) {
        checkedKeys.value.push(node.key)
      }
      return node
    })
}

// 勾选了树节点
const onCheckTreeItem = (keys: string[]) => {
  Object.keys(layersObj).forEach((k) => {
    const newKeys = keys.map((item) => {
      return String(item)
    })
    const show = newKeys.indexOf(k) !== -1
    const layer = layersObj[k]
    layer.show = show
    if (show) {
      if (!layer.isAdded) {
        mapWork.map.addLayer(layer)
      }
      layer.flyTo()
    } else {
      if (layer.isAdded) {
        mapWork.map.removeLayer(layer)
      }
    }
  })
}

</script>

<style scoped>
#gui-container {
  width: 100vw;
  height: 100vh;
}
.ui-container {
  height: 100%;
  overflow-y: scroll;
}
</style>

③ 同文件夹下添加 map.js
import * as mars3d from "mars3d"

export let map // mars3d.Map三维地图对象

// 需要覆盖config.json中地图属性参数(当前示例框架中自动处理合并)
export const mapOptions = {
  scene: {
    center: { lat: 31.823874, lng: 117.223976, alt: 3509, heading: 0, pitch: -90 }
  },
  control: {
    baseLayerPicker: false
  }
}

/**
 * 构造bloom效果对象
 * @type {mars3d.BloomEffect}
 */
let bloomEffect

// 事件对象,用于抛出事件给面板
export const eventTarget = new mars3d.BaseClass()

/**
 * 初始化地图业务,生命周期钩子函数(必须)
 * 框架在地图初始化完成后自动调用该函数
 * @param {mars3d.Map} mapInstance 地图对象
 * @returns {void} 无
 */
export function onMounted(mapInstance) {
  console.log("onMounted执行了")
  map = mapInstance // 记录首次创建的map

  // 构造bloom效果 用于滑动条测试
  bloomEffect = new mars3d.effect.BloomEffect()
  map.addEffect(bloomEffect)

  eventTarget.fire("init", {
    value: 10
  })
  queryTilesetData()
}

/**
 * 释放当前地图业务的生命周期函数
 * @returns {void} 无
 */
export function onUnmounted() {
  console.log("onUnmounted执行了")
  map.graphicLayer.clear()
  map.removeEffect(bloomEffect, true)
  bloomEffect = null
  map = null
}

// 绘制矩形(演示map.js与index.vue的交互)
export function drawExtent() {
  map.graphicLayer.clear()
  // 绘制矩形
  map.graphicLayer.startDraw({
    type: "rectangle",
    style: {
      fill: true,
      color: "rgba(255,255,0,0.2)",
      outline: true,
      outlineWidth: 2,
      outlineColor: "rgba(255,255,0,1)"
    },
    success: function (graphic) {
      const rectangle = mars3d.PolyUtil.formatRectangle(graphic._rectangle_draw)
      eventTarget.fire("drawExtent", { extent: JSON.stringify(rectangle) }) // 抛出事件,可以组件中去监听事件
    }
  })
}

// 是否运行地图鼠标交互
export function enableMapMouseController(value) {
  map.setSceneOptions({
    cameraController: {
      enableZoom: value,
      enableTranslate: value,
      enableRotate: value,
      enableTilt: value
    }
  })
}

// 调整亮度 (演示滑动条)
export function updateBrightness(val) {
  bloomEffect.brightness = val
}

// 调整对比度 (演示滑动条)
export function updateContrast(val) {
  bloomEffect.contrast = val
}

// 创建图层
export function createLayer(layer) {
  return mars3d.LayerUtil.create(layer)
}

// 数据获取
function queryTilesetData() {
  mars3d.Util.fetchJson({ url: "config/tileset.json" })
    .then(function (arr) {
      const modelData = arr.layers
      eventTarget.fire("loadTypeList", { modelData })
    })
    .catch(function (error) {
      console.log("加载JSON出错", error)
    })
}
④ 运行项目,看效果,

在这里插入图片描述
好了,已经完成mars-ui的添加了,可以继续开发了,

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何实现功能插件化

本文将介绍两种方式来实现功能插件化&#xff1a; Java SPISpring factories 在整个插件化的方案中&#xff0c;会涉及到如下 3 个组成部分&#xff1a; 插件定义&#xff08;即将插件定义为一个接口&#xff09; 插件实现&#xff08;即对插件接口的实现&#xff09; 这里…

【需求实现】输入多少就输出多少的拟合任务如何实现(二):进度条简化

文章目录 导读普通的输出方式上下求索TensorBoard是个不错的切入点与Callback参数对应的Callback方法官方的内置Callback官方进度条简单的猜测与简单的验证拼图凑齐了&#xff01; 导读 在训练模型的过程中往往会有日志一堆一堆的困扰。我并不想知道&#xff0c;因为最后我会在…

今天给大家分享几款好用的卸载神器

在日常使用电脑的过程中&#xff0c;我们经常需要安装和卸载各种软件。然而&#xff0c;有时候使用操作系统自带的卸载程序可能无法完全清除程序及其相关文件和注册表项&#xff0c;导致系统出现垃圾文件和残留问题。为了解决这个困扰&#xff0c;今天我将向大家分享几款好用的…

【Spring】基于注解方式存取JavaBean:Spring有几种注入方式?有什么区别?

前言 Hello&#xff0c;我是小黄。众所周知&#xff0c;Spring是一个开源的Java应用程序框架&#xff0c;其中包括许多通过注解实现依赖注入的功能。Spring提供了多种注入方式&#xff0c;可以满足不同的需求和场景。常见的注入方式包括构造函数注入、Setter方法注入和属性注入…

【Redis】Redis的高可用与持久化

文章目录 一、Redis 高可用1. 概念2. 高可用技术以及作用2.1 持久化2.2 主从复制2.3 哨兵2.4 集群 二、Redis 持久化1. 持久化的功能2. Redis 持久化方式 三、RDB 持久化1. 概述2. 触发条件2.1 手动触发2.2 自动触发2.3 其他自动发机制 3. 执行流程4. 启动时加载 四、AOF 持久化…

Modin 入门学习

Modin 是一个 Python 第三方库&#xff0c;用于加速 Pandas 的 API 执行速度。原始的 Pandas 是单线程执行的&#xff0c;而 Modin 则重新打包了 Pandas 里面的 API&#xff0c;使其同时在多个内核中运行&#xff0c;提高硬件性能的利用率。 使用方法很简单&#xff0c;安装 M…

2.9C++多态

C 继承扩展 C继承在实际开发中它可以帮助我们实现代码重用&#xff0c;减少代码冗余&#xff0c;提高代码的可维护性和可扩展性。 通过继承&#xff0c;我们可以从已有的类中派生出新的类&#xff0c;新的类可以继承父类的属性和方法&#xff0c;并且可以添加自己的属性和方法…

selenium元素定位---ElementClickInterceptedException(元素点击交互异常)解决方法

目录 前言&#xff1a; 1、异常原因 2、解决方法&#xff1a; 前言&#xff1a; 当使用Selenium进行元素定位和交互时&#xff0c;可能会遇到ElementClickInterceptedException&#xff08;元素点击交互异常&#xff09;的异常。这通常是由于页面上存在其他元素或弹出窗口遮…

ROS学习之基础包创建的详细流程:包括rosnode, rostopic, rosrun,roslaunch等使用

0 引言 本文旨在学习ROS基础包的从零开始创建&#xff0c;包括如何创建一个发布消息节点&#xff0c;一个接收消息节点&#xff0c;还有如何使用roslaunch同时启动多个节点&#xff0c;如何编译ROS工程包等操作。 默认已在Ubuntu系统中安装ROS机器人系统&#xff0c;比如Ubun…

AOP--拦截器

AOP应用--拦截器Spring拦截器拦截器执行流程前缀的添加统一异常处理统一数据返回格式返回String类型 AOP应用–拦截器 AOP的作用&#xff1a;统一功能处理&#xff1b;我们将以三个内容作为学习的掌握点&#xff1b;而这三点也是我们非常迫切需要的 1&#xff1a;用户登录权限…

Windows系统分区大小

Microsoft Reserved&#xff08;MSR&#xff09;——保留分区——16MB左右 EFI System Partition&#xff08;ESP&#xff09;——系统分区——100MB左右 Recovery Partition&#xff08;自起名字REP&#xff09;——恢复分区——450MB左右 其他分区——剩余

对rabbitmq进行压测

添加rabbitmq依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactI…

C# PaddleOCR标注工具

基于以下开源项目改造的 https://gitee.com/BaoJianQiang/FastOCRLabel 效果 Demo下载

CMake使用gRPC(Protobuf) 的c++ demo

gRPC的命令参数里&#xff0c; 1. 如果要用pacakge&#xff0c;需要--proto_path的参数&#xff0c; 例如helloworld.proto的绝对路径是 /home/user/grpc_demo_ws/grpc_demo/hello_world/proto/helloworld.proto 在helloworld.proto里面的pacakge是 package grpc_demo.hello_w…

同步(通信原理)

同步原理&#xff1a; 在通信系统中&#xff0c;同步是指发送端和接收端在时间上保持一致&#xff0c;使得接收端能够正确地解析和还原发送端发送的信号。同步的原理可以根据具体的通信系统和协议来区分&#xff0c;下面是几种常见的同步原理&#xff1a; 1. 时钟同步&#x…

uniapp 配置chooseLocation微信小程序腾讯地图选点

uniapp 配置chooseLocation微信小程序腾讯地图选点 场景 在uniapp中使用地图选点 搜索功能&#xff0c;回显功能&#xff0c;移动选点功能 使用到的API是uni.chooseLocation 详细看一下都有哪些属性 latitude &#xff1a;目标地纬度 Number longitude &#xff1a;目标地经度…

论文阅读: (CVPR2023 SDT )基于书写者风格和字符风格解耦的手写文字生成及源码对应

目录 引言SDT整体结构介绍代码与论文对应搭建模型部分数据集部分 总结 引言 许久不认真看论文了&#xff0c;这不赶紧捡起来。这也是自己看的第一篇用到Transformer结构的CV论文。之所以选择这篇文章来看&#xff0c;是考虑到之前做过手写字体生成的项目。这个工作可以用来合成…

浅析基于物联网技术的校园能耗智慧监控平台的设计及应用

摘 要&#xff1a;为打造低碳绿色校园&#xff0c;营造良好的学习环境&#xff0c;针对目前校园建筑能耗大&#xff0c;特别是空调节能困难等问题&#xff0c;特采用物联网技术构建校园建筑能耗智慧监控平台。通过设计空调监控子系统&#xff0c;搭建空调监控模型实现了空调等智…

在 Jetpack Compose 中使用 Snackbar

Jetpack Compose 是 Android 的现代 UI 工具库&#xff0c;提供了丰富的组件和功能来构建漂亮、交互丰富的用户界面。在本文中&#xff0c;我们将学习如何在 Jetpack Compose 中使用 Snackbar 组件来显示临时消息或操作反馈。 什么是 Snackbar&#xff1f; Snackbar 是一种用于…

基于Layui实现管理页面

基于Layui实现的后台管理页面&#xff08;仅前端&#xff09; 注&#xff1a;这是博主在帮朋友实现的一个简单的系统前端框架&#xff08;无后端&#xff09;&#xff0c;跟大家分享出来&#xff0c;可以直接将对应菜单跟html文件链接起来&#xff0c;页面使用标签页方式存在&…