【记录】微信小程序开发和发布及一些问题解决

前言

        公司要调研小程序开发,学习小程序开发流程。个人以小程序对话gpt为案例,本文主要用作记录。主要参考uni-app官网

        前置条件:安装NodeJS(使用的是v18.17.0)、安装HbuildX

新建项目浏览器启动测试

这里使用的是vue2

直接浏览器启动

查看效果

引入uView

uView简介

uView是uni-app生态专用的UI框架,uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码, 可发布到iOS、Android、H5、以及各种小程序(微信/支付宝/百度/头条/QQ/钉钉)等多个平台(引言自uni-app网)。但目前除微信小程序,其它小程序平台的兼容可能存在一些问题,后续会针对这方面持续优化。

uView安装

安装有多种方式有两种方式:uni-app插件市场和npm。此处记录npm方式。

在项目根目录执行如下命令即可:

// 如果您的根目录没有package.json文件的话,请先执行如下命令:
// npm init -y

npm install uview-ui@2.0.36

// 更新
// npm update uview-ui

uView配置

关于SCSS

uView依赖SCSS,您必须要安装此插件,否则无法正常运行。

  • 如果您的项目是由HBuilder X创建的,相信已经安装scss插件,如果没有,请在HX菜单的 工具->插件安装中找到"scss/sass编译"插件进行安装, 如不生效,重启HX即可
  • 如果您的项目是由vue-cli创建的,请通过以下命令安装对sass(scss)的支持,如果已安装,请略过。
// 安装sass
npm i sass -D

// 安装sass-loader,注意需要版本10,否则可能会导致vue与sass的兼容问题而报错
npm i sass-loader@10 -D

引入uView主JS库

在项目src目录中的main.js中,引入并使用uView的JS库,注意这两行要放在import Vue之后。

// main.js
import uView from "uview-ui";
Vue.use(uView);

引入uView的全局SCSS主题文件

在项目src目录的uni.scss中引入此文件。

/* uni.scss */
@import 'uview-ui/theme.scss';

引入uView基础样式

App.vue首行的位置引入,注意给style标签加入lang="scss"属性

<style lang="scss">
	/* 注意要写在第一行,同时给style标签加入lang="scss"属性 */
	@import "uview-ui/index.scss";
</style>

配置easycom组件模式

此配置需要在项目src目录的pages.json中进行。

// pages.json
{
	"easycom": {
		"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
	},
	
	// 此为本身已有的内容
	"pages": [
		// ......
	]
}

测试

        在以下微信小程序启动中一同测试。

微信小程序启动

        直接在HbuildX中启动,选择微信小程序。

注意事项

         需要在小程序设置中安全设置开启服务端口

功能Demo

设置底部导航

修改pages.json。注意需要在pages文件夹对应路径下建立vue文件。

{
	"easycom": {
			"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
	},
	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
		{
			"path": "pages/index/index",
			"style": {
				"navigationBarTitleText": "uni-app"
			}
		},
		{
			"path": "pages/func/funcList",
			"style": {
				"navigationBarTitleText": ""
			}
		},{
            "path" : "pages/chat/dialog",
			"style" : {
				"navigationBarTitleText" : "",
				"navigationStyle" : "custom"
			}
		},{
            "path" : "pages/my/my",
            "style" :                                                                                    
            {
                "navigationBarTitleText": ""
            }
            
        }
	],
	"globalStyle": {
		"navigationBarTextStyle": "black",
		"navigationBarTitleText": "uni-app",
		"navigationBarBackgroundColor": "#F8F8F8",
		"backgroundColor": "#F8F8F8"
	},
	"tabBar": {
		"color": "#999999",
		"selectedColor": "#26B3A0",
		"borderStyle": "white",
		"backgroundColor": "#ffffff",
		"list": [{
			"pagePath": "pages/index/index",
			"iconPath": "static/images/index.png",
			"selectedIconPath": "static/images/indexs.png",
			"text": "首页"
		}, {
			"pagePath": "pages/func/funcList",
			"iconPath": "static/images/func.png",
			"selectedIconPath": "static/images/funcs.png",
			"text": "功能"
		},
		{
			"pagePath": "pages/chat/dialog",
			"iconPath": "static/images/chat.png",
			"selectedIconPath": "static/images/chats.png",
			"text": "对话"
		},
		{
			"pagePath": "pages/my/my",
			"iconPath": "static/images/my.png",
			"selectedIconPath": "static/images/mys.png",
			"text": "我的"
		}]
	},
	"uniIdRouter": {}
}

首页设置

<template>
	<view class="homeLayout">
		<uv-navbar :title="title" :autoBack="false" titleStyle="font-weight: 600">
		</uv-navbar>
		<view class="banner">
			<swiper circular indicator-dots indicator-color="rgba(255,255,255,0.5)" 
			indicator-active-color="#fff" autoplay>
				<swiper-item v-for="item in bannerList" :key="item._id">
					
					<navigator v-if="item.target == 'miniProgram'" 
					:url="item.url" 
					class="like"
					target="miniProgram"
					:app-id="item.appid"
					>
						<image :src="item.picurl" mode="aspectFill"></image>
					</navigator>
					
					<navigator v-else :url="`/pages/classlist/classlist?${item.url}`" class="like">
						<image :src="item.picurl" mode="aspectFill"></image>
					</navigator>
				</swiper-item>				
			</swiper>
		</view>
		
		
		<view class="u-content">
				<uv-parse :content="content"></uv-parse>
		</view>
	</view>
</template>

<script setup>
import { ref } from 'vue';

const bannerList= ref([]);
const content = ref([]);
const title = ref('维亿智慧');

const getBanner = async ()=>{
	// let res =await apiGetBanner();
	// bannerList.value = res.data;
	setTimeout(() => {
	  bannerList.value 	= [
	    { _id: '1', target:'miniProgram', picurl: 'http://121.41.225.164/staticfile/%E9%A6%96%E9%A1%B51.jpg' },
	    { _id: '2', target:'miniProgram', picurl: 'http://121.41.225.164/staticfile/%E9%A6%96%E9%A1%B52.jpg' },
	  ];
	}, 1000);
}

const getContent = async ()=>{
	// let res =await apiGetBanner();
	// bannerList.value = res.data;
	setTimeout(() => {
	  content.value = `
					<p>&nbsp;&nbsp;&nbsp;&nbsp;维亿科技是一家在国内以工业互联,数字孪生为理念,从工艺流程优化、生产和管理变革出发,通过基于数字孪生的全局优化控制,建设基于工业互联网的能源智能工厂,从设计,生产,运维实现能源企业价值重构,推动能源产业变革升级的企业。地址于武汉中心区域,地区拥有多所知名高校和研究机构,培养了大量的计算机科学和软件工程等专业人才。人才吸收为公司提供了强大的研发和创新能力,经过多年的发展,形成了完善的产业链和供应链,涵盖了软件开发、测试、运维、技术支持等多个环节。</p>
					
					<div class="visible-xs-block" style="margin-top: 20px">
					            <span class="mobile-title2">智慧能源</span>
					        </div>
					<img style='height:300rpx;width:100%' src="http://121.41.225.164/staticfile/solutions/%E6%99%BA%E6%85%A7%E8%83%BD%E6%BA%90%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88.jpg">
					<div class="mobile-function-description">
					            维亿科技与能源紧密结合“互联网+能源管理“与电力改革背景,以”安全、数据、成本、管理”为核心价值,实现对电、水、气、生产环境、设备等用能数据进行集中监控和管理,帮助客户提高能源管理水平,降低用能成本,提升用能质量,减少安全隐患
					        </div>
					
					<div class="visible-xs-block" style="margin-top: 20px">
					            <span class="mobile-title2">智慧园区</span>
					        </div>
					<img style='height:300rpx;width:100%'  src="http://121.41.225.164/staticfile/solutions/%E6%99%BA%E6%85%A7%E5%9B%AD%E5%8C%BA%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88.jpg">
					<div class="mobile-function-description">
					            利用先进的信息技术和可视化技术,通过构建三维可视化平台,实时采集、整合和展示园区内各类资源、设施、企业等信息,实现全局监控和智慧运营。同时,它融合物联网、云计算等技术,优化资源配置,提高决策效率,推动园区产业的创新与发展,有助于提升园区的综合竞争力和可持续发展水平。
					        </div>
					
					<div class="visible-xs-block" style="margin-top: 20px">
					            <span class="mobile-title2">智慧城市</span>
					        </div>
					<img style='height:300rpx;width:100%' src="http://121.41.225.164/staticfile/solutions/%E6%99%BA%E6%85%A7%E5%9F%8E%E5%B8%82%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88.jpg">
					<div class="mobile-function-description">
					            维亿科技综合利用GIS、物联网、云计算等技术,将环卫设施、人员及车辆等环卫要素融合在一个信息平台上,按照“网格化管理,监管分离”的环卫管理模式,实现对环卫管理所涉及的人、车、物、事进行全过程实时管控,实现精细化管理,规范作业,提高效率,降低运营成本,建立环卫管理的长效机制。
					        </div>
							
					<div class="visible-xs-block" style="margin-top: 20px">
					            <span class="mobile-title2">智慧化工</span>
					        </div>
					<img style='height:300rpx;width:100%' src="http://121.41.225.164/staticfile/solutions/%E6%99%BA%E6%85%A7%E5%8C%96%E5%B7%A5%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88.jpg">
					<div class="mobile-function-description">
					            维亿以工业互联,数字孪生为理念,从工艺流程优化、生产和管理变革出发,通过基于数字孪生的全局优化控制,建设基于工业互联网的化工智能工厂,从设计,生产,远维实现化工企业价值结重构,推动石化,重化工、精细化工,医药化工等化工产业变革升级。
					        </div>
				
				`	
				
	}, 1000);
}

getBanner();
getContent();

</script>

<style lang="scss" scoped>
.homeLayout{
	.banner{
		width: 750rpx;
		padding:30rpx 0;
		swiper{
			width: 750rpx;
			height: 440rpx;
			&-item{
				width: 100%;
				height: 100%;
				padding:0 30rpx;
				.like{
					width: 100%;
					height: 100%;
					image{
						width: 100%;
						height: 100%;
						border-radius: 10rpx;
					}
				}
				
			}
		}
	}
	.u-content {
		margin-left: 30rpx;
		margin-right: 20rpx;
		// margin-top:  100rpx;
		
	}

	
}
.mobile-btn-img{
	width: 100%;
	height: 100rpx;
}
</style>

对话页面

<template>
	<view class="chat">
		<uv-navbar :title="title" :autoBack="false" titleStyle="font-weight: 600">
		</uv-navbar>
		<mescroll-body top="150" :auto="false" @init="mescrollInit" :down="downOption" @down="downCallback"
			:up="upOption" @up="upCallback">
			<view style="padding-bottom: 30px;">
				<view class="guide">
					<view class="guide_title">
						{{welcome.title}}
					</view>
					<view class="guide_text">
						{{welcome.info}}
					</view>
					<view @click="welcomeSend(welcomeItem)" class="guide_select" v-for="welcomeItem, index in welcome.list" :key="index">
						<text>{{welcomeItem}}</text>
						<uv-icon size="14" name="arrow-right" color="#9f9f9f"></uv-icon>
					</view>
				</view>
			</view>
			<view class="chat-item" v-for="item, index in chat" :key="index">
				<uv-transition :show="true" mode="fade-right">
					<view class="chat-item__right">
						<view class="chat-item__right-left">
							<view class="chat-item__right-message" @longtap="copy(item.question)">
								{{ item.question }}
							</view>
						</view>
						<uv-avatar class="chat-item__right-avatar" shape="circle" size="35" :src="userInfo.head_img"></uv-avatar>
					</view>
				</uv-transition>
				<uv-transition :show="true" mode="fade-left">
					<view class="chat-item__left u-flex">
						<uv-avatar size="35" shape="circle"></uv-avatar>
						<view class="chat-item__left-right">
							<view class="chat-item__left-name"> {{channel.name}} </view>
							<view class="chat-item__left-bottom">
								<view class="chat-item__left-message" @longtap="copy(item.answer)">
									{{item.answer}}
									<uv-loading-icon v-if="creating"></uv-loading-icon>
								</view>
							</view>
						</view>
					</view>
				</uv-transition>
			</view>
			<view class="seize" style="height: 200rpx"></view>
		</mescroll-body>
		<view class="input-box">
			<uv-input @confirm="send" :disabled="creating" confirmType="send" dshape="circle" placeholder="有问题尽管问我~" border="surround" v-model="question" cursorSpacing="10" maxlength="500">
			</uv-input>
			<uv-icon v-if="creating" color="#1acc89" size="38" name="pause-circle-fill" @click="finish"></uv-icon>
			<uv-icon v-if="!creating" color="#1acc89" size="38" name="play-circle-fill" @click="send"></uv-icon>
		</view>
	</view>
</template>

<script>
	import MescrollBody from "mescroll-uni/mescroll-body.vue";
	import * as base64 from "base-64";
	import CryptoJS from 'crypto-js';
	import * as utf8 from "utf8";
	import URL from 'url';

	export default {
		components: {
			MescrollBody
		},
		data() {
			return {
				userInfo: uni.getStorageSync('userInfo'),
				mescroll: null,
				upOption: {
					use: false,
				},
				downOption: {
					auto: false,
					textInOffset:'下拉加载',
					beforeEndDelay:1000,
					bgColor:'white',
					textColor:'black'
				},
				chat : [],
				page : 0,
				sessionId : 0,
				question : '',
				creating : 0,
				welcome : {
					title : '你好,我是你的智能助手',
					info : '作为你的智能伙伴,我既能写文案、想点子,又能陪你聊天、答疑解惑。你可以试着问我:',
					list : [
						'请帮我生成一对春联,要表达出吉祥、团圆、步步高升的意思。'
					]
				},
				streamDefault:true,
				title : '对话',
				channel:uni.getStorageSync('channel_info'),
				httpUrl: "",
				modelDomain: '',
				APPID: '',
				APISecret: '',
				APIKey: '',
				sparkResult: '',
				historyTextList: [],
				tempRes: ''
			}
		},
		onLoad(options) {
			this.downCallback();
		},
		methods: {
			async send() {
				this.creating = 1;
				if (!this.question) {
					uni.showToast({
						title: '你还没有输入内容呢!',
						icon: 'none'
					});
					this.creating = 0;
					return
				}
				this.chat.push({
					question: this.question,
					answer: ''
				});
				this.$nextTick(() => {
					this.mescroll.scrollTo(99999999);
				});
				let myUrl = await this.getWebSocketUrl();
				this.tempRes = "";
				let realThis = this;
				this.socketTask = uni.connectSocket({
					url: myUrl,
					method: 'GET',
					success: res => {
						console.log(res, "ws成功连接...", myUrl)
						realThis.wsLiveFlag = true;
					}
				})
				realThis.socketTask.onError((res) => {
					uni.showToast({
					    title: '请求失败,请联系管理员。错误内容:'+JSON.stringify(res),
					    icon: 'none',
					    duration: 2000
					});
				})
				realThis.socketTask.onOpen((res) => {
					realThis.historyTextList.push({
						"role": "user",
						"content": realThis.question
					})
					realThis.question = ''
					console.info("wss的onOpen成功执行...", res)
					let params = {
						"header": {
							"app_id": realThis.APPID,
							"uid": "aef9f963-7"
						},
						"parameter": {
							"chat": {
								"domain": realThis.modelDomain,
								"temperature": 0.5,
								"max_tokens": 1024
							}
						},
						"payload": {
							"message": {
								"text": realThis.historyTextList
							}
						}
					};
					console.log("请求的params:" + JSON.stringify(params))
					realThis.socketTask.send({
						data: JSON.stringify(params),
						success() {
							console.log('第一帧发送成功')
						}
					});
				});
				realThis.socketTask.onMessage((res) => {
					console.log('收到API返回的内容:', res.data);
					let obj = JSON.parse(res.data)
					let dataArray = obj.payload.choices.text;
					for (let i = 0; i < dataArray.length; i++) {
						realThis.chat[realThis.chat.length-1]['answer']= realThis.chat[realThis.chat.length-1].answer + dataArray[i].content
						realThis.tempRes = realThis.tempRes + dataArray[i].content
					}
					realThis.$nextTick(() => {
						realThis.mescroll.scrollTo(99999999);
					});
					let temp = JSON.parse(res.data)
					if (temp.header.code !== 0) {
						console.log(`${temp.header.code}:${temp.message}`);
						realThis.socketTask.close({
							success(res) {
								console.log('关闭成功', res)
								realThis.wsLiveFlag = false;
							},
							fail(err) {
								console.log('关闭失败', err)
							}
						})
					}
					if (temp.header.code === 0) {
						if (temp.header.status === 2) {
							realThis.historyTextList.push({
								"role": "assistant",
								"content": this.tempRes
							})
							console.log(realThis.historyTextList);
							realThis.socketTask.close({
								success(res) {
									realThis.creating = 0
									console.log('关闭成功', res)
								},
								fail(err) {
									realThis.creating = 0
								}
							})
						

测试效果运行效果

小程序发布

注册小程序开发者账号(过程略),填写appid后直接上传即可。

小程序成员添加

小程序成员管理中可以添加项目成员和体验成员。便于真机体验和测试。

项目成员:可参与小程序开发、运营的成员,可登陆小程序管理后台,包括运营者、开发者及数据分析者。
体验成员:表示参与小程序内测体验的成员,可打开体验版或开发版小程序。

小程序体验版测试

扫码可打开看实际效果

安全域名问题

"errMsg:"createSocketTask:fail wcwss url not in domain list

平台设置小程序域名

按实际情况填写

注意微信小程序支持不支持ws和http等不安全协议头。

注意

配置完成后需要重新进入小程序。

安卓重新进入依旧出错

按以下操作:

在手机端,下拉小程序->把当前的小程序删除->再重新进行进入,重试。

  • 43
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值