使用.NETWinForm开发所见即所得的IDE开发环境,实现不写代码直接生成应用程序升讯威在线客服系统

项目的核心功能已经基本实现,但12年之后我基本停止了这方面的开发,现在翻出来在这里写出来想和大家交流一下。

鉴于篇幅和精力的原因,请原谅我这篇博文对于技术实现的具体细节谈的不是很多,只能算是一个概述。对业务的说明也不多,我想大家都是技术流,应该一看就明白。

如果此篇博文有点儿价值,给个推荐呗^_^

项目使用了.NetFramework3.5开发,分为两大块:IDE和运行时(解析器)

IDE中开发的项目在打包后生成zip格式的包,解析器通过读取zip包实时解析运行,有点类似中间语言的概念,但我这里生成的zip包中主要以xml文件为主,通过xml文件对项目的UI,业务,数据结构进行描述。

到此可以看出,运行时本身并不一定是.Net或WinForm的,而是可以使用任何平台或语言实现,只要读取zip文件和xml文件并解析即可。

事实上我自己实现的默认运行时也不是WinForm,而是用了Silverlight。

再简单说说IDE的设计思路,几个主要的设计目标如下:

1.像VisualStudio一样

有可视化的环境,拖拖拽拽界面就出来了。

2.模块化设计

功能模块全部独立,解耦,以插件的形式存在于主程序(宿主)中。

2.不要写代码,业务通过界面,向导进行配置

拖一个按钮上去,想要单击时做一件事情,就先把按钮拖上去,然后设置这个按钮的事件序列,配置对应的事件。

3.把事件这个概念抽象并封装起来

4.对数据操作要有一定的自由度

除了基本的向导式配置以外,要能满足特殊需求,比如支持自定义sql语句。但是自定义sql语句怎样与数据源,目标交互呢?我设计了一种简单的表达方法,如UPDATEFROM[User]SET[Name]={FormElement.txtName}WHERE[Id]={System.UserId}

5.对数据库数据表的操作怎样交互

就是将其抽象为“数据实体”,数据实体也在IDE中由用户自己定义,定义的过程类似于SqlServer,定义好数据实体以后,在IDE中进行设计时,通过数据实体来抽象对数据库、表的操作,在打包项目时,可以根据定义的数据实体,生成多种数据库,如SqlServer,Mysql等。

6.资源文件的管理

在项目中必然要引用到外部资源,这部分外部资源,怎样引入,管理,打包呢?我在IDE中设计了独立的资源管理器,在IDE中设计UI时,通过资源管理器引用资源,打包时,将资源打包到zip文件中。

7.打包前的静态编译检查

类似于我们在VisualStudio中写程序,编译时如果有错误就会出现警告或错误提示。在这个IDE中,也必须有同样的功能。当引用的数据实体被删除,数据项不存在,引用的资源文件不存在,以及事件配置中一些问题出现时,能够实时,并在打包项目时指出这些错误的具体位置。

8.支持嵌入脚本

能够在事件序列中添加自定义脚本,支持在运行时动态解析或者调用某种脚本语言。此功能有所设计,但并未开发。

9.支持插件

10.IDE界面支持多国语言

目前IDE完整支持多国语言,所有文本均使用了资源,但是我没有直接使用资源文件,而是将其强类型化了,具体实现方式下文详述。

在设计开发这个IDE的早期,我并没有给自己设定如此详细的目标,现在写其实更多的是回顾和总结。

在这个项目中,大量使用了GDI+绘图,说复杂,给你调用的接口也就那么多,说简单,用GDI+自己写一个功能完备的WinForm控件,分分钟教你重新做人。在这个项目中,几乎所有的界面元素都是我自己用GDI+绘制的,使用的第三方控件不多。后面我会写一些这方面的感想。

下面罗列一些技术难点和主要功能点,有些细节可能没有试着做过都不会意识到那是个问题。

1.工具栏按钮/右键菜单的状态控制

黄色背景部分是动态挂载上去的,状态的控制在后文中说明。

此处右键菜单指的是窗体设计器中的右键菜单,在窗体设计器中,右键菜单比较复杂,不同控件的右键菜单有所不同,有共通的项目,有特殊的项目,以及状态是不是灰掉可能和控件本身的某些因素有关,但右键菜单本身是不可能通过处于设计状态的控件自身提供的,所以此处如何把控件特有的菜单项挂载上去,又怎样控制它们的状态?注意设计器本身和用来设计的控件是解耦合的。

注意这个例子,右键DataGrid产生的右键菜单中存在“添加列”和“编辑列”两个特殊的项目。

此处当我选中DataGrid时,属性网格下方也会出现这两个项目,这里先提一个关键概念,叫做“谓词”,这是一个DesignSurface中的概念,后文再详述。

此处实际上我实现了一个独立的菜单(包括工具栏项目)的管理器,并非直接创建MenuItem之类的实例去使用,这个管理器也是独立于业务进行设计的,对菜单项的各种状态,行为都进行了抽象与封装。在管理器层面统一调度这些菜单项,通过一定的机制使菜单项的状态与业务状态关联起来,不允许外部代码直接修改菜单项的状态,整套机制本身,与菜单项在UI层面的实现也是无关解耦的,最终生成可见菜单项时,才会生成特定的控件,如MenuItem,也可以换成其它任何菜单项控件,不影响管理器的功能与逻辑。

我记得当时我研究了几个IDE的设计细节,包括VisualStudio,应该都采用了类似的机制,好吧我承认是我研究之后借鉴了它们的机制。

这个问题我放在首位,是我意识到这个问题在大型软件中,真的是个很大的问题,我现在参与开发的一款电气化CAD软件中,就存在这个问题,但是他们早期并未意识到这个问题,也谈不上能很好的解决,几千个菜单项,工具栏按钮项,直接硬编码,对他们的状态控制也谈不上成体系,就是粗暴的硬编码,现在的维护,修改,调整都异常痛苦。

2.窗体设计器

最初我是自己用GDI+写了一个简单的设计器模型,支持拖拽,绘制,动态对齐等等功能,但是越往后越复杂,比如绘制一个DataGrid,你不能光是一个框框,你要自己去绘制它的列,列头,如果要绘制一个图片框,你就要自己去绘制它的图片内容,要考虑图片的缩放方式等等细节,如果要一条道走到黑完全自己实现,成本将非常高昂。

先看看早期直接使用GDI+实现的效果:

下面是直接使用微软DesignSurface效果:

和VisualStudio效果一样,不过这里需要注意的是DesignSurface仅仅也只是提供了基本的窗体设计能力(图中右侧部分),比我上面GDI+自己写的功能多不了多少,但是不用自己绘制控件的外观,其它辅助功能都是需要自行开发的。

这里要注意的一点是窗体设计器中允许被设计的控件们,是与设计器本身,与IDE解耦的,是完全独立实现的,后期添加新控件,修改控件都与IDE无关,这个地方的难点毅然是解耦合,各种解耦合。

左侧的属性列表是自行开发的,.NetFramework中确实提供了PropertyGrid控件,但是对于高阶开发此处并不适用,有很多制限,下文详述。

3.工具箱

工具箱本身是独立实现的,不依赖其所处的窗体设计器,同时它自身所承载的控件,也是动态载入的,后期允许第三方插件挂载控件到工具箱中。

这个地方需要注意的不多,一个是动态载入控件,另一个就是在和窗体设计器交互的时候,比如我拖一个控件到设计器上,这里是需要对接DesignSurface的。

4.属性网格(PropertyGrid)

.NetFramework中提供了PropertyGrid控件,可以实现对对象实例的属性编辑功能,但是难于扩展与自定义,我此处需要个性化定制的地方比较多,所以选择自己实现一个。

主要实现了以下功能

1)对于单个对象实例,列出它的属性(Property,下同),以及属性的值,如果属性值与默认值不同,能够粗体显示。

2)对于特殊的属性,提供对应的扩展编辑器,如颜色属性,在点击后应该提供一个颜色选择器。且这些扩展编辑器,是与属性网格本身解偶的。

3)如果同时设置了多个不同类型(Type)的对象实例,例如在窗体设计器中框选了多个控件,这个场景就复杂一些了;首先得到这些对象实例的类型(Type),抽取共通的属性,属性网格中仅显示共通属性,对于某个属性的值,如果所有对象实例的值是相同的,则显示,如果有所不同,则留空不显示。在设置了某个属性的值之后,能够将新值设置到这些对象实例中。

5.撤销重做引擎

这里可以用的上“引擎”二字,因为确实比较复杂,我们先将这个问题简化,可以简单理解为对“对象”属性变化的跟踪,可以撤销这些变化,也可以重做这些变化,可以任意步骤的操作。

涉及到的问题和知识点很多,在IDE里对象状态的变化又被抽象为具体的“操作”,以及这些操作又要和设计器进行联动,有一定难度。

UI上的效果是直接使用GDI+自定义的一个列表,并不是很复杂,其它能够直观看的界面UI不多,主要是代码了。

6.事件及事件编辑器

上文中提到,要将常用的操作(事件)都封装起来,通过配置的方式来运行,大方向好像并不复杂,但是,怎么做呢?首先事件本身的抽象要独立,要与窗体设计解耦合,其次“事件”的定义应该允许由第三方插件扩展,甚至“触发时机”也应该允许由第三方插件进行扩展。以一个最简单的按钮为例:

看上去和普通编程中的事件机制没什么区别,是的,我们要做的是对其基本机制进行抽象化。例如:

1)触发时机应该与事件寄主解耦,甚至允许第三方插件挂载触发时机。

2)事件序列应该与触发时机解耦,事件序列中的事件定义,应该与以上机制解耦,甚至允许第三方插件扩展。

看看项目中实现的效果:

我们就以“为窗体元素加载数据”这个事件为例,看看现在的事件编辑器大概是什么模样。

这个事件支持“关联数据实体方式”和“执行SQL方式”。

这里就可以配置事件在执行时,从哪里取得数据,我们指定了从用户这个数据实体中选择数据,同时指定了一个条件,就是用户的Id要等于指定文本框中的值。

除了使用界面元素中的值作为条件,还可以使用系统数据,如:

对于选择特定的用户,比如这个Id怎样获取呢?只要在加载数据时,把Id绑定到一个隐藏的文本框中就可以了,加载数据时,可以读取它的值。

然后切换到载入界面

在载入界面中,指定我的数据取出来以后,加载到界面的哪些元素中。

我们上文提到,希望对数据的操作有一定的自由度,那么在事件编辑器中,就允许直接定义sql语句,或者说sql语句的模板。

切换到sql界面后,首先可以通过获取sql按钮自动根据前面的配置生成sql,然后在此基础上进行调整,修改。

在sql编辑器中,可以通过{Provider.Source}的方式访问数据。

支持语法着色,支持智能提示。

目前实现了两种Provider,FormElement(窗体元素)和System(系统),在智能提示中支持递进的提示。

所谓递进的提示是输入“{”之后自动给出Provider,选择后进一步自动给出Source列表。

也可以在“{Provider”后输入“.”则自动给出Source列表。

智能提示用起来简单方便,看起来也很简单,貌似只是一个Popup,实则是一个不小的坑,这个功能困惑了我很久,记得当时到处找大神请教,除了高谈阔论的就是直接告诉我不知道,有个人也研究过SharpDeveloper,告诉我这个问题深了,后来我又去翻SharpDeveloper的源代码,参考了它的实现,完成之后还是相当有成就感的。

对于事件序列的编辑,有两种方法,一种是在设计器中双击控件之后打开的事件序列编辑器

另一种方法是在窗体设计器中提供了以树形方式展示的事件序列,可以直接拖动改变事件的触发时机,或其在事件序列中的位置。

事件在解析器中执行时,是按钮它所处事件序列中的顺序进行执行的。

目前实现的事件大概有十几个,基本的应用程序操作,数据交互等。

不再一一详细说明,因为事件本事是在解耦的情况下独立实现的,IDE并不依赖他们,所以未来扩展也很容易,可以说IDE和解析器是核心引擎,而这些事件定义,只是系统中的“业务”部分。

7.集合编辑器

集合编辑器,就真的只是用来编辑对象集合的,支持对集合中对象实例的编辑,以及集合中元素顺序的调整,并且在与窗体设计器解耦合的基础上,与窗体设计器联动,能够从窗体设计器中的元素取得对象集合,同时与撤销/重做引擎对接,在编辑的过程中,提供撤销/重做的支持。

这个编辑器完成之后复用性比较强,在窗体设计器中有很多地方需要对集合进行编辑,行定义,列定义,元素定义之类。

一个典型的使用场景是在窗体设计器中,对DataGrid的列进行编辑。

8.有效性检查

在窗体设计器中,能够对当前窗体中的各项设置,包含的事件进行有效性的检查。例如我在某个事件中设置了加载数据到TextBox1,后来我删除了这个TextBox1,那么就必须给出提示。

此处的主要难点应该在于解耦合,各种解耦合。

9.IDE多国语言实现

另一方面,实现了一种将界面文本绑定到资源的机制,这一点在WPF下非常方便,在WinForm下就要自己动手了。通过特定字符串标记资源key,在运行时自动扫描窗体或其它容器控件,通过解析这些字符串自动查找对应的资源,将其替换。

10.界面用户数据的验证

目前几乎所有的开发平台都提供了比较友好的用户输入验证方案,在WinForm下也有,不过并不是很完善,使用起来限制比较多,功能也有限,不是很顺手。

我自己开发了一套用于WinForm的用户界面数据验证功能。举个最简单的例子,我给文本框设置一个不允许空的属性,或者设置一个正则表达式,在我调用验证方法时,就能够对它进行有效性验证。方案非常简单,只是要花点心思把它实现好,各种控件都要支持,要解耦合,验证器要支持多种不同验证机制,验证结果如何向用户反馈等等。

这套验证机制也同样实现在了运行时(解析器)当中。

验证结果的反馈并不一定要用MessageBox,可以很容易的改进为其它更友好的形式。

11.模块化设计

模块化,插件式的框架设计现在应该有很多现成的框架和设计方法,但是在当时,又是WinForm下,可以参考的资料非常少,大方向不复杂,但是做完善做细致,在当时对我来说有相当大的难度。当时唯一可以参考的是微软的CAB框架,但在当时来看,CAB就已经是一个有些过时的框架了,使用起来有一些缺点和限制。

我在参考CAB的基础上在WinForm下实现了一套分解的非常细致的模块化开发框架,对软件的功能进行层层解耦,宿主程序与功能模块完全无关,而在我业务功能的设计上,IDE中的功能也实现了完全解耦,上文也多处提到了,窗体设计器与被设计的控件包解耦,事件机制与具体的事件定义解耦等等。

其它功能点

其它功能点主要是指:数据实体定义,主菜单定义,枚举定义,资源管理,以及其它小功能等,下文先做个简单展示,暂不再做详细的说明。

1.欢迎界面

欢迎界面是内嵌了一个HTML页面,只是和C#代码有简单交互,例如单击链接会调用C#方法,并传入参数。

此处注意一个细节,URL地址不是一个磁盘文件地址,而是一个自定义协议和路径的地址,这个需要自己实现,但是很简单。

年代久远,CSS和图片可能遗失了,不太好看,见谅。

2.数据实体定义

这块相对比较简单,没有复杂功能。

发布项目时可以根据数据实体定义自动生成数据库。

也可以针对指定的数据实体生成脚本。

3.枚举定义

界面很简单,生成数据库时,根据枚举定义向枚举表插入枚举数据。

但是有一个小细节是它和窗体设计器是有对接的,它是一个数据源的Provider,可以在设计器中把控件中的值绑定到枚举。

4.主菜单/工具栏定义

定义要生成的软件的主菜单和工具栏,运行时解析之后,根据自己的实现方式生成,可以是Ribbon的,也可以是传统的,或者其它方式。

菜单或工具栏项目支持事件,可以挂载事件序列。

5.资源管理

实现一个资源管理器,目前只实现了对图片资源的管理。

这里有点看点的是,我当时没有找到我觉得不错缩略图控件,于是只好自己实现一个。和Windows资源管理器功能一致,没有需要特殊说明的地方,只是自己从头实现一个不能说很难,但是真的很麻烦。借这个地方简单讲一下这个缩略浏览器的实现,可能有些朋友对GDI+不是很了解。

对于在WinForm下使用GDI+绘制界面(自己实现一个控件),是比较原始的,想像一下给你一张白纸,和一些简单的绘图接口,画线,画圆,画矩形,其实没别的了。画一个圆角矩形?自己计算坐标系,通过画弧线和画直线画一个。显示一些文本?自己进行字体字号测量坐标系换算,如果涉及到文本换行,超长用省略号代替,都是比较麻烦的。

你要自己在逻辑上把握控件的不同状态,如选中,非选中,鼠标滑过等等,和WPF下预定义的状态组不同,WinForm下这些状态是你要自己去把握的,状态切换时,你要自己根据状态进行重绘……

在绘制界面时,你只有一个从0,0开始的二维的平面坐标系,和它的尺寸。实现这样一个缩略图浏览器,缩略图的排版,布局,一行显示多少个,什么时候换行,选中非选中,鼠标框选,滚动条滚动都需要自己实现,包括鼠标框选时的框,也是需要自己用GDI+绘制的,然后自己计算坐标系,判断哪些项目应该处于被选中状态。

这个控件的代码接近3000行。现在回过头去看,只觉得注释不够详细。

软件中大部分自己实现的控件,都采用了类似的架构进行设计:控件本身,布局管理器,呈现器,呈现器实现,主题。

6.生成数据库,生成项目

这里目前并不复杂,生成数据库根据数据实体定义生成即可,生成项目目前我直接使用了项目文件,因为我目前的项目文件格式就是zip包,内含xml文件。

附带产出是实现了一个简单的比较通用的向导功能。

7.其它控件的美化。

从上面的截图中能够看到我使用了相当多的自定义控件,或经过美化的WinForm自带控件,典型的几个除了上面的缩略图控件,还有IDE上面的主菜单(效果参考了Paint.NET),DataGrid,重新实现的ComboBox等等,居然一步一步形成了一个自己的控件包。可惜技术更新换代日新月异,现在也基本用不上了。

IDE部分现在回过头去看,貌似实际功能并不多,但是核心架构已经基本完整了,后续如果继续开发,基本相当于开发插件和添加新的功能包。

其中绝大部分是从空白class硬写出来的,很多地方用现在的眼光去看,存在很大的过度设计问题。

解析器部分我是用Silverlight实现了一个,核心实现了,业务没有实现完整,可能是我现在的机器Silverlight版本有问题还是怎么回事没有运行起来,也不想去调试了,

并不复杂,只是解析zip包,xml文件,生成界面,事件处发时解析事件序列中的事件即可。

最后,如果你现在要做客户端软件,选择WPF吧,生产性非常高,功能非常完善与强大,如果你担心性能问题,我想说现在已经2015年了,不是2005年,如果你在开发中遇到了性能问题或其它问题,先从自身找原因。

专业程序员永远从自身找问题,业余程序员从平台从语言找问题。

后记:

最后想写一点点个人的感想与反思。我在开发这个软件的过程中,犯了许多的错误,这些错误未必是技术上的,但都是严重错误。

第二:目标非常的不明确。看上去有目标,我要做一个什么什么样的东西,但是太宏大,太宽泛,太遥远。没有认真的考量我要的到底是个什么,所以完全没有详细的计划,里程碑什么都没有。

第三:缺少与外界沟通。这个沟通除了技术,更多的是市场对技术的需求到底是什么,如果回到当初,我会抽自己一巴掌,你睁开眼睛,走出去看看别人的世界好吗!做技术不是高新技术行业,更多的是服务业,我们需要利用手中的技术去为他人服务,这是技术存在的意义。

第五:做东西尽量不要藏着掖着。没意义,藏着掖着无非怕别人剽窃了自己的创意,想法,这个先不论创意想法有多大实际价值,就算你的想法真的很厉害,如果你没有其它门槛,别人看了就会抄去,那你这个东西一定是会出问题的。门槛这么低,怎么就你想到了?别算别人确实一时没想到,你没有其它门槛,被抄了是迟早的事情,藏着掖着没有用。做了东西就要勇敢拿出来和人交流,正面的就吸纳,负面的就多反思自己。

THE END
1.欢迎的声音音效素材欢迎的声音mp3音效下载熊猫办公网站共为您提供32个欢迎的声音设计素材以及精品欢迎的声音音效素材下载,汇集全球精品流行的欢迎的声音mp3格式音效模板,下载后可以直接使用,方便快捷的不二选择。https://www.tukuppt.com/yinxiaomuban/huanyingdeshengyin.html
2.老BWBWBWBWBW对欢迎您:1.欢迎您加入我们的大家庭,共同探索无限理解欢迎您的重要性人们对“欢迎您”这一主题的关注,不仅关乎情感上的接纳,也涉及到社交互动和心理认同。一个真诚而温暖的问候能够拉近彼此之间http://soft.shikongyishu.net/synews/22896.html
3.简短欢迎词精彩28篇在现在社会,欢迎词在我们的视野里出现的频率越来越高,一般的欢迎词都是一种礼节性的外交或公关辞令,宜短小精悍,不必长篇大论。欢迎词的注意事项有许多,你确定会写吗? 欢迎词 1 尊敬的各位领导、同志们: 上午好! 5月,是一个充满关爱与温暖的季节;刚刚过去的5月12日,是我国首个“防灾减灾日”。今天,我市迎来https://m.hunwen.com/fanwen/huanyingci/904/904924.html
4.欢迎回来欢迎回来2024-12-10 22:19:12 智慧生活笔记 河北 举报 0 分享至 0:00 / 0:00 速度 洗脑循环 Error: Hls is not supported. 视频加载失败 智慧生活笔记 227粉丝 分享生活小妙招、实用技巧和所见所得,让生活更简单更有趣。 03:16 老美慌了!叙利亚局势再次反转#中东局势最新消息 #叙利亚局势 22:03https://www.163.com/v/video/VUI59N7B5.html
5.土耳其人何以成为德国最多的少数族裔?澎湃号·湃客澎湃新闻三、欢迎欢迎 二战结束后,欧洲大陆上的各个国家都展开了战后的重建和经济恢复工作。面对因为战争而几近废墟的欧洲大陆,当时没有人看好欧洲的前景,甚至有人认为“即使是清除柏林街头的瓦砾,也需要二十年的时间”。 ▲ 战后满是废墟的柏林街头 但欧洲各国原本较好的经济基础,加之欧共体的成立和美国马歇尔计划的援助,战https://www.thepaper.cn/newsDetail_forward_5630593
6.财神爷生日是哪一天?wwp13欢迎欢迎光临我的图书馆!喜欢就请点收 财神生日 中国财神信仰普遍,财神众多。但是主要的是武财神赵公明。 根据国学大师唐德刚的考证,武财神赵公明崇拜的起源有两个,所以赵公明的生日也不同。其一是秦时陕西终南山人士,生日为三月十五;其二为山东天台山”日精“所托化,生日为七月二十二。中国民间传统节日财神节是http://www.360doc.com/content/13/0211/23/11549880_265225162.shtml
7.我害怕昆虫的翻译是:Meafraidofinsects中文翻译英文意思a姆里奇,你现在回来了~欢迎欢迎、我们广州队的小王,祝你快d走出阴影,为广州队夺冠,姆里奇拿最佳球员奖 Mho Ritchie, you came back ~ to welcome, our Guangzhou team's young Wang now, wished your quick d to go out the shadow, won the championship for the Guangzhou team, mho Ritchie took the plahttp://eyu.zaixian-fanyi.com/fan_yi_158459
8.官道最新章节列表,官道快眼看书,官道全文阅读最快最新收集整理的官道最新章节,排版精确。小说《官道》全文阅读内容精彩不断!《官道》是作者“贾国建”创作的作品,欢迎收藏阅读。http://www.xuken.com/html/0/722/index.html
9.换片回望来时路{本帖版聊中,欢迎加入}欢迎欢迎~是准高三吧? 贾不假 对呀对呀( ′ ▽ ` )ノ 回应 2013-06-18 20:35:30 省长沙市天心区黄兴南路309号长郡中学1217班喻晖乔(收)邮编410000 谢谢啦?会认真挑片写满了寄出?我不挑片的哟>< 喜欢什么片呢? 回应 不假 (白玉为堂金作马) 楼主 2013-06-18 20:https://www.douban.com/group/topic/40310890/?cid=489995935
10.表示欢迎都有什么词–手机爱问表示欢迎都有什么词: 表示欢迎的词语有:一、蓬荜生辉 [ péng bì shēng huī ]https://m.iask.sina.com.cn/mib/new2Io6BJE2aQr.html
11.如何只用两个字介绍重庆菜?要讲清楚重庆菜,需要写一篇博士论文。我显然没有那个水平,只能写篇小文,亮明观点。欢迎表扬、欢迎批评,也欢迎谩骂。 用两个字介绍重庆菜 这两个字就是——麻辣。 麻辣,是川菜的主要特点。而重庆菜,是川菜中,把麻辣两个字玩得最好、玩到极致的一个派系。甚至,不管重庆菜有多少毛病,从1980年代开始,重庆菜就是https://www.cqcb.com/hot/2019-06-28/1713006_pc.html
12.抖音直播话术有哪些?抖音直播基本话术介绍运营技巧自媒体6、欢迎各位小伙伴们来到我的直播间,主播性格好,关注就像捡到宝。 7、小伙伴们走过路过不要错过,点击左上角我图像旁边的关注哦! 8、 爱心走一走,活到 99! 下播告别词: 1、主播还有 20 分钟就要下播了,非常感谢大家的陪伴,今天和宝宝们度过了非常愉快的时光哦! https://www.jb51.net/zimeiti/830232.html
13.让梅西苏亚雷斯走不动道的马黛茶,究竟是个啥玩意?马黛茶为何如此受球员欢迎? 马黛茶究竟为什么如此受欢迎?我想,最本质的原因在于它并不是真正的“茶”。 虽然美洲人处理冬青树叶的方式喝中国人处理茶叶的方式类似,但马黛茶并不同于我们常规认知中的“茶”。 马黛茶所含的主要成分马黛因,跟咖啡因成分类似,而每一杯马黛茶中的马黛因含量与同量咖啡中的咖啡因https://www.dongqiudi.com/articles/3075633.html
14.400电话怎么设置?四、录制欢迎提示语音 通过添加欢迎提示语音,可以让客户在打通电话后听到您的问候和相关服务介绍,增强对客户的亲和力和信赖感。录制欢迎提示语音前需要准备好内容,尽量能直观地让客户理解所提供的服务或产品,并能有效地吸引顾客的注意力。 五、设置来电显示 https://400.ihuyi.com/news/265.html
15.大食堂加盟大食堂加盟大概多少钱?加盟总部在哪里?大食堂为什么受大家欢迎? 大食堂之所以受到大家的欢迎,主要有以下几个原因: 1、便捷和经济实惠:大食堂提供了便捷、经济实惠的餐饮选择。人们快节奏的生活和工作压力使得他们寻求方便、快速的就餐方式,而大食堂恰好能够满足这一需求。相比于去餐厅用餐,大食堂通常价格更为亲民,能够提供丰富的菜品选择,让消费者在预算范围https://mip.jiamengfei.com/xm/50100
16.时至今日,韩系车究竟还值不值得入手?说完了现代,我们来看看另一个收欢迎的品牌—起亚。 在国内,起亚与东风汽车公司、江苏悦达投资股份有限公司创立东风悦达起亚品牌。 该品牌的主要产品有K3、K5、智跑、奕跑、KX3、KX5等,涵盖了不同类型的SUV与轿车车型。自2002年成立以来,东风悦达起亚秉持“创中国第一,争世界一流”的信念,稳扎稳打,先后推出了经济https://www.dongchedi.com/article/6753818821766676999
17.最新周记大全(通用74篇)时间一溜烟儿的走了,眨眼间,一个星期已经过去了,相信大家一定感触颇深吧,现在的你想必不是在写周记,就是在准备写周记吧。可是怎样写周记才能出彩呢?以下是小编精心整理的最新周记大全,欢迎大家分享。目录【1】暑假最新周记【6】春节最新周记【2】寒假最新周记【7】校https://www.ruiwen.com/zhouji/4535148.html
18.第一时间e法豫说丨办公软件也不是绝对安全!小心躲在里面的“假悟空” 大河网讯玩转多种办公软件是新时代打工人的必备技能,但是,所有的办公软件都安全吗?是否会存在风险隐患?近日,商丘市互联网信息办公室在工作中发现,其属地某学校运营的“阅卷系统”存在网络 https://news.dahe.cn/dysj/index.html
19.游侠NETSHOW论坛单机游戏游戏攻略心得秘籍游戏补丁单机游戏帖子: 108194235|会员: 31140608|欢迎新会员: 游侠网-GijXDS |查看新帖 搜索 搜索 版块搜索 查找游戏专区推荐使用左侧的版块搜索功能,它支持[拼音简拼,全拼,英文缩写,英文关键词,中文]五种搜索方式 NetShow 游侠新区推荐 一修大师讨论区 (14) 『一修大师专区』 游侠对战平台 『游侠对战平台专区』PC游戏https://game.ali213.net/forum.php
20.新生入学欢迎发言致辞(精选10篇)无论在学习、工作或是生活中,大家对致辞都再熟悉不过了吧,致辞具有“礼仪性”或“仪式化”的特点,要特别注意措辞得体。你还在找寻优秀的致辞吗?下面是小编帮大家整理的新生入学欢迎发言致辞,欢迎阅读,希望大家能够喜欢。 新生入学欢迎发言致辞 1尊敬的各位领导,各https://www.oh100.com/a/202312/7517753.html