简介
Demo基于Open Harmony系统使用ETS语言举行编写,本Demo紧张通过装备认证、分布式拉起、分布式数据管理等功能来实现。
应用结果
- 装备认证,获取同一个局域网内的装备ID,并拉起应用
开发步调
1.新建Openharmony ETS工程
在DevEco Studio中点击File -> New Project ->[Standard]Empty Ability->Next,Language 选择ETS语言,末了点击Finish即创建乐成。
2.界面代码编写
1) 首页界面

- build() {
- Flex({ direction: FlexDirection.Column}) {
- //发现设备
- Button('发现设备', { type: ButtonType.Normal, stateEffect: true })
- .borderRadius(8)
- .backgroundColor(0x317aff).width(90)
- .onClick(() =>{
- this.fun()
- })
- //设备认证
- Button('authDevice', { type: ButtonType.Normal, stateEffect: true })
- .borderRadius(8)
- .backgroundColor(0x317aff).width(90)
- .onClick(() =>{
- this.authDevice()
- })
- // 拉起应用
- Button('拉起应用', { type: ButtonType.Normal, stateEffect: true })
- .borderRadius(8)
- .backgroundColor(0x317aff).width(90)
- .onClick(() =>{
- this.startAb()
- })
- Stack({
- alignContent:Alignment.TopEnd
- }){
- Text('家庭账本')
- .fontSize(20)
- .fontWeight(FontWeight.Bold)
- .width('100%')
- .margin({left:12})
- .onClick(() =>{
- // routePage()
- this.fun()
- })
- Image("/picture/add.png")
- .width(40)
- .height(40)
- .align(Alignment.Start)
- .margin({
- right:12
- }).onClick(() =>{
- routePage()
- })
- }
- .width(350)
- .height(60)
- .margin({
- top:10,
- bottom:10
- })
- Flex({
- direction: FlexDirection.Column, alignItems:ItemAlign.Start,
- }){
- Text("2022年12月")
- .fontSize(20)
- .fontColor(Color.White)
- Text("结余")
- .fontSize(20)
- .fontColor(Color.White)
- .margin({
- top:30
- }).align(Alignment.Start)
- Text("总支出0|总收入0")
- .fontSize(16)
- .fontColor(Color.White)
- .margin({
- top:10
- }).align(Alignment.Start)
- }
- .backgroundColor("#665A5A")
- .height(230)
- .layoutWeight(1)
- .padding(10)
- .onClick(() =>{
- routePage()
- })
- Tabs() {
- TabContent() {
- ProjectList()
- }
- .tabBar("项目")
- TabContent() {
- Statistics()
- }
- .tabBar("统计")
- }
- }
- .width('100%')
- .height('100%')
- .padding({
- left:12,right:12
- })
- }
复制代码 底部TabContent 项目模块
- @Component
- struct ProjectList {
- remoteDataManager = new RemoteDataManager()
- @State ProjectData: Array<any> = []
- TestData:any[] = []
- TestKvData: Array<any> = []
- kvManager = null
- kvStore = null
- STORE_ID = 'store_accountbook'
- aboutToAppear(){
- try {
- const config = {
- userInfo: {
- userId: '0',
- userType: 0
- },
- bundleName: 'com.example.accountbookets'
- }
- factory.createKVManager(config).then((manager) => {
- this.kvManager = manager
- let options =
- {
- createIfMissing: true,
- encrypt: false,
- backup: false,
- autoSync: true,
- kvStoreType: 1,
- securityLevel: 3
- }
- this.kvManager.getKVStore(this.STORE_ID, options).then((store) => {
- this.kvStore = store
- this.kvStore.get("key2").then((data) => {
- this.ProjectData = JSON.parse(data)
- })
- }).catch((err) => {
- })
- }).catch((err) => {
- })
- } catch (e) {
- }
- }
- @Builder ProjectItem(image, name, des,time,money) {
- Flex({ direction: FlexDirection.Row,alignItems: ItemAlign.Center }){
- Image($r("app.media.icon1"))
- .width(30)
- .height(30)
- Column() {
- Text(name)
- .fontSize(16)
- .fontColor(Color.Black)
- Text('11:20')
- .fontSize(16)
- .fontColor(Color.Gray)
- }
- .alignItems(HorizontalAlign.Start)
- .margin({left:15})
- Text('HUAWEI')
- .fontSize(12)
- .fontColor(Color.Black)
- .margin({left:20})
- Text(des)
- .fontSize(14)
- .fontColor(Color.Gray)
- .margin({left:15})
- Column() {
- Text('-100')
- .fontSize(16)
- .fontColor(Color.Black)
- Text(time)
- .fontSize(16)
- .fontColor(Color.Gray)
- }
- .alignItems(HorizontalAlign.Start)
- .margin({left:20})
- }
- .width(400)
- .height(50)
- .margin({top:10})
- }
- build() {
- List() {
- ForEach(this.ProjectData, (item) => {
- ListItem() {
- this.ProjectItem(item.image, item.name, item.des,item.time,item.money)
- }
- .onClick(() => {
- })
- }, (item) => JSON.stringify(item)) {
- }
- }
- }
- }
复制代码 底部TabContent 统计模块
- @Component
- struct Statistics{
- build(){
- Flex({ direction: FlexDirection.Row}){
- Tabs() {
- TabContent() {
- PayList()
- }
- .tabBar("支出分类")
- TabContent() {
- }
- .tabBar("成员分类")
- }
- }
- }
- }
复制代码 统计模块里面的TabContent
- @Component
- struct PayList {
- private PayData: PayBean[] = initializeOnStartup()
- @Builder PayItem(previewUrl, title, describe) {
- Flex({ direction: FlexDirection.Row,alignItems: ItemAlign.Center }){
- Image(previewUrl)
- .width(30)
- .height(30)
- Text(title)
- .fontSize(16)
- .fontColor(Color.Black)
- .margin({left:8})
- Text('100%')
- .fontSize(12)
- .fontColor(Color.Black)
- .margin({left:8})
- Progress({ value: 20, total: 150, style: ProgressStyle.Linear }).color(Color.Red).value(150).width(200)
- Text('-100')
- .fontSize(14)
- .fontColor(Color.Gray)
- .margin({left:8})
- }
- .width(400)
- .height(50)
- .margin({top:10})
- }
- build() {
- List() {
- ForEach(this.PayData, (item) => {
- ListItem() {
- this.PayItem(item.image, item.name, item.des)
- }
- .onClick(() => {
- console.info("点击我")
- router.push({
- uri: "pages/VideoPlayer",
- })
- })
- }, (item) => JSON.stringify(item)) {
- }
- }
- }
- }
复制代码 2) add.ets页面

- build() {
- Flex({ direction: FlexDirection.Column,alignItems: ItemAlign.Center}) {
- Flex({ direction: FlexDirection.Row,alignItems: ItemAlign.Center})
- {
- Image("/picture/icon_back.png")
- .width(35)
- .height(35)
- .onClick(() =>{
- router.push({
- uri: "pages/index",
- })
- })
- Text("加一笔")
- .fontSize(20)
- .fontWeight(FontWeight.Bold)
- .margin({left:20})
- }.margin({top:10})
- .padding({left:20})
- .height(100)
- .width(500)
- Stack({
- alignContent: Alignment.TopStart
- }){
- Tabs() {
- TabContent() {
- pay({payTime:$strTime,payRemark:$strRemark,payType:$strType})
- }
- .tabBar("支出")
- TabContent() {
- Income()
- }
- .tabBar("收入")
- }
- .height(450)
- }.width(500)
- .height(500)
- Flex({
- direction: FlexDirection.Row,alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center
- }){
- Text("输入金额")
- .fontColor(Color.Black)
- .fontSize(20)
- .margin({
- right:15
- })
- .width(100)
- TextInput({ placeholder: '100', text:this.strMoney })
- .type(InputType.Normal)
- .placeholderColor(Color.Gray)
- .placeholderFont({ size: 20, weight: 2})
- .enterKeyType(EnterKeyType.Search)
- .caretColor(Color.Green)
- .width(250)
- .height(40)
- .borderRadius('20px')
- }
- .width(400)
- .height(50)
- Text('保存')
- .fontColor(Color.White)
- .fontSize(20)
- .margin({
- top:20
- })
- .textAlign(TextAlign.Center)
- .width(380)
- .height(80)
- .backgroundColor("#FE4F16")
- .onClick(() =>{
- TestData.push({image:"/picture/icon1.png",title:'canyin',des:'ceshi',time:'2021',money:'50'})
- if (AppStorage.Get("key1") == null) {
- AppStorage.SetAndLink("key1", TestData)
- this.remoteDataManager.dataChange("key2", JSON.stringify(TestData))
- }else{
- this.TestStorageData = AppStorage.Get("key1")
- //
- // this.TestStorageData.push({image:"/picture/icon1.png",title:'canyin',des:'beizhu',time:'2021',money:'50'})
- //具体代码
- this.TestStorageData.push({image:"/picture/icon1.png",title:this.strType,des:this.strRemark,time:this.strTime,money:this.strMoney})
- AppStorage.SetAndLink("key1", this.TestStorageData)
- let str = JSON.stringify(this.TestStorageData)
- this.TestKvData = JSON.parse(str)
- this.remoteDataManager.dataChange("key2", JSON.stringify(this.TestKvData))
- }
- router.push({
- uri: "pages/index",
- })
- })
- }
- .width('100%')
- .height('100%')
- }
复制代码 add页面付出模块
- @Component
- struct pay{
- @Link payTime:string
- @Link payRemark:string
- @Link payType:string
- @State private index:number = 0
- @State strType:string = "canyin"
- @State AccountData: Array<any> = [
- { previewUrl: "/picture/icon1.png", title: "canyin" ,number:0},
- { previewUrl: "/picture/icon2_2.png", title: "gouwu" ,number:1},
- { previewUrl: "/picture/icon3_3.png", title: "jiaotong" ,number:2},
- { previewUrl: "/picture/icon4_4.png", title: "fuwu" ,number:3},
- { previewUrl: "/picture/icon5_5.png", title: "jiaoyu" ,number:4},
- { previewUrl: "/picture/icon6_6.png", title: "yundong" ,number:5},
- { previewUrl: "/picture/icon7_7.png", title: "luxing" ,number:6},
- { previewUrl: "/picture/icon8_8.png", title: "yiliao" ,number:7},
- // { previewUrl: "/picture/icon9_9.png", title: "生活" ,number:9},
- // { previewUrl: "/picture/icon10_10.png", title: "宠物" ,number:10},
- ]
- @Builder ProItem(previewUrl, title,number) {
- Stack() {
- Flex({
- direction: FlexDirection.Column
- }) {
- if (this.index == number) {
- if (number == 0) {
- Image("/picture/icon1.png")
- .width(60)
- .height(60)
- }else if (number == 1) {
- Image("/picture/icon2.png")
- .width(60)
- .height(60)
- }else if (number == 2) {
- Image("/picture/icon3.png")
- .width(60)
- .height(60)
- }else if (number == 3) {
- Image("/picture/icon4.png")
- .width(60)
- .height(60)
- }else if (number == 4) {
- Image("/picture/icon5.png")
- .width(60)
- .height(60)
- }else if (number == 5) {
- Image("/picture/icon6.png")
- .width(60)
- .height(60)
- }else if (number == 6) {
- Image("/picture/icon7.png")
- .width(60)
- .height(60)
- }else if (number == 7) {
- Image("/picture/icon8.png")
- .width(60)
- .height(60)
- }else if (number == 8) {
- Image("/picture/icon9.png")
- .width(60)
- .height(60)
- }else if (number == 9) {
- Image("/picture/icon10.png")
- .width(60)
- .height(60)
- }
- }else{
- if (number == 0) {
- Image("/picture/icon1_1.png")
- .width(60)
- .height(60)
- }else{
- Image(previewUrl)
- .width(60)
- .height(60)
- }
- }
- Column() {
- Text(title)
- .fontSize(16)
- .fontColor(Color.Black)
- }
- .alignItems(HorizontalAlign.Center)
- }
- }
- .height(100)
- .width(100)
- .margin({
- bottom: 16
- })
- }
- build(){
- Flex({direction: FlexDirection.Column}){
- Grid(){
- ForEach(this.AccountData, (item) => {
- GridItem() {
- this.ProItem(item.previewUrl, item.title,item.number)
- }
- .onClick(() => {
- console.info("点击我")
- this.index = item.number
- this.payType = this.AccountData[this.index].title
- })
- }, (item) => JSON.stringify(item)) {
- }
- }
- .rowsTemplate('1fr 1fr')
- .columnsTemplate('1fr 1fr 1fr 1fr')
- .columnsGap(8)
- .rowsGap(8)
- .height(200)
- // Time()
- // Remark()
- // ******************时间**********************
- Flex({
- direction: FlexDirection.Row,alignItems: ItemAlign.Center
- }){
- Text("时间")
- .fontColor(Color.Black)
- .fontSize(20)
- .margin({
- right:15
- })
- .width(70)
- TextInput({ placeholder: '输入收支时间', text: this.payTime })
- .type(InputType.Normal)
- .placeholderColor(Color.Gray)
- .placeholderFont({ size: 20, weight: 2})
- .enterKeyType(EnterKeyType.Search)
- .caretColor(Color.Green)
- .width(300)
- .height(40)
- .borderRadius('20px')
- .backgroundColor(Color.White)
- .onChange((value: string) => {
- this.payTime = value
- })
- }
- .margin({
- top:20,left:15
- })
- .width(200)
- //*******************备注********************
- Flex({
- direction: FlexDirection.Row,alignItems: ItemAlign.Center
- }){
- Text("备注")
- .fontColor(Color.Black)
- .fontSize(20)
- .margin({
- right:15
- })
- .width(70)
- TextInput({ placeholder: '输入说明', text: this.payRemark })
- .type(InputType.Normal)
- .placeholderColor(Color.Gray)
- .placeholderFont({ size: 20, weight: 2})
- .enterKeyType(EnterKeyType.Search)
- .caretColor(Color.Green)
- // .layoutWeight(8)
- .height(40)
- .width(300)
- .borderRadius('20px')
- .backgroundColor(Color.White)
- .onChange((value: string) => {
- this.payRemark = value
- })
- }
- .margin({
- top:20,left:15
- })
- .width(50)
- .height(50)
- }
- .height('100%')
- .layoutWeight(1)
- }
- }
复制代码 收入模块代码
- @Component
- struct Income{
- build(){
- Flex({direction: FlexDirection.Column}){
- Time()
- Remark()
- }
- }
- }
复制代码 时间模块
- @Component
- struct Time{
- @State inputTime:string = ''
- build(){
- Flex({
- direction: FlexDirection.Row,alignItems: ItemAlign.Center
- }){
- Text("时间")
- .fontColor(Color.Black)
- .fontSize(20)
- .margin({
- right:15
- })
- .width(70)
- TextInput({ placeholder: '2021', text: this.inputTime })
- .type(InputType.Normal)
- .placeholderColor(Color.Gray)
- .placeholderFont({ size: 20, weight: 2})
- .enterKeyType(EnterKeyType.Search)
- .caretColor(Color.Green)
- .width(300)
- .height(40)
- .borderRadius('20px')
- .backgroundColor(Color.White)
- }
- .margin({
- top:20,left:15
- })
- .width(200)
- }
- }
复制代码 备注模块
- @Component
- struct Remark{
- @State inputRemark:string = ''
- build(){
- Flex({
- direction: FlexDirection.Row,alignItems: ItemAlign.Center
- }){
- Text("备注")
- .fontColor(Color.Black)
- .fontSize(20)
- .margin({
- right:15
- })
- .width(70)
- TextInput({ placeholder: 'ceshe', text: this.inputRemark })
- .type(InputType.Normal)
- .placeholderColor(Color.Gray)
- .placeholderFont({ size: 20, weight: 2})
- .enterKeyType(EnterKeyType.Search)
- .caretColor(Color.Green)
- // .layoutWeight(8)
- .height(40)
- .width(300)
- .borderRadius('20px')
- .backgroundColor(Color.White)
- }
- .margin({
- top:20,left:15
- })
- .width(50)
- .height(50)
- }
- }
复制代码 3.装备认证
装备认证是依赖DeviceManager组件来实现的,详细代码参考源码RemoteDeviceModel.ets
1.创建DeviceManager实例
- registerDeviceListCallback(callback) {
- if (typeof (this.#deviceManager) === 'undefined') {
- deviceManager.createDeviceManager('com.example.tictactoegame', (error, value) => {
- if (error) return
- this.#deviceManager = value;
- this.registerDeviceListCallback_(callback);
- });
- } else {
- this.registerDeviceListCallback_(callback);
- }
- }
复制代码 2.查询可信装备列表
- var list = this.#deviceManager.getTrustedDeviceListSync();
- if (typeof (list) != 'undefined' && typeof (list.length) != 'undefined') {
- this.deviceList = list;
- }
复制代码 3.注册装备上下线监听
- this.#deviceManager.on('deviceStateChange', (data) => {
- switch (data.action) {
- case 0:
- this.deviceList[this.deviceList.length] = data.device;
- this.callback();
- if (this.authCallback != null) {
- this.authCallback();
- this.authCallback = null;
- }
- break;
- case 2:
- if (this.deviceList.length > 0) {
- for (var i = 0; i < this.deviceList.length; i++) {
- if (this.deviceList[i].deviceId === data.device.deviceId) {
- this.deviceList[i] = data.device;
- break;
- }
- }
- }
- this.callback();
- break;
- case 1:
- if (this.deviceList.length > 0) {
- var list = [];
- for (var i = 0; i < this.deviceList.length; i++) {
- if (this.deviceList[i].deviceId != data.device.deviceId) {
- list[i] = data.device;
- }
- }
- this.deviceList = list;
- }
- this.callback();
- break;
- default:
- break;
- }
- });
复制代码 4.装备发现
- this.#deviceManager.on('deviceFound', (data) => {
- for (let i = 0; i < this.discoverList.length; i++) {
- if (that.discoverList[i].deviceId === data.device.deviceId) {
- return;
- }
- }
- this.discoverList[this.discoverList.length] = data.device;
- this.callback();
- });
复制代码 5.装备认证
- authDevice(deviceInfo, callback){
- let extraInfo = {
- "targetPkgName": 'com.example.tictactoegame',
- "appName": 'com.example.tictactoegame',
- "appDescription": 'com.example.tictactoegame',
- "business": '0'
- };
- let authParam = {
- "authType": 1,
- "appIcon": '',
- "appThumbnail": '',
- "extraInfo": extraInfo
- };
- this.#deviceManager.authenticateDevice(deviceInfo, authParam, (err, data) => {
- if (err) {
- this.authCallback = null;
- } else {
- this.authCallback = callback;
- }
- });
- }
复制代码 4.数据管理
分布式数据管理依赖@ohos.data.distributedData模块实现,详细参考源码RemoteDataManager.ets
1.导入该模块
- import factory from '@ohos.data.distributedData';
复制代码 2.创建KVManager实例,用于管理数据库对象
- registerDataListCallback(callback) {
- let that = this
- if (this.kvManager == null) {
- try {
- const config = {
- userInfo: {
- userId: '0',
- userType: 0
- },
- bundleName: 'com.example.tictactoegame'
- }
- factory.createKVManager(config).then((manager) => {
- that.kvManager = manager
- that.registerDataListCallback_(callback)
- }).catch((err) => {
- })
- } catch (e) {
- }
- } else {
- this.registerDataListCallback_(callback)
- }
- }
复制代码 3.创建并获取KVStore数据库
- registerDataListCallback_(callback) {
- let that = this
- if (that.kvManager == null) {
- callback()
- return
- }
- if (that.kvStore == null) {
- try {
- let options =
- {
- createIfMissing: true,
- encrypt: false,
- backup: false,
- autoSync: true,
- kvStoreType: 1,
- securityLevel: 3
- }
- this.kvManager.getKVStore(this.STORE_ID, options).then((store) => {
- that.kvStore = store
- that._registerDataListCallback_(callback)
- }).catch((err) => {
- })
- } catch (e) {
- }
- } else {
- this._registerDataListCallback_(callback)
- }
- }
复制代码 4.订阅指定类型的数据变更通知
- _registerDataListCallback_(callback) {
- let that = this
- if (that.kvManager == null) {
- callback()
- return
- }
- this.kvStore.on('dataChange', 1, function(data) {
- if (data) {
- that.arr = data.updateEntries
- callback()
- }
- })
- }
复制代码 5.添加指定类型键值对到数据库
- dataChange(key, value) {
- let that = this
- try {
- that.kvStore.put(JSON.stringify(key), JSON.stringify(value)).then((data) => {
- }).catch((err) => {
- prompt.showToast({message:'put err:'+JSON.stringify(value)})
- })
- } catch (e) {
- }
- }
复制代码 5.长途拉起装备app
使用FeatureAbility模块的startAbility接口拉起长途装备app
- startAbilityContinuation(deviceId) {
- let wantValue = {
- bundleName: 'com.example.tictactoegame',
- abilityName: 'com.example.tictactoegame.MainAbility',
- deviceId: deviceId,
- parameters: {
- uri: 'pages/Fight'
- }
- };
- featureAbility.startAbility({ want: wantValue }).then(() => {
- router.replace({ uri: 'pages/Fight' })
- });
- }
复制代码 6.添加数据
新建一个账单数据 添加到分布式数据
- this.remoteDataManager.dataChange("key2", JSON.stringify(this.TestKvData))
复制代码 在另一台装备监听并获取显示该条数据
- private onPageShow() {
- this.remoteDataManager.registerDataListCallback(() => {
- let arr = this.remoteDataManager.arr[0]
- this.strTest = arr.value.value
- this.ProjectData = JSON.parse(this.strTest)
-
- }
复制代码 末了,有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道必要重点把握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(Harmony NEXT)资料用来跟着学习是非常有须要的。
为了可以或许资助各人快速把握鸿蒙(Harmony NEXT)应用开发技术知识。在此给各人分享一下我结合鸿蒙最新资料整理出来的鸿蒙南北向开发学习路线以及整理的最新版鸿蒙学习文档资料。
这份鸿蒙(Harmony NEXT)资料包含了鸿蒙开发必把握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模子、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(Harmony NEXT)技术知识点。
希望这一份鸿蒙学习资料可以或许给各人带来资助,有必要的小伙伴自行领取,限时开源,先到先得~无套路领取!!
如果你是一名有经验的资深Android移动开发、Java开发、前端开发、对鸿蒙感爱好以及转行人员,可以直接领取这份资料
获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
鸿蒙(Harmony NEXT)最新学习路线
- HarmonOS就业必备技能
- HarmonOS多媒体技术
有了路线图,怎么能没有学习资料呢,小编也准备了一份连合鸿蒙官方发布条记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门讲授视频,内容包含:ArkTS、ArkUI、Web开发、应用模子、资源分类…等知识点。
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
《鸿蒙 (OpenHarmony)开发入门讲授视频》
《鸿蒙生态应用开发V2.0白皮书》
《鸿蒙 (OpenHarmony)开发基础到实战手册》
OpenHarmony北向、南向开发环境搭建
《鸿蒙开发基础》
- ArkTS语言
- 安装DevEco Studio
- 运用你的第一个ArkTS应用
- ArkUI声明式UI开发
- .……
《鸿蒙开发进阶》
- Stage模子入门
- 网络管理
- 数据管理
- 电话服务
- 分布式应用开发
- 通知与窗口管理
- 多媒体技术
- 安全技能
- 任务管理
- WebGL
- 国际化开发
- 应用测试
- DFX面向未来计划
- 鸿蒙系统移植和裁剪定制
- ……
《鸿蒙进阶实战》
- ArkTS实践
- UIAbility应用
- 网络案例
- ……
获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料
总结
总的来说,华为鸿蒙不再兼容安卓,对中年步伐员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个厘革的期间中立于不败之地。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |