[文章]

HarmonyOS(鸿蒙)运动手表第一个小游戏app——黑白翻棋

2020-12-2 16:57:57  529 鸿蒙系统 APP
分享
0
创建项目文件DevEco Studio下载成功后,点击左上角的File,点击New,再选择New Project,选择Lite Wearable选项,选择默认的模板,然后选择保存路径,将文件命名为MyGame(文件名不能出现中文或者特殊字符,否则将无法成功创建项目文件),如图所示。


主要编写的文件为index.css、index.hml和index.js,打开路径如图所示,index.hml用于描述页面中包含哪些组件,index.css用于描述页面中的组件都长什么样,index.js用于描述页面中的组件是如何进行交互的。

实现开始界面的布局首先我们要先在运动手表上画出一个7*7的棋盘,色块颜色先设定为全是白色,棋盘上方显示“当前步数:0”,棋盘下方有一个“重新开始”的按钮,如图所示:

  • 首先在index.hml文件中创建一个基础容器div类名为container
<div class="container" ></div>在此容器中间添加一个文字组件text类名为steps,并且写上显示的固定部分“当前步数:”,为动态变换部分赋予一个名为currentSteps的变量
<text class="steps">        当前步数:{   {   currentSteps}}    </text>再添加一个画布组件canvas类名为canvas,增加一个引用属性ref,以便在此画布上画出7*7表格
<canvas class="canvas" ref="canvas" ></canvas>最后添加一个普通按钮,类名为bit,并赋值“重新开始”
<input type="button" value="重新开始" class="bit" />至此,index.hml文件已经全部编写完成了
<div class="container" >    <text class="steps">        当前步数:{   {   currentSteps}}    </text>    <canvas class="canvas" ref="canvas" ></canvas>    <input type="button" value="重新开始" class="bit" /></div>
  • 在index.css编写刚才添加组件的样式,首先编写container的样式,flex-direction为容器主轴方向,选择column(垂直方向从上到下),justIFy-content为容器当前行的主轴对齐格式,选择center(项目位于容器的中心),align-items为容器当前行的交叉轴对齐格式,选择center(元素在交叉轴居中),width、height分别为容器以像素为单位的宽度和高度,都设定为450px
.container {       flex-direction: column;    justify-content: center;    align-items: center;    width:450px;    height:450px;}编写steps的样式,font-size为设置文本的尺寸,设定为18px,text-align为设置文本的文本对齐方式,选择center(文本居中对齐),width、height分别设定为300px和20px,letter-spacing为设置文本的字符间距,设定为0px,margin-top为设置上外边距,设定为10px
.steps {       font-size: 18px;    text-align:center;    width:300px;    height:20px;    letter-spacing:0px;    margin-top:10px;}编写canvas的样式,width、height都设定为320px,background-color为设置背景颜色,设定为#BBADA0
.canvas{       width:320px;    height:320px;    background-color: #BBADA0;}编写bit的样式,width、height分别设定为150px和30px,background-color设定为#AD9D8F,font-size设定为24px,margin-top设定为10px
.bit{       width:150px;    height:30px;    background-color:#AD9D8F;    font-size:24px;    margin-top:10px;}至此,index.css文件已经全部编写完成了
.container {       flex-direction: column;    justify-content: center;    align-items: center;    width:450px;    height:450px;}.steps {       font-size: 18px;    text-align:center;    width:300px;    height:20px;    letter-spacing:0px;    margin-top:10px;}.canvas{       width:320px;    height:320px;    background-color: #BBADA0;}.bit{       width:150px;    height:30px;    background-color:#AD9D8F;    font-size:24px;    margin-top:10px;}
  • 在index.js编写描述页面中的组件是如何进行交互的,首先在data函数中为当前步数赋值为0
data: {           currentSteps: 0,    }在文件开头定义一个全局变量量context,创建一个onReady()函数,用于定义2d绘画工具
var context;onReady(){           context=this.$refs.canvas.getContext('2d');    }用0表示白色,1代表黑色,这样我们就能定义一个用0和1表示键,颜色表示值的字典COLORS,并且定义全局常量边长SIDELEN为40,间距MARGIN为5,定义一个全局变量的二维数组grids,其中的值全为0
var grids=[[0, 0, 0, 0, 0, 0, 0],           [0, 0, 0, 0, 0, 0, 0],           [0, 0, 0, 0, 0, 0, 0],           [0, 0, 0, 0, 0, 0, 0],           [0, 0, 0, 0, 0, 0, 0],           [0, 0, 0, 0, 0, 0, 0],           [0, 0, 0, 0, 0, 0, 0],           [0, 0, 0, 0, 0, 0, 0]];const SIDELEN=40;const MARGIN=5;const COLORS = {       "0": "#FFFFFF",    "1": "#000000",}创建drawGrids()函数,先将grids的值利用toString()函数全部转化为字符串,fillStyle表社画图的背景颜色,引用字典即可,fillRect表示画矩形的大小,其中有四个参数,第一个参数指定矩形左上角的x坐标,第二参数指定矩形左上角的y坐标,第三个参数指定矩形的高度,第四个参数指定矩形的宽度,最后创建onShow()调用drawGrids()函数即可
onShow(){           this.drawGrids();    },    drawGrids(){           for (let row = 0 ;row < 7 ;row++){               for (let column = 0; column < 7;column++){                   let gridStr = grids[row][column].toString();                context.fillStyle = COLORS[gridStr];                let leftTopX = column * (MARGIN + SIDELEN) + MARGIN;                let leftTopY = row * (MARGIN + SIDELEN) + MARGIN;                context.fillRect(leftTopX, leftTopY, SIDELEN, SIDELEN);            }        }    }至此,index.js文件已经全部编写完成了,运行即可得出开始界面布局了
var grids=[[0, 0, 0, 0, 0, 0, 0],           [0, 0, 0, 0, 0, 0, 0],           [0, 0, 0, 0, 0, 0, 0],           [0, 0, 0, 0, 0, 0, 0],           [0, 0, 0, 0, 0, 0, 0],           [0, 0, 0, 0, 0, 0, 0],           [0, 0, 0, 0, 0, 0, 0],           [0, 0, 0, 0, 0, 0, 0]];var context;const SIDELEN=40;const MARGIN=5;const COLORS = {       "0": "#FFFFFF",    "1": "#000000",}export default {       data: {           currentSteps: 0,    },    onReady(){           context=this.$refs.canvas.getContext('2d');    },    onShow(){           this.drawGrids();    },    drawGrids(){           for (let row = 0 ;row < 7 ;row++){               for (let column = 0; column < 7;column++){                   let gridStr = grids[row][column].toString();                context.fillStyle = COLORS[gridStr];                let leftTopX = column * (MARGIN + SIDELEN) + MARGIN;                let leftTopY = row * (MARGIN + SIDELEN) + MARGIN;                context.fillRect(leftTopX, leftTopY, SIDELEN, SIDELEN);            }        }    }}实现题目的随机生成和色块的翻转其次我们要先在运动手表上随机生成一个色块被打乱的7*7的棋盘,并且点击棋盘中任一色块,其上下左右四个色块也会跟着一起变色(在边缘的色块则只会改变其中若干个色块的颜色),棋盘上方的当前步数则会相应依次增加,如图所示:


1.为了使点击任意一个色块时能得到其对应的二维数组的下标,我们需要给每个色块添加一个按钮button,并增加一个点击事件click,分别给这些按钮设定一个类名和点击按钮所调用的函数然后为了使按钮显示在棋盘格子的上方,需要添加一个栈stack类名设定位stack,使画布先进栈,按钮后进栈,这样就能达到预期效果了,index.hml代码如下:
<div class="container" >    <text class="steps">        当前步数:{   {   currentSteps}}    </text>    <stack class="stack">        <canvas class="canvas" ref="canvas" ></canvas>        <input type="button" class="bitgrid1"  onclick="getgrid1"/>        <input type="button" class="bitgrid2"  onclick="getgrid2"/>        <input type="button" class="bitgrid3"  onclick="getgrid3"/>        <input type="button" class="bitgrid4"  onclick="getgrid4"/>        <input type="button" class="bitgrid5"  onclick="getgrid5"/>        <input type="button" class="bitgrid6"  onclick="getgrid6"/>        <input type="button" class="bitgrid7"  onclick="getgrid7"/>        <input type="button" class="bitgrid8"  onclick="getgrid8"/>        <input type="button" class="bitgrid9"  onclick="getgrid9"/>        <input type="button" class="bitgrid10"  onclick="getgrid10"/>        <input type="button" class="bitgrid11"  onclick="getgrid11"/>        <input type="button" class="bitgrid12"  onclick="getgrid12"/>        <input type="button" class="bitgrid13"  onclick="getgrid13"/>        <input type="button" class="bitgrid14"  onclick="getgrid14"/>        <input type="button" class="bitgrid15"  onclick="getgrid15"/>        <input type="button" class="bitgrid16"  onclick="getgrid16"/>        <input type="button" class="bitgrid17"  onclick="getgrid17"/>        <input type="button" class="bitgrid18"  onclick="getgrid18"/>        <input type="button" class="bitgrid19"  onclick="getgrid19"/>        <input type="button" class="bitgrid20"  onclick="getgrid20"/>        <input type="button" class="bitgrid21"  onclick="getgrid21"/>        <input type="button" class="bitgrid22"  onclick="getgrid22"/>        <input type="button" class="bitgrid23"  onclick="getgrid23"/>        <input type="button" class="bitgrid24"  onclick="getgrid24"/>        <input type="button" class="bitgrid25"  onclick="getgrid25"/>        <input type="button" class="bitgrid26"  onclick="getgrid26"/>        <input type="button" class="bitgrid27"  onclick="getgrid27"/>        <input type="button" class="bitgrid28"  onclick="getgrid28"/>        <input type="button" class="bitgrid29"  onclick="getgrid29"/>        <input type="button" class="bitgrid30"  onclick="getgrid30"/>        <input type="button" class="bitgrid31"  onclick="getgrid31"/>        <input type="button" class="bitgrid32"  onclick="getgrid32"/>        <input type="button" class="bitgrid33"  onclick="getgrid33"/>        <input type="button" class="bitgrid34"  onclick="getgrid34"/>        <input type="button" class="bitgrid35"  onclick="getgrid35"/>        <input type="button" class="bitgrid36"  onclick="getgrid36"/>        <input type="button" class="bitgrid37"  onclick="getgrid37"/>        <input type="button" class="bitgrid38"  onclick="getgrid38"/>        <input type="button" class="bitgrid39"  onclick="getgrid39"/>        <input type="button" class="bitgrid40"  onclick="getgrid40"/>        <input type="button" class="bitgrid41"  onclick="getgrid41"/>        <input type="button" class="bitgrid42"  onclick="getgrid42"/>        <input type="button" class="bitgrid43"  onclick="getgrid43"/>        <input type="button" class="bitgrid44"  onclick="getgrid44"/>        <input type="button" class="bitgrid45"  onclick="getgrid45"/>        <input type="button" class="bitgrid46"  onclick="getgrid46"/>        <input type="button" class="bitgrid47"  onclick="getgrid47"/>        <input type="button" class="bitgrid48"  onclick="getgrid48"/>        <input type="button" class="bitgrid49"  onclick="getgrid49"/>    </stack>    <input type="button" value="重新开始" class="bit" /></div>
  • 编写stack的样式,width、height都设定为320px,margin-top设定为10px
.stack{       width: 320px;    height: 320px;    margin-top: 10px;}分别编写每个按钮的样式,left为指示距边界框左上角的以像素为单位的水平坐标,top为指示距边界框左上角的以像素为单位的垂直坐标,border-color为设置边框颜色,transparent指透明颜色
.bitgrid1{       left:5px;    top:5px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid2{       left:50px;    top:5px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid3{       left:95px;    top:5px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid4{       left:140px;    top:5px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid5{       left:185px;    top:5px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid6{       left:230px;    top:5px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid7{       left:275px;    top:5px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid8{       left:5px;    top:50px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid9{       left:50px;    top:50px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid10{       left:95px;    top:50px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid11{       left:140px;    top:50px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid12{       left:185px;    top:50px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid13{       left:230px;    top:50px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid14{       left:275px;    top:50px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid15{       left:5px;    top:95px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid16{       left:50px;    top:95px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid17{       left:95px;    top:95px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid18{       left:140px;    top:95px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid19{       left:185px;    top:95px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid20{       left:230px;    top:95px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid21{       left:275px;    top:95px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid22{       left:5px;    top:140px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid23{       left:50px;    top:140px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid24{       left:95px;    top:140px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid25{       left:140px;    top:140px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid26{       left:185px;    top:140px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid27{       left:230px;    top:140px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid28{       left:275px;    top:140px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid29{       left:5px;    top:185px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid30{       left:50px;    top:185px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid31{       left:95px;    top:185px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid32{       left:140px;    top:185px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid33{       left:185px;    top:185px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid34{       left:230px;    top:185px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid35{       left:275px;    top:185px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid36{       left:5px;    top:230px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid37{       left:50px;    top:230px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid38{       left:95px;    top:230px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid39{       left:140px;    top:230px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid40{       left:185px;    top:230px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid41{       left:230px;    top:230px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid42{       left:275px;    top:230px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid43{       left:5px;    top:275px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid44{       left:50px;    top:275px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid45{       left:95px;    top:275px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid46{       left:140px;    top:275px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid47{       left:185px;    top:275px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid48{       left:230px;    top:275px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}.bitgrid49{       left:275px;    top:275px;    width:40px;    height:40px;    border-color:transparent;    background-color:transparent;}至此,增加的组件样式已经全部设定完毕了。
3. 先增加一个函数change(x,y),接受二维数组的下标,用来改变二维数字的值,如果值为0 则改为1,如果值为1则改为0,这样对应的色块颜色也能跟着发生变化
change(x,y){           if(grids[x][y] == 0){               grids[x][y] = 1;        }else if(grids[x][y] == 1) {               grids[x][y] = 0;        }    }之后增加一个函数changeOneGrids(x,y),接受二维数组的下标,调用刚才编写的函数change(x,y),改变其上下左右四个色块对应的二维数组的值,并且调用函数drawGrids()重新画图实现颜色的变化,再使当前步数加1
changeOneGrids(x,y){           if(x>-1 && y>-1 && x<7 && y<7){               this.change(x,y);        }        if(x+1>-1 && y>-1 && x+1<7 && y<7){               this.change(x+1,y);        }        if(x-1>-1 && y>-1 && x-1<7 && y<7){               this.change(x-1,y);        }        if(x>-1 && y+1>-1 && x<7 && y+1<7){               this.change(x,y+1);        }        if(x>-1 && y-1>-1 && x<7 && y-1<7){               this.change(x,y-1);        }        this.drawGrids();        this.currentSteps+=1;    }再编写49个按钮对应的49个函数,作用是读取当前二维数组位置的下标,并且调用函数changeOneGrids(x,y)
getgrid1(){           let x = 0;        let y = 0;        this.changeOneGrids(x,y);    },    getgrid2(){           let x = 0;        let y = 1;        this.changeOneGrids(x,y);    },    getgrid3(){           let x = 0;        let y = 2;        this.changeOneGrids(x,y);    },    getgrid4(){           let x = 0;        let y = 3;        this.changeOneGrids(x,y);    },    getgrid5(){           let x = 0;        let y = 4;        this.changeOneGrids(x,y);    },    getgrid6(){           let x = 0;        let y = 5;        this.changeOneGrids(x,y);    },    getgrid7(){           let x = 0;        let y = 6;        this.changeOneGrids(x,y);    },    getgrid8(){           let x = 1;        let y = 0;        this.changeOneGrids(x,y);    },    getgrid9(){           let x = 1;        let y = 1;        this.changeOneGrids(x,y);    },    getgrid10(){           let x = 1;        let y = 2;        this.changeOneGrids(x,y);    },    getgrid11(){           let x = 1;        let y = 3;        this.changeOneGrids(x,y);    },    getgrid12(){           let x = 1;        let y = 4;        this.changeOneGrids(x,y);    },    getgrid13(){           let x = 1;        let y = 5;        this.changeOneGrids(x,y);    },    getgrid14(){           let x = 1;        let y = 6;        this.changeOneGrids(x,y);    },    getgrid15(){           let x = 2;        let y = 0;        this.changeOneGrids(x,y);    },    getgrid16(){           let x = 2;        let y = 1;        this.changeOneGrids(x,y);    },    getgrid17(){           let x = 2;        let y = 2;        this.changeOneGrids(x,y);    },    getgrid18(){           let x = 2;        let y = 3;        this.changeOneGrids(x,y);    },    getgrid19(){           let x = 2;        let y = 4;        this.changeOneGrids(x,y);    },    getgrid20(){           let x = 2;        let y = 5;        this.changeOneGrids(x,y);    },    getgrid21(){           let x = 2;        let y = 6;        this.changeOneGrids(x,y);    },    getgrid22(){           let x = 3;        let y = 0;        this.currentSteps += 1;        this.changeOneGrids(x,y);    },    getgrid23(){           let x = 3;        let y = 1;        this.changeOneGrids(x,y);    },    getgrid24(){           let x = 3;        let y = 2;        this.changeOneGrids(x,y);    },    getgrid25(){           let x = 3;        let y = 3;        this.changeOneGrids(x,y);    },    getgrid26(){           let x = 3;        let y = 4;        this.changeOneGrids(x,y);    },    getgrid27(){           let x = 3;        let y = 5;        this.changeOneGrids(x,y);    },    getgrid28(){           let x = 3;        let y = 6;        this.changeOneGrids(x,y);    },    getgrid29(){           let x = 4;        let y = 0;        this.changeOneGrids(x,y);    },    getgrid30(){           let x = 4;        let y = 1;        this.changeOneGrids(x,y);    },    getgrid31(){           let x = 4;        let y = 2;        this.changeOneGrids(x,y);    },    getgrid32(){           let x = 4;        let y = 3;        this.changeOneGrids(x,y);    },    getgrid33(){           let x = 4;        let y = 4;        this.changeOneGrids(x,y);    },    getgrid34(){           let x = 4;        let y = 5;        this.changeOneGrids(x,y);    },    getgrid35(){           let x = 4;        let y = 6;        this.changeOneGrids(x,y);    },    getgrid36(){           let x = 5;        let y = 0;        this.changeOneGrids(x,y);    },    getgrid37(){           let x = 5;        let y = 1;        this.changeOneGrids(x,y);    },    getgrid38(){           let x = 5;        let y = 2;        this.currentSteps += 1;        this.changeOneGrids(x,y);    },    getgrid39(){           let x = 5;        let y = 3;        this.changeOneGrids(x,y);    },    getgrid40(){           let x = 5;        let y = 4;        this.changeOneGrids(x,y);    },    getgrid41(){           let x = 5;        let y = 5;        this.changeOneGrids(x,y);    },    getgrid42(){           let x = 5;        let y = 6;        this.changeOneGrids(x,y);    },    getgrid43(){           let x = 6;        let y = 0;        this.changeOneGrids(x,y);    },    getgrid44(){           let x = 6;        let y = 1;        this.changeOneGrids(x,y);    },    getgrid45(){           let x = 6;        let y = 2;        this.changeOneGrids(x,y);    },    getgrid46(){           let x = 6;        let y = 3;        this.changeOneGrids(x,y);    },    getgrid47(){           let x = 6;        let y = 4;        this.changeOneGrids(x,y);    },    getgrid48(){           let x = 6;        let y = 5;        this.changeOneGrids(x,y);    },    getgrid49(){           let x = 6;        let y = 6;        this.changeOneGrids(x,y);    }最后是随机生成一个色块被打乱的7 7的棋盘,首先我们得先把二维数组的下标放进一个列表中,Math.random()函数是随机[0,1)内的小数,Math.floor(x)为得出小于或等于x的最大整数,每次随机生成一个数后,读取刚才的列表对应的下标,调用函数changeOneGrids(x,y),重复此操作若干次,这样就能随机生成一个色块被打乱的7*7的棋盘
initGrids(){           let array = [];        for (let row = 0; row < 7; row++) {               for (let column = 0; column < 7; column++) {                   if (grids[row][column] == 0) {                       array.push([row, column])                }            }        }        for (let i = 0; i < 20; i++){               let randomIndex = Math.floor(Math.random() * array.length);            let row = array[randomIndex][0];            let column = array[randomIndex][1];            this.changeOneGrids(row,column);        }    }至此,这一部分内容已经全部编写完毕。

严政新 2020-12-29 09:57:04
小屏幕,大智慧
回复

举报

评论

您需要登录后才可以回帖 登录 | 注册

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
发文章