Skip to content
本页目录

代码示例

API 定义

反例

js
getTreeData(`/framework-server2/menuGroupManager/orgListWithMenuByType/${state.MenuGLOBAL}`, 'get')
getTreeData(`/framework-server2/menuGroupManager/orgListWithMenuByType/${state.MenuGLOBAL}`, 'get')

正例

js
import { server4A, frameworkEngin } from '@/utils/gap3-common'
export async function getInfo() {
  return request({
    url: `${server4A}/restapi/4a/view/userInfo`,
    method: 'get',
  })
}
import { server4A, frameworkEngin } from '@/utils/gap3-common'
export async function getInfo() {
  return request({
    url: `${server4A}/restapi/4a/view/userInfo`,
    method: 'get',
  })
}

loading 设置

操作类:提交、保存、审批、暂存、确认、删除批量类:批量设置、导出在 api 定义时,增加  headers: { loading: true }标识

js
export async function savePmProjectAp(params = {}, data = {}) {
  return request({
    url: `${myGlobal.GIC_BASE_URL}/projectInfo/saveProjectInfo`,
    method: 'post',
    params,
    data,
    headers: { loading: true },
  })
}
export async function savePmProjectAp(params = {}, data = {}) {
  return request({
    url: `${myGlobal.GIC_BASE_URL}/projectInfo/saveProjectInfo`,
    method: 'post',
    params,
    data,
    headers: { loading: true },
  })
}
  • API headers 参数说明

    目前 headers 设置支持两类,loading 和 getHeaders loading:启用 loading getHeaders:返回整个 response,用于导出时取 headers 中的文件名,默认只返回 respinse.data

// 启用loading
headers: { loading: true },
headers: { getHeaders: true, loading: true },
// 启用loading
headers: { loading: true },
headers: { getHeaders: true, loading: true },

代码规范

组件引用一律使用大驼峰命名

正例

html
<CreateView :selectList="selectList" :table-configs="tableConfigs"></CreateView>
<script lang="ts" setup>
  import { CreateView } from 'ctj-ui-next'
</script>
<CreateView :selectList="selectList" :table-configs="tableConfigs"></CreateView>
<script lang="ts" setup>
  import { CreateView } from 'ctj-ui-next'
</script>

反例

html
<create-form-view></create-form-view>
<script lang="ts" setup>
  import createFormView from '@/components/gic/UIViews/createFormView/index.vue'
</script>
<create-form-view></create-form-view>
<script lang="ts" setup>
  import createFormView from '@/components/gic/UIViews/createFormView/index.vue'
</script>
  • 弹窗都支持拖动,一律添加 v-dialogDrag 指令

    正例:
html
<a-modal
  class="gic-modal info-modal"
  v-model:visible="modalchooseVisible"
  title="退回意见"
  width="640px"
  :force-render="true"
  @cancel="hideChooseProModal"
  @ok="doBackPurchase"
>
  <template #footer>
    <a-button key="submit" type="primary" @click="doBackPurchase">确定</a-button>
  </template>
  <div class="modal-content" v-dialogDrag></div>
</a-modal>
<a-modal
  class="gic-modal info-modal"
  v-model:visible="modalchooseVisible"
  title="退回意见"
  width="640px"
  :force-render="true"
  @cancel="hideChooseProModal"
  @ok="doBackPurchase"
>
  <template #footer>
    <a-button key="submit" type="primary" @click="doBackPurchase">确定</a-button>
  </template>
  <div class="modal-content" v-dialogDrag></div>
</a-modal>

操作按钮统一添加 loading 状态或系统级 loading

正例 1:操作按钮添加防抖指令,不等待接口返回

javascript
<!--默认加载1.5s -->
<a-button v-btnLoading type="primary">确定</a-button>
<!--加载3s -->
<a-button v-btnLoading="3" type="primary">确定</a-button>
<!--默认加载1.5s -->
<a-button v-btnLoading type="primary">确定</a-button>
<!--加载3s -->
<a-button v-btnLoading="3" type="primary">确定</a-button>

正例 2:按钮自带 loading 属性,防重

html
<a-button :loading="isLoading" type="primary">保存</a-button>
<script lang="ts" setup>
  const isLoading = ref(false)
  const handleClick = async () => {
    isLoading.value = true
    const res = await getData()
    isLoading.value = false
  }
</script>
<a-button :loading="isLoading" type="primary">保存</a-button>
<script lang="ts" setup>
  const isLoading = ref(false)
  const handleClick = async () => {
    isLoading.value = true
    const res = await getData()
    isLoading.value = false
  }
</script>

正例 3:数据批量或响应时间长的,等待结果返回,使用系统级全屏 loading

html
<script lang="ts" setup>
  import { show, hide } from '@/hooks/loading'
  Modal.confirm({
    title: '提示',
    content: '是否确认挑选?',
    okText: '确认',
    cancelText: '取消',
    async onOk() {
      show()
      const res: any = await save()
      hide()
    },
  })
</script>
<script lang="ts" setup>
  import { show, hide } from '@/hooks/loading'
  Modal.confirm({
    title: '提示',
    content: '是否确认挑选?',
    okText: '确认',
    cancelText: '取消',
    async onOk() {
      show()
      const res: any = await save()
      hide()
    },
  })
</script>

正例 4:antdesign a-spin 的使用说明:单据新增时加载二级视图页面需要添加 loading 状态,由于新增时会同时请求多个接口,若在 api 上统一处理,会存在本身添加了 loading 的接口并未请求完就已经关闭了 loading,此时可以使用 a-spin 包裹二级页面,自行处理 loading 的开关时间参考天津津南 163 V1.6.3 分支 @/views/gic/expense/billForm/billForm.vue

html
<a-spin :spinning="isLoading">二级视图组件</a-spin>
<script lang="ts" setup>
  const isLoading = ref(false)
  const handleClick = async () => {
    isLoading.value = true
    const res = await getData()
    isLoading.value = false
  }
</script>
<a-spin :spinning="isLoading">二级视图组件</a-spin>
<script lang="ts" setup>
  const isLoading = ref(false)
  const handleClick = async () => {
    isLoading.value = true
    const res = await getData()
    isLoading.value = false
  }
</script>

获取当前用户信息,使用公共 hook 方法

正例:

html
<script lang="ts" setup>
  import { getUserInfoCom } from '@/hooks/useComData'
  // 获取当前登录人信息
  const getUserInfo = async () => {
    const useCom = await getUserInfoCom()
  }
</script>
<script lang="ts" setup>
  import { getUserInfoCom } from '@/hooks/useComData'
  // 获取当前登录人信息
  const getUserInfo = async () => {
    const useCom = await getUserInfoCom()
  }
</script>

反例

html
<script lang="ts" setup>
  import { getUser } from '@/api/gic/common'
  // 获取当前登录人信息
  const getUserInfo = async () => {
    const res: any = await getUser()
  }
</script>
<script lang="ts" setup>
  import { getUser } from '@/api/gic/common'
  // 获取当前登录人信息
  const getUserInfo = async () => {
    const res: any = await getUser()
  }
</script>

获取 UUID,前端生成

正例

javascript
import { useUUID } from '@/hooks/useUUID'
let uuId = useUUID()
import { useUUID } from '@/hooks/useUUID'
let uuId = useUUID()

反例

javascript
export async function getUUID() {
  return request({
    url: `${myGlobal.GIC_BASE_URL}/public/getUUID`,
    method: 'get',
  })
}
export async function getUUID() {
  return request({
    url: `${myGlobal.GIC_BASE_URL}/public/getUUID`,
    method: 'get',
  })
}

随意定义全局变量

反例 正例

变量定义随便

反例

js
const getBillTypeIdList = ref([]) //获取单据类型数据
const selectControl_assets = xxx
let currentId = ref('') // 发票id
const getBillTypeIdList = ref([]) //获取单据类型数据
const selectControl_assets = xxx
let currentId = ref('') // 发票id

正例

const billTypeIdList = ref( []);// 单据类型数据
const selectControlAssets = xxx;
const invoiceId = ref("") // 发票id
const billTypeIdList = ref( []);// 单据类型数据
const selectControlAssets = xxx;
const invoiceId = ref("") // 发票id

弹框数据混用

接口重复请求

反例 正例

一级组件(CreateView)示例

正例 http://172.16.22.196:8080/web/#/15/719

二级视图组件(create-from-view)规范

正例 http://172.16.22.196:8080/web/#/15/721

赋值表达式

逻辑运算符和赋值表达式(&&=,||=,??=)反例

js
data.flowModuleId ? '' : (data.flowModuleId = me.flowId)
data.flowModuleId ? '' : (data.flowModuleId = me.flowId)

正例

// 1、逻辑或赋值运算符
data.flowModuleId ||= me.flowId
// 2、常规
if (!data.flowModuleId) {
data.flowModuleId = me.flowId
}
// 1、逻辑或赋值运算符
data.flowModuleId ||= me.flowId
// 2、常规
if (!data.flowModuleId) {
data.flowModuleId = me.flowId
}

赋值表达式扩展

知识扩展逻辑运算符和赋值表达式(&&=,||=,??=) (1) &&=:逻辑与赋值运算符 x &&= y 等价于 x && (x=y):意思是当 x 为真时,x = y。 (2) ||=:逻辑或赋值运算符 x ||= y 等价于 x || (x = y):意思是仅在 x 为 false 的时候,x = y。 (3) ??=:逻辑空赋值运算符 x ??= y 等价于 x ?? (x = y):意思是仅在 x 为 null 或 undefined 的时候,x = y。

js
let a = 1
a &&= 2
console.log(a) // 2

const aa = { duration: 50, title: '' }
aa.duration ||= 10
console.log(aa.duration) // 50
aa.title ||= 'title is empty.'
console.log(aa.title) // "title is empty"

const a = { duration: 50 }

ac.duration ??= 10
console.log(ac.duration) // 50
ac.speed ??= 25
console.log(ac.speed) // 25
let a = 1
a &&= 2
console.log(a) // 2

const aa = { duration: 50, title: '' }
aa.duration ||= 10
console.log(aa.duration) // 50
aa.title ||= 'title is empty.'
console.log(aa.title) // "title is empty"

const a = { duration: 50 }

ac.duration ??= 10
console.log(ac.duration) // 50
ac.speed ??= 25
console.log(ac.speed) // 25

统一影响拦截处理

由于平台、内控及第三方对接时,接口影响结果中的状态码、结果消息不一致,导致应用上判断不通一如:内控{data:[],reason:'',status_code:'0000'},平台{data:[],message:'',code:'0000'},单据引擎{data:[],message:'',code:'00000'} 处理方式,在 response 统一拦截处理

/**
   *统一处理返回结果,方便业务代码对结果集的统一处理
   *内控结果{data:[],reason:'',status_code:'0000'}
   *非内控如平台等其他情况统一处理为上述结构
   */
  if (response.data) {
    const code = response?.data?.status_code || response?.data?.code || '0000';
    response.data.status_code = code == '00000' ? '0000' : code;
    const reason = response.data.reason || response.data.message || null;
    response.data.reason = reason;
  }
/**
   *统一处理返回结果,方便业务代码对结果集的统一处理
   *内控结果{data:[],reason:'',status_code:'0000'}
   *非内控如平台等其他情况统一处理为上述结构
   */
  if (response.data) {
    const code = response?.data?.status_code || response?.data?.code || '0000';
    response.data.status_code = code == '00000' ? '0000' : code;
    const reason = response.data.reason || response.data.message || null;
    response.data.reason = reason;
  }

使用示例:

平台接口:if (res.code == ResStatus.PtSuccess)
内控接口:if (resExtra.status_code === ResStatus.success)
转换后可统一使用
if (resExtra.status_code === ResStatus.success)
平台接口:if (res.code == ResStatus.PtSuccess)
内控接口:if (resExtra.status_code === ResStatus.success)
转换后可统一使用
if (resExtra.status_code === ResStatus.success)

属性安全性

对象为空时,做属性、循环等操作引起的 js 脚本异常,阻断页面的正常展示与加载 反例:

// 在biButtons为空时,会导致js错误中断页面操作
uiView.uiButtons.forEach(uiButton => {})
// 在biButtons为空时,会导致js错误中断页面操作
uiView.uiButtons.forEach(uiButton => {})

正例:可使用可选链运算符(?.)避免异常

示例1:
uiView.uiButtons && uiView.uiButtons.forEach(uiButton => {})
示例2(推荐):
uiView.uiButtons?.forEach(uiButton => {})
示例1:
uiView.uiButtons && uiView.uiButtons.forEach(uiButton => {})
示例2(推荐):
uiView.uiButtons?.forEach(uiButton => {})

预算单位软件产品开发部