HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

基于flutter3.32仿微信app聊天模板

flutter

flutter3-chat:基于最新跨平台技术flutter3.32+dart3.8+get_storage+photo_view+toast搭建仿微信App界面聊天项目。包含聊天、通讯录、我的、朋友圈模块。实现发送图文消息、gif大图、长按仿微信语音操作面板、图片预览、红包/朋友圈等功能。

使用技术

  • 框架技术:Flutter3.32+Dart3.8
  • 组件库:material-design3
  • 弹窗组件:showDialog/SimpleDialog/showModalBottomSheet/AlertDialog
  • 图片预览:photo_view^0.15.0
  • 存储组件:get_storage^2.1.1
  • 下拉刷新:easy_refresh^3.4.0
  • toast提示:toast^0.3.0
  • 网址预览组件:url_launcher^6.3.1

项目框架目录

flutter3-chat聊天app模板已经更新到我的原创作品集。

flutter3.32+dart3.8跨平台仿微信聊天app应用

如果想要了解更多项目实现情况,可以去看看下面这篇文章。
最新版Flutter3.32+Dart3.8跨平台仿微信app聊天界面|朋友圈

热文推荐

最新版uniapp+vue3+uv-ui跨三端短视频+直播+聊天【H5+小程序+App端】
原创uniapp+vue3+deepseek+uv-ui跨端实战仿deepseek/豆包流式ai聊天对话助手。
vue3-webseek网页版AI问答|Vite6+DeepSeek+Arco流式ai聊天打字效果
Electron35-DeepSeek桌面端AI系统|vue3.5+electron+arco客户端ai模板
uniapp+vue3聊天室|uni-app+vite4+uv-ui跨端仿微信app聊天语音/朋友圈
uniapp+vue3酒店预订|vite5+uniapp预约订房系统模板(h5+小程序+App端)
Electron32-Vue3OS桌面版os系统|vue3+electron+arco客户端OS管理模板
tauri2.0-admin桌面端后台系统|Tauri2+Vite5+ElementPlus管理后台EXE程序
Tauri2.0+Vite5聊天室|vue3+tauri2+element-plus仿微信|tauri聊天应用

继续阅读 »

flutter3-chat:基于最新跨平台技术flutter3.32+dart3.8+get_storage+photo_view+toast搭建仿微信App界面聊天项目。包含聊天、通讯录、我的、朋友圈模块。实现发送图文消息、gif大图、长按仿微信语音操作面板、图片预览、红包/朋友圈等功能。

使用技术

  • 框架技术:Flutter3.32+Dart3.8
  • 组件库:material-design3
  • 弹窗组件:showDialog/SimpleDialog/showModalBottomSheet/AlertDialog
  • 图片预览:photo_view^0.15.0
  • 存储组件:get_storage^2.1.1
  • 下拉刷新:easy_refresh^3.4.0
  • toast提示:toast^0.3.0
  • 网址预览组件:url_launcher^6.3.1

项目框架目录

flutter3-chat聊天app模板已经更新到我的原创作品集。

flutter3.32+dart3.8跨平台仿微信聊天app应用

如果想要了解更多项目实现情况,可以去看看下面这篇文章。
最新版Flutter3.32+Dart3.8跨平台仿微信app聊天界面|朋友圈

热文推荐

最新版uniapp+vue3+uv-ui跨三端短视频+直播+聊天【H5+小程序+App端】
原创uniapp+vue3+deepseek+uv-ui跨端实战仿deepseek/豆包流式ai聊天对话助手。
vue3-webseek网页版AI问答|Vite6+DeepSeek+Arco流式ai聊天打字效果
Electron35-DeepSeek桌面端AI系统|vue3.5+electron+arco客户端ai模板
uniapp+vue3聊天室|uni-app+vite4+uv-ui跨端仿微信app聊天语音/朋友圈
uniapp+vue3酒店预订|vite5+uniapp预约订房系统模板(h5+小程序+App端)
Electron32-Vue3OS桌面版os系统|vue3+electron+arco客户端OS管理模板
tauri2.0-admin桌面端后台系统|Tauri2+Vite5+ElementPlus管理后台EXE程序
Tauri2.0+Vite5聊天室|vue3+tauri2+element-plus仿微信|tauri聊天应用

收起阅读 »

uniapp-x 官方文档 UTSActivityCallback 示例有误

uni-app-x

大标题

官方链接 :https://doc.dcloud.net.cn/uni-app-x/uts/utsactivitycallback.html#UniActivityKeyEventCallback

uvue代码部分缺少变量 cbText,新建 uni_modules插件不能以uts开头,即示例中的 uts-syntaxcase 不可以以这个命名,将其改为 muts-syntaxcase

uts代码代码缺少所有需要引入的库,除了内置库。

缺少以下库

import Bundle from "android.os.Bundle"  
import KeyEvent from "android.view.KeyEvent"  
import WindowManager from "android.view.WindowManager"   
import Menu from "android.view.Menu"  
import ActionMode from "android.view.ActionMode"  
import Configuration from "android.content.res.Configuration"  
import KeyboardShortcutGroup from "android.view.KeyboardShortcutGroup";

完整代码

------uvue页面代码------

<template>  
    <!-- #ifdef APP-ANDROID -->  
    <scroll-view style="flex: 1">  
        <view>  
            <view class="uni-padding-wrap uni-common-mt">  
                <view class="text-box" scroll-y="true">  
                    <text>{{ text }}</text>  
                </view>  
            </view>  
            <button @tap="activityCallback">注册activity 回调方法</button>  
            <view class="uni-padding-wrap uni-common-mt">  
                <view class="uni-hello-text">  
                    点击注册activity 回调方法后,可以手动切换其他APP再返回,可在控制台和界面观察事件日志  
                </view>  
            </view>  
            <view class="uni-padding-wrap uni-common-mt">  
                <view class="text-box" scroll-y="true">  
                    <text>{{ cbText }}</text>  
                </view>  
            </view>  
            <button @tap="unRegActivityCallback">取消注册activity 回调方法</button>  
        </view>  
    </scroll-view>  
    <!-- #endif -->  
</template>  

<script>  
    // #ifdef APP-ANDROID  
    import {  
        UTSAcvitiyLifeCycleCallback,  
        UTSAcvitiyKeyEventCallback,  
        UTSActivityWindowCallback,  
        UTSActivityCallback,  
        UTSActivityComponentCallback,  
        onCallbackChange  
    } from '@/uni_modules/muts-syntaxcase'  
    // #endif  

    import File from 'java.io.File';  
    import Intent from 'android.content.Intent';  

    export default {  
        data() {  
            return {  
                text: '',  
                cbText: "" as string,  
                callback: [] as Any[]  
            }  
        },  
        unmounted() {  
            // #ifdef APP-ANDROID  
            this.unRegActivityCallback()  
            // #endif  

        },  
        methods: {  
            // #ifdef APP-ANDROID  
            // #ifdef UNI-APP-X  
            activityCallback() {  
                var that = this  
                onCallbackChange(function (eventLog : string) {  
                    // 展示捕捉到的声明周期日志  
                    let nextLine = that.cbText + eventLog  
                    that.cbText = nextLine  
                    let nextLineFlag = that.cbText + '\n'  
                    that.cbText = nextLineFlag  
                })  
                let index = getCurrentPages().length - 1  
                let page = getCurrentPages()[index]  
                console.log('page route=' + page.route)  
                this.callback.push(new UTSAcvitiyLifeCycleCallback())  
                this.callback.push(new UTSActivityWindowCallback())  
                this.callback.push(new UTSAcvitiyKeyEventCallback())  
                this.callback.push(new UTSActivityCallback(), page.route)  
                this.callback.push(new UTSActivityComponentCallback())  
                this.callback.forEach((value) => {  
                    if (value instanceof UTSAcvitiyLifeCycleCallback) {  
                        UTSAndroid.onActivityCallback(value, page.route)  
                    }  
                    if (value instanceof UTSActivityWindowCallback) {  
                        UTSAndroid.onActivityCallback(value)  
                    }  
                    if (value instanceof UTSAcvitiyKeyEventCallback) {  
                        UTSAndroid.onActivityCallback(value)  
                    }  
                    if (value instanceof UTSActivityCallback) {  
                        UTSAndroid.onActivityCallback(value)  
                    }  
                    if (value instanceof UTSActivityComponentCallback) {  
                        UTSAndroid.onActivityCallback(value)  
                    }  

                })  
            },  
            unRegActivityCallback() {  
                this.callback.forEach((value) => {  

                    if (value instanceof UTSAcvitiyLifeCycleCallback) {  
                        UTSAndroid.offActivityCallback(value)  
                    }  
                    if (value instanceof UTSActivityWindowCallback) {  
                        UTSAndroid.offActivityCallback(value)  
                    }  
                    if (value instanceof UTSAcvitiyKeyEventCallback) {  
                        UTSAndroid.offActivityCallback(value)  
                    }  
                    if (value instanceof UTSActivityCallback) {  
                        UTSAndroid.offActivityCallback(value)  
                    }  
                    if (value instanceof UTSActivityComponentCallback) {  
                        UTSAndroid.offActivityCallback(value)  
                    }  
                })  
            }  
            // #endif  
            // #endif  
        },  
    }  
</script>

------uts代码------

代码位置:uni_modules/muts-syntaxcase/utssdk/app-android/index.uts

let callback : (eventLog : string) => void = (res) => { };  

export function onCallbackChange(fn : (eventLog : string) => void) {  
    callback = fn  
}  
import Bundle from "android.os.Bundle"  
import KeyEvent from "android.view.KeyEvent"  
import WindowManager from "android.view.WindowManager"   
import Menu from "android.view.Menu"  
import ActionMode from "android.view.ActionMode"  
import Configuration from "android.content.res.Configuration"  
import KeyboardShortcutGroup from "android.view.KeyboardShortcutGroup";  
export class UTSAcvitiyLifeCycleCallback extends UniActivityLifeCycleCallback {  
    constructor() {  
        super()  
    }  
    override onCreate(params : UniActivityParams, savedInstanceState : Bundle | null) {  
        console.log('UTSAcvitiyLifeCycle', 'onCreate', savedInstanceState)  
        callback('onCreate')  
    }  

    override onResume(params : UniActivityParams) {  
        console.log('UTSAcvitiyLifeCycle', 'onResume', params)  
        callback('onResume')  
    }  
    override onPreResume(params : UniActivityParams) {  
        console.log('UTSAcvitiyLifeCycle', 'onPreResume', params)  
        callback('onPreResume')  
    }  
    override onStart(params : UniActivityParams) {  
        console.log('UTSAcvitiyLifeCycle', 'onStart', params)  
        callback('onStart')  
    }  
    override onPreStart(params : UniActivityParams) {  
        console.log('UTSAcvitiyLifeCycle', 'onPreStart', params)  
        callback('onPreStart')  
    }  
}  
export class UTSAcvitiyKeyEventCallback extends UniActivityKeyEventCallback {  
    constructor() {  
        super()  
    }  
    override onKeyDown(params : UniActivityParams, keyCode : Int, event : KeyEvent | null) {  
        console.log('UTSAcvitiyKeyEvent', 'onKeyDown', params, keyCode, '' + event)  
        callback('onKeyDown')  
    }  
    override onPreKeyDown(params : UniActivityParams, keyCode : Int, event : KeyEvent | null) {  
        console.log('UTSAcvitiyKeyEvent', 'onPreKeyDown', params, keyCode, '' + event)  
        callback('onPreKeyDown')  
    }  
    override onKeyLongPress(params : UniActivityParams, keyCode : Int, event : KeyEvent | null) {  
        console.log('UTSAcvitiyKeyEvent', 'onKeyLongPress', params, keyCode, '' + event)  
        callback('onKeyLongPress')  
    }  
    override onPreKeyLongPress(params : UniActivityParams, keyCode : Int, event : KeyEvent | null) {  
        console.log('UTSAcvitiyKeyEvent', 'onPreKeyLongPress', params, keyCode, '' + event)  
        callback('onPreKeyLongPress')  
    }  
}  

export class UTSActivityWindowCallback extends UniActivityWindowCallback {  
    constructor() {  
        super()  
    }  
    override dispatchPreKeyEvent(params : UniActivityParams, event : KeyEvent | null) {  
        console.log('UTSActivityWindowCallback', 'dispatchPreKeyEvent', params, '' + event)  
        callback('dispatchPreKeyEvent')  
    }  
    override dispatchKeyEvent(params : UniActivityParams, event : KeyEvent | null) {  
        console.log('UTSActivityWindowCallback', 'dispatchKeyEvent', params, '' + event)  
        callback('dispatchKeyEvent')  
    }  
    override  onWindowAttributesChanged(params : UniActivityParams, attrs : WindowManager.LayoutParams) {  
        console.log('UTSActivityWindowCallback', 'onWindowAttributesChanged', '' + attrs)  
        callback('onWindowAttributesChanged')  

    }  
    override onAttachedToWindow(params : UniActivityParams) {  
        console.log('UTSActivityWindowCallback', 'onAttachedToWindow', params)  
        callback('onAttachedToWindow')  

    }  
    override onPanelClosed(params : UniActivityParams, featureId : Int, menu : Menu) {  
        console.log('UTSActivityWindowCallback', 'onPanelClosed', featureId, menu)  
        callback('onPanelClosed')  

    }  
    override onWindowStartingActionMode(params : UniActivityParams, callback : ActionMode.Callback | null) {  
        console.log('UTSActivityWindowCallback', 'onWindowStartingActionMode', callback)  
        callback('onWindowStartingActionMode')  
    }  
    override onProvideKeyboardShortcuts(params : UniActivityParams, data : MutableList<KeyboardShortcutGroup> | null, menu : Menu | null, deviceId : Int) {  
        console.log('UTSActivityWindowCallback', 'onProvideKeyboardShortcuts', data, menu)  
        callback('onProvideKeyboardShortcuts')  
    }  
    override  onPreWindowAttributesChanged(params : UniActivityParams, attrs : WindowManager.LayoutParams) {  
        console.log('UTSActivityWindowCallback', 'onPreWindowAttributesChanged', attrs)  
        callback('onPreWindowAttributesChanged')  
    }  
    override  onPrePanelClosed(params : UniActivityParams, featureId : Int, menu : Menu) {  
        console.log('UTSActivityWindowCallback', 'onPrePanelClosed', featureId, menu)  
        callback('onPrePanelClosed')  
    }  
}  

export class UTSActivityCallback extends UniActivityCallback {  
    constructor() {  
        super()  
    }  
    override onRequestPermissionsResult(params : UniActivityParams, requestCode : Int, permissions : MutableList<String>, grantResults : IntArray) {  
        console.log('UTSActivityCallback', 'onRequestPermissionsResult', params)  
        callback('onRequestPermissionsResult')  
    }  

}  

export class UTSActivityComponentCallback extends UniActivityComponentCallback {  
    constructor() {  
        super()  
    }  
    override onConfigurationChanged(params : UniActivityParams, newConfig : Configuration) {  
        console.log('UTSActivityComponentCallback', 'onConfigurationChanged', params, '' + newConfig)  
        callback('onConfigurationChanged')  
    }  
    override onPreConfigurationChanged(params : UniActivityParams, newConfig : Configuration) {  
        console.log('UTSActivityComponentCallback', 'onPreConfigurationChanged', params, '' + newConfig)  
        callback('onPreConfigurationChanged')  
    }  
}

使用HbuilderX 4.74.2025063012-alpha版本编写

继续阅读 »

大标题

官方链接 :https://doc.dcloud.net.cn/uni-app-x/uts/utsactivitycallback.html#UniActivityKeyEventCallback

uvue代码部分缺少变量 cbText,新建 uni_modules插件不能以uts开头,即示例中的 uts-syntaxcase 不可以以这个命名,将其改为 muts-syntaxcase

uts代码代码缺少所有需要引入的库,除了内置库。

缺少以下库

import Bundle from "android.os.Bundle"  
import KeyEvent from "android.view.KeyEvent"  
import WindowManager from "android.view.WindowManager"   
import Menu from "android.view.Menu"  
import ActionMode from "android.view.ActionMode"  
import Configuration from "android.content.res.Configuration"  
import KeyboardShortcutGroup from "android.view.KeyboardShortcutGroup";

完整代码

------uvue页面代码------

<template>  
    <!-- #ifdef APP-ANDROID -->  
    <scroll-view style="flex: 1">  
        <view>  
            <view class="uni-padding-wrap uni-common-mt">  
                <view class="text-box" scroll-y="true">  
                    <text>{{ text }}</text>  
                </view>  
            </view>  
            <button @tap="activityCallback">注册activity 回调方法</button>  
            <view class="uni-padding-wrap uni-common-mt">  
                <view class="uni-hello-text">  
                    点击注册activity 回调方法后,可以手动切换其他APP再返回,可在控制台和界面观察事件日志  
                </view>  
            </view>  
            <view class="uni-padding-wrap uni-common-mt">  
                <view class="text-box" scroll-y="true">  
                    <text>{{ cbText }}</text>  
                </view>  
            </view>  
            <button @tap="unRegActivityCallback">取消注册activity 回调方法</button>  
        </view>  
    </scroll-view>  
    <!-- #endif -->  
</template>  

<script>  
    // #ifdef APP-ANDROID  
    import {  
        UTSAcvitiyLifeCycleCallback,  
        UTSAcvitiyKeyEventCallback,  
        UTSActivityWindowCallback,  
        UTSActivityCallback,  
        UTSActivityComponentCallback,  
        onCallbackChange  
    } from '@/uni_modules/muts-syntaxcase'  
    // #endif  

    import File from 'java.io.File';  
    import Intent from 'android.content.Intent';  

    export default {  
        data() {  
            return {  
                text: '',  
                cbText: "" as string,  
                callback: [] as Any[]  
            }  
        },  
        unmounted() {  
            // #ifdef APP-ANDROID  
            this.unRegActivityCallback()  
            // #endif  

        },  
        methods: {  
            // #ifdef APP-ANDROID  
            // #ifdef UNI-APP-X  
            activityCallback() {  
                var that = this  
                onCallbackChange(function (eventLog : string) {  
                    // 展示捕捉到的声明周期日志  
                    let nextLine = that.cbText + eventLog  
                    that.cbText = nextLine  
                    let nextLineFlag = that.cbText + '\n'  
                    that.cbText = nextLineFlag  
                })  
                let index = getCurrentPages().length - 1  
                let page = getCurrentPages()[index]  
                console.log('page route=' + page.route)  
                this.callback.push(new UTSAcvitiyLifeCycleCallback())  
                this.callback.push(new UTSActivityWindowCallback())  
                this.callback.push(new UTSAcvitiyKeyEventCallback())  
                this.callback.push(new UTSActivityCallback(), page.route)  
                this.callback.push(new UTSActivityComponentCallback())  
                this.callback.forEach((value) => {  
                    if (value instanceof UTSAcvitiyLifeCycleCallback) {  
                        UTSAndroid.onActivityCallback(value, page.route)  
                    }  
                    if (value instanceof UTSActivityWindowCallback) {  
                        UTSAndroid.onActivityCallback(value)  
                    }  
                    if (value instanceof UTSAcvitiyKeyEventCallback) {  
                        UTSAndroid.onActivityCallback(value)  
                    }  
                    if (value instanceof UTSActivityCallback) {  
                        UTSAndroid.onActivityCallback(value)  
                    }  
                    if (value instanceof UTSActivityComponentCallback) {  
                        UTSAndroid.onActivityCallback(value)  
                    }  

                })  
            },  
            unRegActivityCallback() {  
                this.callback.forEach((value) => {  

                    if (value instanceof UTSAcvitiyLifeCycleCallback) {  
                        UTSAndroid.offActivityCallback(value)  
                    }  
                    if (value instanceof UTSActivityWindowCallback) {  
                        UTSAndroid.offActivityCallback(value)  
                    }  
                    if (value instanceof UTSAcvitiyKeyEventCallback) {  
                        UTSAndroid.offActivityCallback(value)  
                    }  
                    if (value instanceof UTSActivityCallback) {  
                        UTSAndroid.offActivityCallback(value)  
                    }  
                    if (value instanceof UTSActivityComponentCallback) {  
                        UTSAndroid.offActivityCallback(value)  
                    }  
                })  
            }  
            // #endif  
            // #endif  
        },  
    }  
</script>

------uts代码------

代码位置:uni_modules/muts-syntaxcase/utssdk/app-android/index.uts

let callback : (eventLog : string) => void = (res) => { };  

export function onCallbackChange(fn : (eventLog : string) => void) {  
    callback = fn  
}  
import Bundle from "android.os.Bundle"  
import KeyEvent from "android.view.KeyEvent"  
import WindowManager from "android.view.WindowManager"   
import Menu from "android.view.Menu"  
import ActionMode from "android.view.ActionMode"  
import Configuration from "android.content.res.Configuration"  
import KeyboardShortcutGroup from "android.view.KeyboardShortcutGroup";  
export class UTSAcvitiyLifeCycleCallback extends UniActivityLifeCycleCallback {  
    constructor() {  
        super()  
    }  
    override onCreate(params : UniActivityParams, savedInstanceState : Bundle | null) {  
        console.log('UTSAcvitiyLifeCycle', 'onCreate', savedInstanceState)  
        callback('onCreate')  
    }  

    override onResume(params : UniActivityParams) {  
        console.log('UTSAcvitiyLifeCycle', 'onResume', params)  
        callback('onResume')  
    }  
    override onPreResume(params : UniActivityParams) {  
        console.log('UTSAcvitiyLifeCycle', 'onPreResume', params)  
        callback('onPreResume')  
    }  
    override onStart(params : UniActivityParams) {  
        console.log('UTSAcvitiyLifeCycle', 'onStart', params)  
        callback('onStart')  
    }  
    override onPreStart(params : UniActivityParams) {  
        console.log('UTSAcvitiyLifeCycle', 'onPreStart', params)  
        callback('onPreStart')  
    }  
}  
export class UTSAcvitiyKeyEventCallback extends UniActivityKeyEventCallback {  
    constructor() {  
        super()  
    }  
    override onKeyDown(params : UniActivityParams, keyCode : Int, event : KeyEvent | null) {  
        console.log('UTSAcvitiyKeyEvent', 'onKeyDown', params, keyCode, '' + event)  
        callback('onKeyDown')  
    }  
    override onPreKeyDown(params : UniActivityParams, keyCode : Int, event : KeyEvent | null) {  
        console.log('UTSAcvitiyKeyEvent', 'onPreKeyDown', params, keyCode, '' + event)  
        callback('onPreKeyDown')  
    }  
    override onKeyLongPress(params : UniActivityParams, keyCode : Int, event : KeyEvent | null) {  
        console.log('UTSAcvitiyKeyEvent', 'onKeyLongPress', params, keyCode, '' + event)  
        callback('onKeyLongPress')  
    }  
    override onPreKeyLongPress(params : UniActivityParams, keyCode : Int, event : KeyEvent | null) {  
        console.log('UTSAcvitiyKeyEvent', 'onPreKeyLongPress', params, keyCode, '' + event)  
        callback('onPreKeyLongPress')  
    }  
}  

export class UTSActivityWindowCallback extends UniActivityWindowCallback {  
    constructor() {  
        super()  
    }  
    override dispatchPreKeyEvent(params : UniActivityParams, event : KeyEvent | null) {  
        console.log('UTSActivityWindowCallback', 'dispatchPreKeyEvent', params, '' + event)  
        callback('dispatchPreKeyEvent')  
    }  
    override dispatchKeyEvent(params : UniActivityParams, event : KeyEvent | null) {  
        console.log('UTSActivityWindowCallback', 'dispatchKeyEvent', params, '' + event)  
        callback('dispatchKeyEvent')  
    }  
    override  onWindowAttributesChanged(params : UniActivityParams, attrs : WindowManager.LayoutParams) {  
        console.log('UTSActivityWindowCallback', 'onWindowAttributesChanged', '' + attrs)  
        callback('onWindowAttributesChanged')  

    }  
    override onAttachedToWindow(params : UniActivityParams) {  
        console.log('UTSActivityWindowCallback', 'onAttachedToWindow', params)  
        callback('onAttachedToWindow')  

    }  
    override onPanelClosed(params : UniActivityParams, featureId : Int, menu : Menu) {  
        console.log('UTSActivityWindowCallback', 'onPanelClosed', featureId, menu)  
        callback('onPanelClosed')  

    }  
    override onWindowStartingActionMode(params : UniActivityParams, callback : ActionMode.Callback | null) {  
        console.log('UTSActivityWindowCallback', 'onWindowStartingActionMode', callback)  
        callback('onWindowStartingActionMode')  
    }  
    override onProvideKeyboardShortcuts(params : UniActivityParams, data : MutableList<KeyboardShortcutGroup> | null, menu : Menu | null, deviceId : Int) {  
        console.log('UTSActivityWindowCallback', 'onProvideKeyboardShortcuts', data, menu)  
        callback('onProvideKeyboardShortcuts')  
    }  
    override  onPreWindowAttributesChanged(params : UniActivityParams, attrs : WindowManager.LayoutParams) {  
        console.log('UTSActivityWindowCallback', 'onPreWindowAttributesChanged', attrs)  
        callback('onPreWindowAttributesChanged')  
    }  
    override  onPrePanelClosed(params : UniActivityParams, featureId : Int, menu : Menu) {  
        console.log('UTSActivityWindowCallback', 'onPrePanelClosed', featureId, menu)  
        callback('onPrePanelClosed')  
    }  
}  

export class UTSActivityCallback extends UniActivityCallback {  
    constructor() {  
        super()  
    }  
    override onRequestPermissionsResult(params : UniActivityParams, requestCode : Int, permissions : MutableList<String>, grantResults : IntArray) {  
        console.log('UTSActivityCallback', 'onRequestPermissionsResult', params)  
        callback('onRequestPermissionsResult')  
    }  

}  

export class UTSActivityComponentCallback extends UniActivityComponentCallback {  
    constructor() {  
        super()  
    }  
    override onConfigurationChanged(params : UniActivityParams, newConfig : Configuration) {  
        console.log('UTSActivityComponentCallback', 'onConfigurationChanged', params, '' + newConfig)  
        callback('onConfigurationChanged')  
    }  
    override onPreConfigurationChanged(params : UniActivityParams, newConfig : Configuration) {  
        console.log('UTSActivityComponentCallback', 'onPreConfigurationChanged', params, '' + newConfig)  
        callback('onPreConfigurationChanged')  
    }  
}

使用HbuilderX 4.74.2025063012-alpha版本编写

收起阅读 »

我对uniappx的一些看法

我早期写mui, 后续用apicoud ,此时apicloud服务层面做的更好。
后放弃apicloud使用flutter, flutter理念更加不错。
最近发现uniappx ,觉得uniappx理念不错,这些理念都是有迹可循,但没有形成规范,兼容平台过多形成累赘。
1.我觉得uniappx应该放弃其他web端技术的平台,由uniapp继续支持,因为web本就互通。一次写多端理解适配web技术产品还行,
app 3端,这样适配,只会导致app 3端只能做简单应用层app,复制大型应用只能再次去选择flutter或者原生,uniappx在整体布局上明显不足。
2.uniappx的竞争对象应该是flutter,不仅仅编译适配3端,还可以考虑适配c#桌面,linux系统。不应该局限在应用层,
用web技术代码风格规范,去适配其他平台的应用。
3.目前这种大杂烩,uniapp,uniappx互相兼容的模式,带来各种混乱
01.文档层面,准确度不够,对比案例和文档,有些内容基本没有写入文档,或者在uniapp文档中,但对于没有用过和不了解uniapp非常麻烦,
并且uniapp的理念在当下并不新颖。此处对uniappx人员非常不友好。
02.uniappx借助了各种理念,比喻借助了vue,ts等,编译需要,并不会全部使用,但在文档上并没有与这些语言框架切割,还需要去其他平台看那些技术的文档,
dcloud对于这些讲解不全,我猜dcloud底层架构人员都是前端,用前端思维去解决所有问题,并且默认认为所有人都懂前端发展的层次技术,
借助前端的理念去规范和组织代码是没有问题的,但没必要去借助前端思维。
03.前端技术有极强的互通性,如web,各平台小程序,写各个平台不需要学新技术,仅仅是节省了一点开发时间,其他没啥优势,甚至在各平台新功能上无法即使更新,
那么其服务的群体也是国内的微型公司或者是市场性公司,功能也极具简单,也说明了布局者眼光非常窄,放弃了全球市场,也没有全球的世界观,
当然也就没有大的高加载的客户群体,目前这种节省了一点开发时间的成本,其附加值本就低,很有可能会转移到其他非发达国家去开发,
届时dcloud的这种服务对象会错位。
4.目前我看到的uniappx的优势是
1.用web技术代码风格规范,通过编译的能力适配各平台。
2.最早适配鸿蒙的混合模式,flutter都没这么快,这是市场空白期。

继续阅读 »

我早期写mui, 后续用apicoud ,此时apicloud服务层面做的更好。
后放弃apicloud使用flutter, flutter理念更加不错。
最近发现uniappx ,觉得uniappx理念不错,这些理念都是有迹可循,但没有形成规范,兼容平台过多形成累赘。
1.我觉得uniappx应该放弃其他web端技术的平台,由uniapp继续支持,因为web本就互通。一次写多端理解适配web技术产品还行,
app 3端,这样适配,只会导致app 3端只能做简单应用层app,复制大型应用只能再次去选择flutter或者原生,uniappx在整体布局上明显不足。
2.uniappx的竞争对象应该是flutter,不仅仅编译适配3端,还可以考虑适配c#桌面,linux系统。不应该局限在应用层,
用web技术代码风格规范,去适配其他平台的应用。
3.目前这种大杂烩,uniapp,uniappx互相兼容的模式,带来各种混乱
01.文档层面,准确度不够,对比案例和文档,有些内容基本没有写入文档,或者在uniapp文档中,但对于没有用过和不了解uniapp非常麻烦,
并且uniapp的理念在当下并不新颖。此处对uniappx人员非常不友好。
02.uniappx借助了各种理念,比喻借助了vue,ts等,编译需要,并不会全部使用,但在文档上并没有与这些语言框架切割,还需要去其他平台看那些技术的文档,
dcloud对于这些讲解不全,我猜dcloud底层架构人员都是前端,用前端思维去解决所有问题,并且默认认为所有人都懂前端发展的层次技术,
借助前端的理念去规范和组织代码是没有问题的,但没必要去借助前端思维。
03.前端技术有极强的互通性,如web,各平台小程序,写各个平台不需要学新技术,仅仅是节省了一点开发时间,其他没啥优势,甚至在各平台新功能上无法即使更新,
那么其服务的群体也是国内的微型公司或者是市场性公司,功能也极具简单,也说明了布局者眼光非常窄,放弃了全球市场,也没有全球的世界观,
当然也就没有大的高加载的客户群体,目前这种节省了一点开发时间的成本,其附加值本就低,很有可能会转移到其他非发达国家去开发,
届时dcloud的这种服务对象会错位。
4.目前我看到的uniappx的优势是
1.用web技术代码风格规范,通过编译的能力适配各平台。
2.最早适配鸿蒙的混合模式,flutter都没这么快,这是市场空白期。

收起阅读 »

文档真是够够的,研究都要找瞎也没看到哪儿有UTS插件导出接口名称的定义全是类型定义

uts插件 文档

interface.uts 作为整个插件的入口声明 文档找了个遍也没看到怎么定义每个函数的名称 通篇都是类型 ,类型导出也是犯愁

插件申明文件中 export type和export type 对外都不可见,尝试用 export class (本不应该用class,这里没有具体实现)
结果 编译运行开始报错平台实现没找到导出的类型
然后在接口声明一个 接口 去平台目录实现 好家伙接口中要返回的类型必须 改成接口里面声明的接口 外面又看不到接口中导出的 interface
只能用typ 导出 t ype导出了 实现的时候需要一个class 去实现返回封装 好家伙类型又报错

interface.uts

export/open/public/   interface  IResult {  
        x:number  
        y:number;  
       close():void   
}  

  export interface IPlugins {      

    a():void   
    b():Promise<IResult>  

  }   

web/index.uts

class IResultWebImpl  implements IResult  {  
     //     
}  

PluginsWebImpl implements IPlugins  {  

  //...   
}

// page/index.uts;

import * as P from  '@/uni_modules/xx'  

P.b().then(r:P.IResult ) {  
        // .....  
}  

外部使用的始终是 接口定义的不关心实现 这种模式很难实现吗?

简化一下

interface.uts

export/open/public/   interface  IResult {  
        x:number  
        y:number;  
       close():void   
}  

//  export interface IPlugins {     省略掉  

 export  function a ():void   
  export  function b ():Promise<IResult>  

//  }   

或者使用 internal open public protected declare 等等标记 一下 应该不是多难得事情
面向接口而非实现 不是首要遵守的吗 为什么那么折腾

继续阅读 »

interface.uts 作为整个插件的入口声明 文档找了个遍也没看到怎么定义每个函数的名称 通篇都是类型 ,类型导出也是犯愁

插件申明文件中 export type和export type 对外都不可见,尝试用 export class (本不应该用class,这里没有具体实现)
结果 编译运行开始报错平台实现没找到导出的类型
然后在接口声明一个 接口 去平台目录实现 好家伙接口中要返回的类型必须 改成接口里面声明的接口 外面又看不到接口中导出的 interface
只能用typ 导出 t ype导出了 实现的时候需要一个class 去实现返回封装 好家伙类型又报错

interface.uts

export/open/public/   interface  IResult {  
        x:number  
        y:number;  
       close():void   
}  

  export interface IPlugins {      

    a():void   
    b():Promise<IResult>  

  }   

web/index.uts

class IResultWebImpl  implements IResult  {  
     //     
}  

PluginsWebImpl implements IPlugins  {  

  //...   
}

// page/index.uts;

import * as P from  '@/uni_modules/xx'  

P.b().then(r:P.IResult ) {  
        // .....  
}  

外部使用的始终是 接口定义的不关心实现 这种模式很难实现吗?

简化一下

interface.uts

export/open/public/   interface  IResult {  
        x:number  
        y:number;  
       close():void   
}  

//  export interface IPlugins {     省略掉  

 export  function a ():void   
  export  function b ():Promise<IResult>  

//  }   

或者使用 internal open public protected declare 等等标记 一下 应该不是多难得事情
面向接口而非实现 不是首要遵守的吗 为什么那么折腾

收起阅读 »

uniappX 需求强已经出现 微信登录、分享、打开微信小程序需求,大家可以投票,顶起来,官方的插件才是靠谱的选择

微信登录 微信小程序 微信分享 uni-appx

uniappX 需求强已经出现 微信登录、分享、打开微信小程序需求,大家可以投票,顶起来,官方的插件才是靠谱的选择

地址: https://vote.dcloud.net.cn/#/?name=uni-app%20x

我只认可官方插件,顶起来

uniappX 需求强已经出现 微信登录、分享、打开微信小程序需求,大家可以投票,顶起来,官方的插件才是靠谱的选择

地址: https://vote.dcloud.net.cn/#/?name=uni-app%20x

我只认可官方插件,顶起来

uni-app 能否搞一套声明式UI呢,声明式UI是趋势呢,能极大的提高开发效率呢

鸿蒙的开发思路就是: 声明式UI + TS 这种模式用着很舒服呢

鸿蒙的开发思路就是: 声明式UI + TS 这种模式用着很舒服呢

flutter3.32调用deepseek客户端ai流式模板

flutter

flutter3-win-deepseek:最新研发 flutter3.32+dio+deepseek-v3+window_manager 接入 deepseek-v3 大模型。支持侧边栏收缩、本地会话存储、代码块高亮、代码块横向滚动、表格边框线、图片100%宽度渲染、图片预览、链接跳转

技术栈

  • 开发工具:VScode
  • 技术框架:flutter3.32.0+dart3.8.0
  • 对话大模型:deepseek-v3
  • 流请求:dio^5.8.0+1
  • 窗口管理:window_manager^0.5.0
  • 托盘管理:system_tray^2.0.3
  • 路由/状态管理:get^4.7.2
  • 存储服务:get_storage^2.1.1
  • markdown解析:flutter_markdown^0.7.7
  • 高亮组件:flutter_highlight^0.7.0
  • 环境变量配置:flutter_dotenv^5.2.1

项目特性

  1. 支持侧边栏收缩/展开
  2. 支持多轮对话、代码高亮、本地存储会话
  3. 支持代码块横向滚动、复制代码功能
  4. 支持图片100%宽度渲染、在线图片预览
  5. 支持网络链接跳转、表格功能
  6. 自定义无边框窗口、托盘图标

项目框架目录

flutter3-winseek桌面端ai对话系统已经更新到我的原创作品集。
flutter3.32+deepseek+dio客户端ai流式对话Exe

如果想要了解更多的技术实现细节的话,可以去看看下面这篇分享文章。
flutter3-winseek客户端AI实例|Flutter3.32+DeepSeek流式ai对话模板Exe

热文推荐

flutter3-deepseek流式AI模板|Flutter3.27+Dio+DeepSeeek聊天ai助手
uniapp+vue3+deepseek+uv-ui跨端实战仿deepseek/豆包流式ai聊天对话助手
vue3-webseek网页版AI问答|Vite6+DeepSeek+Arco流式ai聊天打字效果
Electron35-DeepSeek桌面端AI系统|vue3.5+electron+arco客户端ai模板
Vue3-DeepSeek-Chat流式AI对话|vite6+vant4+deepseek智能ai聊天助手
flutter3-dymall仿抖音直播商城|Flutter3.27短视频+直播+聊天App实例
Vite5+Electron聊天室|electron31跨平台仿微信EXE客户端|vue3聊天程序
Tauri2.0-Vue3OS桌面端os平台|tauri2+vite6+arco电脑版OS管理系统
uniapp+vue3聊天室|uni-app+vite4+uv-ui跨端仿微信app聊天语音/朋友圈

继续阅读 »

flutter3-win-deepseek:最新研发 flutter3.32+dio+deepseek-v3+window_manager 接入 deepseek-v3 大模型。支持侧边栏收缩、本地会话存储、代码块高亮、代码块横向滚动、表格边框线、图片100%宽度渲染、图片预览、链接跳转

技术栈

  • 开发工具:VScode
  • 技术框架:flutter3.32.0+dart3.8.0
  • 对话大模型:deepseek-v3
  • 流请求:dio^5.8.0+1
  • 窗口管理:window_manager^0.5.0
  • 托盘管理:system_tray^2.0.3
  • 路由/状态管理:get^4.7.2
  • 存储服务:get_storage^2.1.1
  • markdown解析:flutter_markdown^0.7.7
  • 高亮组件:flutter_highlight^0.7.0
  • 环境变量配置:flutter_dotenv^5.2.1

项目特性

  1. 支持侧边栏收缩/展开
  2. 支持多轮对话、代码高亮、本地存储会话
  3. 支持代码块横向滚动、复制代码功能
  4. 支持图片100%宽度渲染、在线图片预览
  5. 支持网络链接跳转、表格功能
  6. 自定义无边框窗口、托盘图标

项目框架目录

flutter3-winseek桌面端ai对话系统已经更新到我的原创作品集。
flutter3.32+deepseek+dio客户端ai流式对话Exe

如果想要了解更多的技术实现细节的话,可以去看看下面这篇分享文章。
flutter3-winseek客户端AI实例|Flutter3.32+DeepSeek流式ai对话模板Exe

热文推荐

flutter3-deepseek流式AI模板|Flutter3.27+Dio+DeepSeeek聊天ai助手
uniapp+vue3+deepseek+uv-ui跨端实战仿deepseek/豆包流式ai聊天对话助手
vue3-webseek网页版AI问答|Vite6+DeepSeek+Arco流式ai聊天打字效果
Electron35-DeepSeek桌面端AI系统|vue3.5+electron+arco客户端ai模板
Vue3-DeepSeek-Chat流式AI对话|vite6+vant4+deepseek智能ai聊天助手
flutter3-dymall仿抖音直播商城|Flutter3.27短视频+直播+聊天App实例
Vite5+Electron聊天室|electron31跨平台仿微信EXE客户端|vue3聊天程序
Tauri2.0-Vue3OS桌面端os平台|tauri2+vite6+arco电脑版OS管理系统
uniapp+vue3聊天室|uni-app+vite4+uv-ui跨端仿微信app聊天语音/朋友圈

收起阅读 »

unipp---HarmonyOS 应用开发实战

鸿蒙next

HarmonyOS 应用开发实战指南

1. 开篇:为什么选择 HarmonyOS?

最近在开发鸿蒙应用时,发现很多开发者都在问:为什么要选择 HarmonyOS?这里分享一下我的看法:

  1. 生态优势

    • 华为手机用户基数大,市场潜力大
    • 开发者支持力度大,文档更新及时
    • 应用场景丰富,从手机到智能家居都有覆盖
  2. 技术优势

    • 分布式架构确实好用,一次开发多端运行
    • 性能表现不错,特别是启动速度
    • 安全机制做得很到位,对开发者友好
  3. 开发体验

    • Vue 3 开发模式,上手快
    • TypeScript 支持,代码质量有保障
    • 原生能力调用方便,API 设计合理

2. 为什么选择 uni-app x 开发鸿蒙应用?

2.1 降低开发门槛

  1. 不用学鸿蒙原生开发

    • 不用学 ArkTS,省时省力
    • 不用研究鸿蒙原生组件,直接用 Vue 组件
    • 不用适应鸿蒙特有的开发模式,保持原有开发习惯
  2. 用熟悉的技术栈

    • Vue 3 语法,写起来顺手
    • TypeScript 类型检查,减少 bug
    • 组件化开发,代码复用方便
  3. 上手快

    • 有 Vue 经验的直接开干
    • 学习成本低,一周就能上手
    • 遇到问题社区都能找到答案

2.2 开发效率提升

  1. 跨平台开发

    • 一套代码,iOS、Android、鸿蒙都能跑
    • 不用为每个平台写一套代码
    • 维护成本大大降低
  2. 组件库丰富

    • 内置组件够用,不用重复造轮子
    • 自定义组件方便,复用性强
    • 社区组件多,能解决大部分需求
  3. 工具链完善

    • HBuilderX 开发体验好
    • 调试方便,问题定位快
    • 插件生态丰富,开发效率高

2.3 实际开发优势

  1. 代码维护

    • 代码风格统一,团队协作方便
    • 目录结构清晰,找文件快
    • 代码复用性强,减少重复工作
  2. 性能表现

    • 性能接近原生,用户体验好
    • 渲染机制优化得不错
    • 内存管理做得好,不容易卡顿
  3. 发布部署

    • 打包流程简单,一键发布
    • 版本管理方便,回滚容易
    • 更新机制完善,用户无感知

2.4 实际案例分享

  1. 开发周期

    • 原生开发:2-3个月
    • uni-app x:1个月搞定
    • 效率提升:50%以上
  2. 团队配置

    • 原生开发:需要专门的鸿蒙工程师
    • uni-app x:前端工程师就能干
    • 人力成本:省了30%以上
  3. 维护成本

    • 原生开发:要维护多套代码
    • uni-app x:一套代码搞定
    • 维护效率:提升40%以上

2.5 踩过的坑

  1. 性能优化

    • 组件不要嵌套太深
    • 注意内存泄漏问题
    • 长列表要用虚拟列表
  2. 兼容性

    • 不同设备表现可能不一样
    • 横竖屏切换要测试
    • 不同系统版本要适配
  3. 原生能力

    • API 可能有兼容性问题
    • 错误处理要做好
    • 权限申请要规范

3. 开发环境准备

3.1 必需工具

  1. DevEco Studio

    • 下载地址:https://developer.harmonyos.com/cn/develop/deveco-studio
    • 建议版本:最新稳定版
  2. HBuilderX

    • 下载地址:https://www.dcloud.io/hbuilderx.html
    • 建议版本:3.8.0 及以上
    • 安装注意:需要安装 uni-app x 插件

3.2 环境配置

# 检查 Node.js 版本  
node -v  # 建议 16.x 以上  

# 检查 npm 版本  
npm -v   # 建议 8.x 以上  

# 安装 uni-app x 命令行工具  
npm install -g @dcloudio/uni-app-x-cli

4. 实战:系统信息展示应用

4.1 项目结构

project/  
├── src/  
│   ├── pages/  
│   │   └── index/  
│   │       ├── index.uvue    # 主页面  
│   │       └── index.uts     # 页面逻辑  
│   │     
│   ├── static/              # 静态资源  
│   └── manifest.json        # 项目配置  
└── package.json

4.2 核心代码实现

4.2.1 页面结构(index.uvue)

<template>  
  <view>  
    <!-- 顶部标题 -->  
    <view class="header">  
      <text class="title">系统信息</text>  
    </view>  

    <!-- 系统信息展示区 -->  
    <scroll-view class="system-info" scroll-y="true">  
      <!-- 应用信息卡片 -->  
      <view class="info-section">  
        <text class="section-title">应用信息</text>  
        <view class="info-item">  
          <text class="label">应用名称:</text>  
          <text class="value">{{systemInfo.appName}}</text>  
        </view>  
        <!-- 其他应用信息... -->  
      </view>  

      <!-- 其他信息卡片... -->  
    </scroll-view>  
  </view>  
</template>

4.2.2 业务逻辑(index.uts)

// 系统信息接口定义  
interface SystemInfo {  
  // 应用信息  
  appId: string;  
  appName: string;  
  appVersion: string;  
  // ... 其他属性  
}  

export default {  
  data() {  
    return {  
      systemInfo: {} as SystemInfo  
    }  
  },  

  onLoad() {  
    // 获取系统信息  
    this.getSystemInfo()  
  },  

  methods: {  
    getSystemInfo() {  
      uni.getSystemInfo({  
        success: (res: SystemInfo) => {  
          this.systemInfo = res  
          console.log('系统信息获取成功:', res)  
        },  
        fail: (err) => {  
          console.error('系统信息获取失败:', err)  
          uni.showToast({  
            title: '获取系统信息失败',  
            icon: 'none'  
          })  
        }  
      })  
    }  
  }  
}

4.3 样式优化

/* 卡片样式 */  
.info-section {  
  margin: 10px;  
  padding: 15px;  
  background-color: #fff;  
  border-radius: 8px;  
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);  
}  

/* 标题样式 */  
.section-title {  
  font-size: 16px;  
  font-weight: bold;  
  color: #333;  
  margin-bottom: 12px;  
  padding-bottom: 8px;  
  border-bottom: 1px solid #eee;  
}  

/* 信息项样式 */  
.info-item {  
  margin: 8px 0;  
  display: flex;  
  align-items: center;  
}  

.label {  
  color: #666;  
  width: 100px;  
  font-size: 14px;  
}  

.value {  
  color: #333;  
  flex: 1;  
  font-size: 14px;  
  word-break: break-all;  
}

5. 开发经验分享

5.1 常见坑点

  1. 系统信息获取

    • 某些设备可能不支持部分属性
    • 需要做好空值处理
    • 建议添加错误处理
  2. 界面适配

    • 不同设备屏幕尺寸差异大
    • 需要适配横竖屏
    • 注意安全区域
  3. 性能优化

    • 避免频繁获取系统信息
    • 合理使用缓存
    • 注意内存管理

5.2 调试技巧

  1. 日志输出

    // 开发环境日志  
    if (process.env.NODE_ENV === 'development') {  
    console.log('调试信息:', data)  
    }
  2. 错误处理

    try {  
    // 可能出错的代码  
    } catch (error) {  
    console.error('错误信息:', error)  
    uni.showToast({  
    title: '操作失败',  
    icon: 'none'  
    })  
    }

5.3 发布注意事项

  1. 版本号管理

    • 遵循语义化版本
    • 记录更新日志
    • 做好版本兼容
  2. 性能测试

    • 多设备测试
    • 压力测试
    • 内存泄漏检测
  3. 安全考虑

    • 敏感信息加密
    • 权限最小化
    • 数据安全存储

6. 进阶开发

6.1 原生能力调用

// 调用相机示例  
uni.chooseImage({  
  count: 1,  
  success: (res) => {  
    console.log('图片选择成功:', res)  
  }  
})  

// 调用传感器示例  
uni.startAccelerometer({  
  interval: 'game',  
  success: () => {  
    console.log('加速度传感器启动成功')  
  }  
})

6.2 性能优化实践

  1. 图片优化

    • 使用适当的图片格式
    • 控制图片大小
    • 实现懒加载
  2. 列表优化

    • 使用虚拟列表
    • 分页加载
    • 数据缓存
  3. 启动优化

    • 减少启动时加载
    • 使用预加载
    • 优化资源加载

7. 实用资源

7.1 开发工具

  • DevEco Studio:https://developer.harmonyos.com
  • HBuilderX:https://www.dcloud.io
  • 调试工具:Chrome DevTools

7.2 学习资源

  • 官方文档:https://developer.harmonyos.com
  • 示例代码:https://github.com/harmonyos
  • 技术社区:https://developer.huawei.com

7.3 开发规范

  • 代码规范:ESLint + Prettier
  • 提交规范:Git Commit Message
  • 文档规范:Markdown

8. 结语

通过这个实战项目,我们学习了:

  1. 如何搭建开发环境
  2. 如何获取系统信息
  3. 如何优化界面展示
  4. 如何处理常见问题

希望这个指南能帮助您更好地开发 HarmonyOS 应用。记住:

  • 保持代码简洁
  • 注重用户体验
  • 重视性能优化
  • 持续学习进步

如果您有任何问题,欢迎在评论区讨论。祝您开发愉快!

继续阅读 »

HarmonyOS 应用开发实战指南

1. 开篇:为什么选择 HarmonyOS?

最近在开发鸿蒙应用时,发现很多开发者都在问:为什么要选择 HarmonyOS?这里分享一下我的看法:

  1. 生态优势

    • 华为手机用户基数大,市场潜力大
    • 开发者支持力度大,文档更新及时
    • 应用场景丰富,从手机到智能家居都有覆盖
  2. 技术优势

    • 分布式架构确实好用,一次开发多端运行
    • 性能表现不错,特别是启动速度
    • 安全机制做得很到位,对开发者友好
  3. 开发体验

    • Vue 3 开发模式,上手快
    • TypeScript 支持,代码质量有保障
    • 原生能力调用方便,API 设计合理

2. 为什么选择 uni-app x 开发鸿蒙应用?

2.1 降低开发门槛

  1. 不用学鸿蒙原生开发

    • 不用学 ArkTS,省时省力
    • 不用研究鸿蒙原生组件,直接用 Vue 组件
    • 不用适应鸿蒙特有的开发模式,保持原有开发习惯
  2. 用熟悉的技术栈

    • Vue 3 语法,写起来顺手
    • TypeScript 类型检查,减少 bug
    • 组件化开发,代码复用方便
  3. 上手快

    • 有 Vue 经验的直接开干
    • 学习成本低,一周就能上手
    • 遇到问题社区都能找到答案

2.2 开发效率提升

  1. 跨平台开发

    • 一套代码,iOS、Android、鸿蒙都能跑
    • 不用为每个平台写一套代码
    • 维护成本大大降低
  2. 组件库丰富

    • 内置组件够用,不用重复造轮子
    • 自定义组件方便,复用性强
    • 社区组件多,能解决大部分需求
  3. 工具链完善

    • HBuilderX 开发体验好
    • 调试方便,问题定位快
    • 插件生态丰富,开发效率高

2.3 实际开发优势

  1. 代码维护

    • 代码风格统一,团队协作方便
    • 目录结构清晰,找文件快
    • 代码复用性强,减少重复工作
  2. 性能表现

    • 性能接近原生,用户体验好
    • 渲染机制优化得不错
    • 内存管理做得好,不容易卡顿
  3. 发布部署

    • 打包流程简单,一键发布
    • 版本管理方便,回滚容易
    • 更新机制完善,用户无感知

2.4 实际案例分享

  1. 开发周期

    • 原生开发:2-3个月
    • uni-app x:1个月搞定
    • 效率提升:50%以上
  2. 团队配置

    • 原生开发:需要专门的鸿蒙工程师
    • uni-app x:前端工程师就能干
    • 人力成本:省了30%以上
  3. 维护成本

    • 原生开发:要维护多套代码
    • uni-app x:一套代码搞定
    • 维护效率:提升40%以上

2.5 踩过的坑

  1. 性能优化

    • 组件不要嵌套太深
    • 注意内存泄漏问题
    • 长列表要用虚拟列表
  2. 兼容性

    • 不同设备表现可能不一样
    • 横竖屏切换要测试
    • 不同系统版本要适配
  3. 原生能力

    • API 可能有兼容性问题
    • 错误处理要做好
    • 权限申请要规范

3. 开发环境准备

3.1 必需工具

  1. DevEco Studio

    • 下载地址:https://developer.harmonyos.com/cn/develop/deveco-studio
    • 建议版本:最新稳定版
  2. HBuilderX

    • 下载地址:https://www.dcloud.io/hbuilderx.html
    • 建议版本:3.8.0 及以上
    • 安装注意:需要安装 uni-app x 插件

3.2 环境配置

# 检查 Node.js 版本  
node -v  # 建议 16.x 以上  

# 检查 npm 版本  
npm -v   # 建议 8.x 以上  

# 安装 uni-app x 命令行工具  
npm install -g @dcloudio/uni-app-x-cli

4. 实战:系统信息展示应用

4.1 项目结构

project/  
├── src/  
│   ├── pages/  
│   │   └── index/  
│   │       ├── index.uvue    # 主页面  
│   │       └── index.uts     # 页面逻辑  
│   │     
│   ├── static/              # 静态资源  
│   └── manifest.json        # 项目配置  
└── package.json

4.2 核心代码实现

4.2.1 页面结构(index.uvue)

<template>  
  <view>  
    <!-- 顶部标题 -->  
    <view class="header">  
      <text class="title">系统信息</text>  
    </view>  

    <!-- 系统信息展示区 -->  
    <scroll-view class="system-info" scroll-y="true">  
      <!-- 应用信息卡片 -->  
      <view class="info-section">  
        <text class="section-title">应用信息</text>  
        <view class="info-item">  
          <text class="label">应用名称:</text>  
          <text class="value">{{systemInfo.appName}}</text>  
        </view>  
        <!-- 其他应用信息... -->  
      </view>  

      <!-- 其他信息卡片... -->  
    </scroll-view>  
  </view>  
</template>

4.2.2 业务逻辑(index.uts)

// 系统信息接口定义  
interface SystemInfo {  
  // 应用信息  
  appId: string;  
  appName: string;  
  appVersion: string;  
  // ... 其他属性  
}  

export default {  
  data() {  
    return {  
      systemInfo: {} as SystemInfo  
    }  
  },  

  onLoad() {  
    // 获取系统信息  
    this.getSystemInfo()  
  },  

  methods: {  
    getSystemInfo() {  
      uni.getSystemInfo({  
        success: (res: SystemInfo) => {  
          this.systemInfo = res  
          console.log('系统信息获取成功:', res)  
        },  
        fail: (err) => {  
          console.error('系统信息获取失败:', err)  
          uni.showToast({  
            title: '获取系统信息失败',  
            icon: 'none'  
          })  
        }  
      })  
    }  
  }  
}

4.3 样式优化

/* 卡片样式 */  
.info-section {  
  margin: 10px;  
  padding: 15px;  
  background-color: #fff;  
  border-radius: 8px;  
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);  
}  

/* 标题样式 */  
.section-title {  
  font-size: 16px;  
  font-weight: bold;  
  color: #333;  
  margin-bottom: 12px;  
  padding-bottom: 8px;  
  border-bottom: 1px solid #eee;  
}  

/* 信息项样式 */  
.info-item {  
  margin: 8px 0;  
  display: flex;  
  align-items: center;  
}  

.label {  
  color: #666;  
  width: 100px;  
  font-size: 14px;  
}  

.value {  
  color: #333;  
  flex: 1;  
  font-size: 14px;  
  word-break: break-all;  
}

5. 开发经验分享

5.1 常见坑点

  1. 系统信息获取

    • 某些设备可能不支持部分属性
    • 需要做好空值处理
    • 建议添加错误处理
  2. 界面适配

    • 不同设备屏幕尺寸差异大
    • 需要适配横竖屏
    • 注意安全区域
  3. 性能优化

    • 避免频繁获取系统信息
    • 合理使用缓存
    • 注意内存管理

5.2 调试技巧

  1. 日志输出

    // 开发环境日志  
    if (process.env.NODE_ENV === 'development') {  
    console.log('调试信息:', data)  
    }
  2. 错误处理

    try {  
    // 可能出错的代码  
    } catch (error) {  
    console.error('错误信息:', error)  
    uni.showToast({  
    title: '操作失败',  
    icon: 'none'  
    })  
    }

5.3 发布注意事项

  1. 版本号管理

    • 遵循语义化版本
    • 记录更新日志
    • 做好版本兼容
  2. 性能测试

    • 多设备测试
    • 压力测试
    • 内存泄漏检测
  3. 安全考虑

    • 敏感信息加密
    • 权限最小化
    • 数据安全存储

6. 进阶开发

6.1 原生能力调用

// 调用相机示例  
uni.chooseImage({  
  count: 1,  
  success: (res) => {  
    console.log('图片选择成功:', res)  
  }  
})  

// 调用传感器示例  
uni.startAccelerometer({  
  interval: 'game',  
  success: () => {  
    console.log('加速度传感器启动成功')  
  }  
})

6.2 性能优化实践

  1. 图片优化

    • 使用适当的图片格式
    • 控制图片大小
    • 实现懒加载
  2. 列表优化

    • 使用虚拟列表
    • 分页加载
    • 数据缓存
  3. 启动优化

    • 减少启动时加载
    • 使用预加载
    • 优化资源加载

7. 实用资源

7.1 开发工具

  • DevEco Studio:https://developer.harmonyos.com
  • HBuilderX:https://www.dcloud.io
  • 调试工具:Chrome DevTools

7.2 学习资源

  • 官方文档:https://developer.harmonyos.com
  • 示例代码:https://github.com/harmonyos
  • 技术社区:https://developer.huawei.com

7.3 开发规范

  • 代码规范:ESLint + Prettier
  • 提交规范:Git Commit Message
  • 文档规范:Markdown

8. 结语

通过这个实战项目,我们学习了:

  1. 如何搭建开发环境
  2. 如何获取系统信息
  3. 如何优化界面展示
  4. 如何处理常见问题

希望这个指南能帮助您更好地开发 HarmonyOS 应用。记住:

  • 保持代码简洁
  • 注重用户体验
  • 重视性能优化
  • 持续学习进步

如果您有任何问题,欢迎在评论区讨论。祝您开发愉快!

收起阅读 »

基于flutter3.27接入deepseek跨平台ai对话实例

OpenAI flutter

flutter3-deepseek-chat:原创基于flutter3.27+dio+deepseek-v3+markdown 接入 DeepSeek-V3 会话大模型。支持本地会话存储、支持markdown代码块高亮、代码块横向滚动、表格边框线、图片100%宽度渲染、图片预览、链接跳转

使用技术

  • 技术框架:flutter3.27.1+dart3.6.0
  • AI对话模型:deepseek-v3
  • 网络请求:dio^5.8.0+1
  • 路由/状态管理:get^4.7.2
  • 本地存储:get_storage^2.1.1
  • markdown解析:flutter_markdown^0.7.7
  • 高亮插件:flutter_highlight^0.7.0

项目功能

  1. Flutter3+DeepSeek流式打字效果
  2. Flutter3.27搭建项目,接入DeepSeek-V3,对话更丝滑
  3. 支持手机端/桌面端显示
  4. 支持代码块高亮、多轮上下文会话、本地存储对话
  5. 支持代码块横向滚动、代码复制
  6. 支持图片宽度100%渲染、在线图片预览功能
  7. 支持链接跳转
  8. 支持表格显示功能

项目框架结构

目前flutter3_deepseek跨平台ai项目已经发布到我的原创作品集。
Flutter3+DeepSeek-V3跨平台AI流式输出聊天模板

如果想要了解更多的技术实现细节的话,可以去看看下面这篇分享文章。
flutter3-deepseek流式AI模板|Flutter3.27+Dio+DeepSeeek聊天ai助手

往期热文

uniapp+vue3+deepseek+uv-ui跨端实战仿deepseek/豆包流式ai聊天对话助手
vue3-webseek网页版AI问答|Vite6+DeepSeek+Arco流式ai聊天打字效果
Electron35-DeepSeek桌面端AI系统|vue3.5+electron+arco客户端ai模板
Vue3-DeepSeek-Chat流式AI对话|vite6+vant4+deepseek智能ai聊天助手
uniapp+vue3聊天室|uni-app+vite4+uv-ui跨端仿微信app聊天语音/朋友圈
flutter3-dymall仿抖音直播商城|Flutter3.27短视频+直播+聊天App实例
Tauri2.0-Vue3OS桌面端os平台|tauri2+vite6+arco电脑版OS管理系统
Vite5+Electron聊天室|electron31跨平台仿微信EXE客户端|vue3聊天程序

继续阅读 »

flutter3-deepseek-chat:原创基于flutter3.27+dio+deepseek-v3+markdown 接入 DeepSeek-V3 会话大模型。支持本地会话存储、支持markdown代码块高亮、代码块横向滚动、表格边框线、图片100%宽度渲染、图片预览、链接跳转

使用技术

  • 技术框架:flutter3.27.1+dart3.6.0
  • AI对话模型:deepseek-v3
  • 网络请求:dio^5.8.0+1
  • 路由/状态管理:get^4.7.2
  • 本地存储:get_storage^2.1.1
  • markdown解析:flutter_markdown^0.7.7
  • 高亮插件:flutter_highlight^0.7.0

项目功能

  1. Flutter3+DeepSeek流式打字效果
  2. Flutter3.27搭建项目,接入DeepSeek-V3,对话更丝滑
  3. 支持手机端/桌面端显示
  4. 支持代码块高亮、多轮上下文会话、本地存储对话
  5. 支持代码块横向滚动、代码复制
  6. 支持图片宽度100%渲染、在线图片预览功能
  7. 支持链接跳转
  8. 支持表格显示功能

项目框架结构

目前flutter3_deepseek跨平台ai项目已经发布到我的原创作品集。
Flutter3+DeepSeek-V3跨平台AI流式输出聊天模板

如果想要了解更多的技术实现细节的话,可以去看看下面这篇分享文章。
flutter3-deepseek流式AI模板|Flutter3.27+Dio+DeepSeeek聊天ai助手

往期热文

uniapp+vue3+deepseek+uv-ui跨端实战仿deepseek/豆包流式ai聊天对话助手
vue3-webseek网页版AI问答|Vite6+DeepSeek+Arco流式ai聊天打字效果
Electron35-DeepSeek桌面端AI系统|vue3.5+electron+arco客户端ai模板
Vue3-DeepSeek-Chat流式AI对话|vite6+vant4+deepseek智能ai聊天助手
uniapp+vue3聊天室|uni-app+vite4+uv-ui跨端仿微信app聊天语音/朋友圈
flutter3-dymall仿抖音直播商城|Flutter3.27短视频+直播+聊天App实例
Tauri2.0-Vue3OS桌面端os平台|tauri2+vite6+arco电脑版OS管理系统
Vite5+Electron聊天室|electron31跨平台仿微信EXE客户端|vue3聊天程序

收起阅读 »

uniapp x开发用uni.request发送请求一直报602001 "errMsg": "request system error" js端可运行 【已解决】

bug反馈

如果是全栈的兄弟们,就是本地环境的接口是会报这个错的,换成公网的接口就行了,不知道是bug还是什么,对于集成本地环境的兄弟不太友好

如果是全栈的兄弟们,就是本地环境的接口是会报这个错的,换成公网的接口就行了,不知道是bug还是什么,对于集成本地环境的兄弟不太友好

关于uni-app X项目离线打包自定义基座不显示静态资源的解决方法

自定义基座 uni-app x 离线打包

targetSDK 34
在AndroidManifest.xml中先关闭调试:

<meta-data  
            android:name="DCLOUD_DEBUG"  
            android:value="false" />

点Run
在生成apk后再打开调试,选择:Build -> Generate App Bundles or APKs -> Generate APKs
这样生成的基座在HBuilder中就可以正常显示静态资源文件了

继续阅读 »

targetSDK 34
在AndroidManifest.xml中先关闭调试:

<meta-data  
            android:name="DCLOUD_DEBUG"  
            android:value="false" />

点Run
在生成apk后再打开调试,选择:Build -> Generate App Bundles or APKs -> Generate APKs
这样生成的基座在HBuilder中就可以正常显示静态资源文件了

收起阅读 »

【经验分享】uniappX中实现类似pinia-plugin-persist-uni的本地数据缓存

uniapp x

主要的实现方法

export function defineStore<T>(name : string, obj : T) : T {  
    let storage = uni.getStorageSync(name);  
    if (storage instanceof UTSJSONObject) {  
        let data = JSON.parse<T>(JSON.stringify(storage));  
        if (data != null) {  
            let newVal = data as T;  
            obj = reactive(newVal);  
        }  
    }  
    watch(obj as any, () => {  
        uni.setStorage({  
            key: name,  
            data: obj as any  
        });  
    }, {  
        deep: true  
    })  
    return obj;  
}

调用示例:

type UserStore = {  
    initReady : boolean;  
    userInfo: UTSJSONObject;  
}  
export const app = defineStore("app", reactive<UserStore>({  
    initReady: false,  
    userInfo:{}  
}))

页面中app.xxx就是响应式,参考官方文档:https://doc.dcloud.net.cn/uni-app-x/tutorial/store.html#%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%E4%B8%8E%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86
如果没有这种处理,app每次启动的时候,状态都会重置。加了后数据就能本地持久化了。

继续阅读 »

主要的实现方法

export function defineStore<T>(name : string, obj : T) : T {  
    let storage = uni.getStorageSync(name);  
    if (storage instanceof UTSJSONObject) {  
        let data = JSON.parse<T>(JSON.stringify(storage));  
        if (data != null) {  
            let newVal = data as T;  
            obj = reactive(newVal);  
        }  
    }  
    watch(obj as any, () => {  
        uni.setStorage({  
            key: name,  
            data: obj as any  
        });  
    }, {  
        deep: true  
    })  
    return obj;  
}

调用示例:

type UserStore = {  
    initReady : boolean;  
    userInfo: UTSJSONObject;  
}  
export const app = defineStore("app", reactive<UserStore>({  
    initReady: false,  
    userInfo:{}  
}))

页面中app.xxx就是响应式,参考官方文档:https://doc.dcloud.net.cn/uni-app-x/tutorial/store.html#%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%E4%B8%8E%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86
如果没有这种处理,app每次启动的时候,状态都会重置。加了后数据就能本地持久化了。

收起阅读 »