代码写的都队——代码规范

代码写的都队 团队 2023-12-01 10:59:02
这个作业属于哪个课程2301-计算机学院-软件工程
这个作业要求在哪里团队作业—beta冲刺+事后诸葛亮
这个作业的目标总结Alpha阶段问题
团队名称代码写的都队
团队项目闲置宝
团队置顶随笔链接代码写的都队——Beta冲刺置顶随笔

目录

  • 前端代码规范(参考vue.js风格指南)
  • 组件名为多个单词
  • 反例
  • 正例
  • 组件数据必要
  • 反例
  • 正例
  • Prop 定义必要
  • 反例
  • 正例
  • 为 v-for 设置键值必要
  • 反例
  • 正例
  • 避免 v-if 和 v-for 用在一起必要
  • 反例
  • 正例
  • 为组件样式设置作用域
  • 反例
  • 正例
  • 私有 property 名
  • 反例
  • 正例
  • 后端代码规范(参考阿里Java代码规范)
  • (一)命名风格
  • (二)常量定义
  • (三)代码格式
  • (四) OOP规约
  • (五) 并发处理
  • (六) 控制语句
  • 前端代码规范(参考vue.js风格指南)
  • 组件名为多个单词
  • 反例
  • 正例
  • 组件数据必要
  • 反例
  • 正例
  • Prop 定义必要
  • 反例
  • 正例
  • 为 v-for 设置键值必要
  • 反例
  • 正例
  • 避免 v-if 和 v-for 用在一起必要
  • 反例
  • 正例
  • 为组件样式设置作用域
  • 反例
  • 正例
  • 私有 property 名
  • 反例
  • 正例
  • 后端代码规范(参考阿里Java代码规范)
  • (一)命名风格
  • (二)常量定义
  • (三)代码格式
  • (四) OOP规约
  • (五) 并发处理
  • (六) 控制语句

前端代码规范(参考vue.js风格指南

组件名为多个单词

组件名应该始终是多个单词的,根组件 App 以及 <transition><component> 之类的 Vue 内置组件除外。

这样做可以避免跟现有的以及未来的 HTML 元素相冲突,因为所有的 HTML 元素名称都是单个单词的。

反例

Vue.component('todo', {
  // ...
})
export default {
  name: 'Todo',
  // ...
}

正例

Vue.component('todo-item', {
  // ...
})
export default {
  name: 'TodoItem',
  // ...
}

组件数据必要

组件的 data 必须是一个函数。

当在组件中使用 data property 的时候 (除了 new Vue 外的任何地方),它的值必须是返回一个对象的函数。

反例

Vue.component('some-comp', {
  data: {
    foo: 'bar'
  }
})
export default {
  data: {
    foo: 'bar'
  }
}

正例

Vue.component('some-comp', {
  data: function () {
    return {
      foo: 'bar'
    }
  }
})
// In a .vue file
export default {
  data () {
    return {
      foo: 'bar'
    }
  }
}
// 在一个 Vue 的根实例上直接使用对象是可以的,
// 因为只存在一个这样的实例。
new Vue({
  data: {
    foo: 'bar'
  }
})

Prop 定义必要

Prop 定义应该尽量详细。

在你提交的代码中,prop 的定义应该尽量详细,至少需要指定其类型。

反例

// 这样做只有开发原型系统时可以接受
props: ['status']

正例

props: {
  status: String
}
// 更好的做法!
props: {
  status: {
    type: String,
    required: true,
    validator: function (value) {
      return [
        'syncing',
        'synced',
        'version-conflict',
        'error'
      ].indexOf(value) !== -1
    }
  }
}

v-for 设置键值必要

总是用 key 配合 v-for

在组件上总是必须用 key 配合 v-for,以便维护内部组件及其子树的状态。甚至在元素上维护可预测的行为,比如动画中的对象固化 (object constancy),也是一种好的做法。

反例

<ul>
  <li v-for="todo in todos">
    {{ todo.text }}
  </li>
</ul>

正例

<ul>
  <li
    v-for="todo in todos"
    :key="todo.id"
  >
    {{ todo.text }}
  </li>
</ul>

避免 v-ifv-for 用在一起必要

永远不要把 v-ifv-for 同时用在同一个元素上。

一般我们在两种常见的情况下会倾向于这样做:

  • 为了过滤一个列表中的项目 (比如 v-for="user in users" v-if="user.isActive")。在这种情形下,请将 users 替换为一个计算属性 (比如 activeUsers),让其返回过滤后的列表。
  • 为了避免渲染本应该被隐藏的列表 (比如 v-for="user in users" v-if="shouldShowUsers")。这种情形下,请将 v-if 移动至容器元素上 (比如 ulol)。

反例

<ul>
  <li
    v-for="user in users"
    v-if="user.isActive"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>
<ul>
  <li
    v-for="user in users"
    v-if="shouldShowUsers"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

正例

<ul>
  <li
    v-for="user in activeUsers"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>
<ul v-if="shouldShowUsers">
  <li
    v-for="user in users"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

为组件样式设置作用域

对于应用来说,顶级 App 组件和布局组件中的样式可以是全局的,但是其它所有组件都应该是有作用域的。

这条规则只和单文件组件有关。你不一定要使用 scoped attribute。设置作用域也可以通过 CSS Modules,那是一个基于 class 的类似 BEM 的策略,当然你也可以使用其它的库或约定。

不管怎样,对于组件库,我们应该更倾向于选用基于 class 的策略而不是 scoped attribute。

这让覆写内部样式更容易:使用了常人可理解的 class 名称且没有太高的选择器优先级,而且不太会导致冲突。

反例

<template>
  <button class="btn btn-close">X</button>
</template>

<style>
.btn-close {
  background-color: red;
}
</style>

正例

<template>
  <button class="button button-close">X</button>
</template>

<!-- 使用 `scoped` attribute -->
<style scoped>
.button {
  border: none;
  border-radius: 2px;
}

.button-close {
  background-color: red;
}
</style>
<template>
  <button :class="[$style.button, $style.buttonClose]">X</button>
</template>

<!-- 使用 CSS Modules -->
<style module>
.button {
  border: none;
  border-radius: 2px;
}

.buttonClose {
  background-color: red;
}
</style>
<template>
  <button class="c-Button c-Button--close">X</button>
</template>

<!-- 使用 BEM 约定 -->
<style>
.c-Button {
  border: none;
  border-radius: 2px;
}

.c-Button--close {
  background-color: red;
}
</style>

私有 property 名

使用模块作用域保持不允许外部访问的函数的私有性。如果无法做到这一点,就始终为插件、混入等不考虑作为对外公共 API 的自定义私有 property 使用 $_ 前缀。并附带一个命名空间以回避和其它作者的冲突 (比如 $_yourPluginName_)。

反例

var myGreatMixin = {
  // ...
  methods: {
    update: function () {
      // ...
    }
  }
}
var myGreatMixin = {
  // ...
  methods: {
    _update: function () {
      // ...
    }
  }
}
var myGreatMixin = {
  // ...
  methods: {
    $update: function () {
      // ...
    }
  }
}
var myGreatMixin = {
  // ...
  methods: {
    $_update: function () {
      // ...
    }
  }
}

正例

var myGreatMixin = {
  // ...
  methods: {
    $_myGreatMixin_update: function () {
      // ...
    }
  }
}
// 甚至更好!
var myGreatMixin = {
  // ...
  methods: {
    publicMethod() {
      // ...
      myPrivateFunction()
    }
  }
}

function myPrivateFunction() {
  // ...
}

export default myGreatMixin

后端代码规范(参考阿里Java代码规范)

(一)命名风格

  1. 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。 类名使用UpperCamelCase风格,但以下情形例外:DO / BO / DTO / VO / AO / PO等。
  2. 方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase风格,必须遵从驼峰形式。常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。抽象类命名使用Abstract或Base开头;异常类命名使用Exception结尾;测试类命名以它要测试的类名开始,以Test结尾。
  3. 类型与中括号紧挨相连来定义数组。POJO类中布尔类型的变量,都不要加is前缀,否则部分框架解析会引起序列化错误。包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。杜绝完全不规范的缩写,避免望文不知义。
  4. 对于Service和DAO类,基于SOA的理念,暴露出来的服务一定是接口,内部的实现类用Impl的后缀与接口区别。
  5. 枚举类名建议带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开。

(二)常量定义

  1. 不允许任何未经预先定义的常量直接出现在代码中。

  2. long或者Long初始赋值时,使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解。

(三)代码格式

  1. 左小括号和字符之间不出现空格;同样,右小括号和字符之间也不出现空格。

  2. if/for/while/switch/do等保留字与括号之间都必须加空格。

  3. 任何二目、三目运算符的左右两边都需要加一个空格。

  4. 注释的双斜线与注释内容之间有且仅有一个空格。

  5. 单行字符数限制不超过120个,超出需要换行。

  6. 方法参数在定义和传入时,多个参数逗号后边必须加空格。

(四) OOP规约

  1. 避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。

  2. 所有的覆写方法,必须加@Override注解。

  3. 相同参数类型,相同业务含义,才可以使用Java的可变参数,避免使用Object。

  4. 外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生影响。接口过时必须加@Deprecated注解,并清晰地说明采用的新接口或者新服务是什么。不能使用过时的类或方法。

  5. 所有的相同类型的包装类对象之间值的比较,全部使用equals方法比较。

  6. 关于基本数据类型与包装数据类型的使用标准如下:
    1) 所有的POJO类属性必须使用包装数据类型。
    2) RPC方法的返回值和参数必须使用包装数据类型。

  7. 定义DO/DTO/VO等POJO类时,不要设定任何属性默认值

  8. 构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在init方法中。

  9. POJO类必须写toString方法。

(五) 并发处理

  1. 获取单例对象需要保证线程安全,其中的方法也要保证线程安全。

  2. 线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。

  3. SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。

  4. 高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。

  5. 对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁。

(六) 控制语句

  1. 在一个switch块内,每个case要么通过break/return等来终止,要么注释说明程序将继续执行到哪一个case为止;在一个switch块内,都必须包含一个default语句并且放在最后,即使空代码。

  2. 在if/else/for/while/do语句中必须使用大括号。即使只有一行代码,避免采用单行的编码方式:

  3. 在高并发场景中,避免使用”等于”判断作为中断或退出的条件。

  4. 表达异常的分支时,少用if-else方式,这种方式可以改写成:

  5. 除常用方法(如getXxx/isXxx)等外,不要在条件判断中执行其它复杂的语句,将复杂逻辑判断的结果赋值给一个有意义的布尔变量名,以提高可读性。

  6. 循环体中的语句要考量性能,以下操作尽量移至循环体外处理,如定义对象、变量、获取数据库连接,进行不必要的try-catch操作(这个try-catch是否可以移至循环体外)。 | 这个作业属于哪个课程 | 2301-计算机学院-软件工程 |
    | :------------------- | :----------------------------------------------------------- |
    | 这个作业要求在哪里 | 团队作业—beta冲刺+事后诸葛亮 |
    | 这个作业的目标 | 总结Alpha阶段问题 |
    | 团队名称 | 代码写的都队 |
    | 团队项目 | 闲置宝 |
    | 团队置顶随笔链接 | 代码写的都队——Beta冲刺置顶随笔 |

目录

  • 前端代码规范(参考vue.js风格指南)
  • 组件名为多个单词
  • 反例
  • 正例
  • 组件数据必要
  • 反例
  • 正例
  • Prop 定义必要
  • 反例
  • 正例
  • 为 v-for 设置键值必要
  • 反例
  • 正例
  • 避免 v-if 和 v-for 用在一起必要
  • 反例
  • 正例
  • 为组件样式设置作用域
  • 反例
  • 正例
  • 私有 property 名
  • 反例
  • 正例
  • 后端代码规范(参考阿里Java代码规范)
  • (一)命名风格
  • (二)常量定义
  • (三)代码格式
  • (四) OOP规约
  • (五) 并发处理
  • (六) 控制语句
  • 前端代码规范(参考vue.js风格指南)
  • 组件名为多个单词
  • 反例
  • 正例
  • 组件数据必要
  • 反例
  • 正例
  • Prop 定义必要
  • 反例
  • 正例
  • 为 v-for 设置键值必要
  • 反例
  • 正例
  • 避免 v-if 和 v-for 用在一起必要
  • 反例
  • 正例
  • 为组件样式设置作用域
  • 反例
  • 正例
  • 私有 property 名
  • 反例
  • 正例
  • 后端代码规范(参考阿里Java代码规范)
  • (一)命名风格
  • (二)常量定义
  • (三)代码格式
  • (四) OOP规约
  • (五) 并发处理
  • (六) 控制语句

前端代码规范(参考vue.js风格指南

组件名为多个单词

组件名应该始终是多个单词的,根组件 App 以及 <transition><component> 之类的 Vue 内置组件除外。

这样做可以避免跟现有的以及未来的 HTML 元素相冲突,因为所有的 HTML 元素名称都是单个单词的。

反例

Vue.component('todo', {
  // ...
})
export default {
  name: 'Todo',
  // ...
}

正例

Vue.component('todo-item', {
  // ...
})
export default {
  name: 'TodoItem',
  // ...
}

组件数据必要

组件的 data 必须是一个函数。

当在组件中使用 data property 的时候 (除了 new Vue 外的任何地方),它的值必须是返回一个对象的函数。

反例

Vue.component('some-comp', {
  data: {
    foo: 'bar'
  }
})
export default {
  data: {
    foo: 'bar'
  }
}

正例

Vue.component('some-comp', {
  data: function () {
    return {
      foo: 'bar'
    }
  }
})
// In a .vue file
export default {
  data () {
    return {
      foo: 'bar'
    }
  }
}
// 在一个 Vue 的根实例上直接使用对象是可以的,
// 因为只存在一个这样的实例。
new Vue({
  data: {
    foo: 'bar'
  }
})

Prop 定义必要

Prop 定义应该尽量详细。

在你提交的代码中,prop 的定义应该尽量详细,至少需要指定其类型。

反例

// 这样做只有开发原型系统时可以接受
props: ['status']

正例

props: {
  status: String
}
// 更好的做法!
props: {
  status: {
    type: String,
    required: true,
    validator: function (value) {
      return [
        'syncing',
        'synced',
        'version-conflict',
        'error'
      ].indexOf(value) !== -1
    }
  }
}

v-for 设置键值必要

总是用 key 配合 v-for

在组件上总是必须用 key 配合 v-for,以便维护内部组件及其子树的状态。甚至在元素上维护可预测的行为,比如动画中的对象固化 (object constancy),也是一种好的做法。

反例

<ul>
  <li v-for="todo in todos">
    {{ todo.text }}
  </li>
</ul>

正例

<ul>
  <li
    v-for="todo in todos"
    :key="todo.id"
  >
    {{ todo.text }}
  </li>
</ul>

避免 v-ifv-for 用在一起必要

永远不要把 v-ifv-for 同时用在同一个元素上。

一般我们在两种常见的情况下会倾向于这样做:

  • 为了过滤一个列表中的项目 (比如 v-for="user in users" v-if="user.isActive")。在这种情形下,请将 users 替换为一个计算属性 (比如 activeUsers),让其返回过滤后的列表。
  • 为了避免渲染本应该被隐藏的列表 (比如 v-for="user in users" v-if="shouldShowUsers")。这种情形下,请将 v-if 移动至容器元素上 (比如 ulol)。

反例

<ul>
  <li
    v-for="user in users"
    v-if="user.isActive"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>
<ul>
  <li
    v-for="user in users"
    v-if="shouldShowUsers"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

正例

<ul>
  <li
    v-for="user in activeUsers"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>
<ul v-if="shouldShowUsers">
  <li
    v-for="user in users"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>

为组件样式设置作用域

对于应用来说,顶级 App 组件和布局组件中的样式可以是全局的,但是其它所有组件都应该是有作用域的。

这条规则只和单文件组件有关。你不一定要使用 scoped attribute。设置作用域也可以通过 CSS Modules,那是一个基于 class 的类似 BEM 的策略,当然你也可以使用其它的库或约定。

不管怎样,对于组件库,我们应该更倾向于选用基于 class 的策略而不是 scoped attribute。

这让覆写内部样式更容易:使用了常人可理解的 class 名称且没有太高的选择器优先级,而且不太会导致冲突。

反例

<template>
  <button class="btn btn-close">X</button>
</template>

<style>
.btn-close {
  background-color: red;
}
</style>

正例

<template>
  <button class="button button-close">X</button>
</template>

<!-- 使用 `scoped` attribute -->
<style scoped>
.button {
  border: none;
  border-radius: 2px;
}

.button-close {
  background-color: red;
}
</style>
<template>
  <button :class="[$style.button, $style.buttonClose]">X</button>
</template>

<!-- 使用 CSS Modules -->
<style module>
.button {
  border: none;
  border-radius: 2px;
}

.buttonClose {
  background-color: red;
}
</style>
<template>
  <button class="c-Button c-Button--close">X</button>
</template>

<!-- 使用 BEM 约定 -->
<style>
.c-Button {
  border: none;
  border-radius: 2px;
}

.c-Button--close {
  background-color: red;
}
</style>

私有 property 名

使用模块作用域保持不允许外部访问的函数的私有性。如果无法做到这一点,就始终为插件、混入等不考虑作为对外公共 API 的自定义私有 property 使用 $_ 前缀。并附带一个命名空间以回避和其它作者的冲突 (比如 $_yourPluginName_)。

反例

var myGreatMixin = {
  // ...
  methods: {
    update: function () {
      // ...
    }
  }
}
var myGreatMixin = {
  // ...
  methods: {
    _update: function () {
      // ...
    }
  }
}
var myGreatMixin = {
  // ...
  methods: {
    $update: function () {
      // ...
    }
  }
}
var myGreatMixin = {
  // ...
  methods: {
    $_update: function () {
      // ...
    }
  }
}

正例

var myGreatMixin = {
  // ...
  methods: {
    $_myGreatMixin_update: function () {
      // ...
    }
  }
}
// 甚至更好!
var myGreatMixin = {
  // ...
  methods: {
    publicMethod() {
      // ...
      myPrivateFunction()
    }
  }
}

function myPrivateFunction() {
  // ...
}

export default myGreatMixin

后端代码规范(参考阿里Java代码规范)

(一)命名风格

  1. 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。 类名使用UpperCamelCase风格,但以下情形例外:DO / BO / DTO / VO / AO / PO等。
  2. 方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase风格,必须遵从驼峰形式。常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。抽象类命名使用Abstract或Base开头;异常类命名使用Exception结尾;测试类命名以它要测试的类名开始,以Test结尾。
  3. 类型与中括号紧挨相连来定义数组。POJO类中布尔类型的变量,都不要加is前缀,否则部分框架解析会引起序列化错误。包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。杜绝完全不规范的缩写,避免望文不知义。
  4. 对于Service和DAO类,基于SOA的理念,暴露出来的服务一定是接口,内部的实现类用Impl的后缀与接口区别。
  5. 枚举类名建议带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开。

(二)常量定义

  1. 不允许任何未经预先定义的常量直接出现在代码中。

  2. long或者Long初始赋值时,使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解。

(三)代码格式

  1. 左小括号和字符之间不出现空格;同样,右小括号和字符之间也不出现空格。

  2. if/for/while/switch/do等保留字与括号之间都必须加空格。

  3. 任何二目、三目运算符的左右两边都需要加一个空格。

  4. 注释的双斜线与注释内容之间有且仅有一个空格。

  5. 单行字符数限制不超过120个,超出需要换行。

  6. 方法参数在定义和传入时,多个参数逗号后边必须加空格。

(四) OOP规约

  1. 避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。

  2. 所有的覆写方法,必须加@Override注解。

  3. 相同参数类型,相同业务含义,才可以使用Java的可变参数,避免使用Object。

  4. 外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生影响。接口过时必须加@Deprecated注解,并清晰地说明采用的新接口或者新服务是什么。不能使用过时的类或方法。

  5. 所有的相同类型的包装类对象之间值的比较,全部使用equals方法比较。

  6. 关于基本数据类型与包装数据类型的使用标准如下:
    1) 所有的POJO类属性必须使用包装数据类型。
    2) RPC方法的返回值和参数必须使用包装数据类型。

  7. 定义DO/DTO/VO等POJO类时,不要设定任何属性默认值

  8. 构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在init方法中。

  9. POJO类必须写toString方法。

(五) 并发处理

  1. 获取单例对象需要保证线程安全,其中的方法也要保证线程安全。

  2. 线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。

  3. SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。

  4. 高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。

  5. 对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁。

(六) 控制语句

  1. 在一个switch块内,每个case要么通过break/return等来终止,要么注释说明程序将继续执行到哪一个case为止;在一个switch块内,都必须包含一个default语句并且放在最后,即使空代码。

  2. 在if/else/for/while/do语句中必须使用大括号。即使只有一行代码,避免采用单行的编码方式:

  3. 在高并发场景中,避免使用”等于”判断作为中断或退出的条件。

  4. 表达异常的分支时,少用if-else方式,这种方式可以改写成:

  5. 除常用方法(如getXxx/isXxx)等外,不要在条件判断中执行其它复杂的语句,将复杂逻辑判断的结果赋值给一个有意义的布尔变量名,以提高可读性。

  6. 循环体中的语句要考量性能,以下操作尽量移至循环体外处理,如定义对象、变量、获取数据库连接,进行不必要的try-catch操作(这个try-catch是否可以移至循环体外)。

...全文
104 回复 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

158

社区成员

发帖
与我相关
我的任务
社区描述
FZU-CS-SE
软件工程 高校
社区管理员
  • LinQF39
  • Jcandc
  • chjinhuu
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧