龙空技术网

uniapp入门到进阶 一 4、uniapp工程全栈结构划分

胖奶奶与胖小伙 651

前言:

此时朋友们对“mysqluuiduuid”大致比较看重,看官们都需要学习一些“mysqluuiduuid”的相关资讯。那么小编在网络上网罗了一些对于“mysqluuiduuid””的相关文章,希望各位老铁们能喜欢,朋友们快快来学习一下吧!

上一小节我们详细讲述了 uni-app全栈开发vite环境及插件配置管理 。接下来我们需要对我们的项目工程 uniapp-demo 做一个结构划分,分类存放我们的工程文件

1、自动注入全局 API ,避免繁琐的API引入

//根目录创建declare文件,存放auto-imports.d.ts/** * @Author: Mr Chen  陈晓  * @Date: 2023-01-16 14:12:05 * @LastEditTime: 2023-02-09 09:52:03 * @Description: 自动注入全局API * 任何傻子都能写出电脑能识别的代码,但我能写出任何人都能看懂的代码 **/declare global {  const app: typeof import('@/app/index')['app']  const assert: typeof import('power-assert')['default']  const computed: typeof import('vue')['computed']  const createApp: typeof import('vue')['createApp']  const customRef: typeof import('vue')['customRef']  const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']  const defineComponent: typeof import('vue')['defineComponent']  const effectScope: typeof import('vue')['effectScope']  const EffectScope: typeof import('vue')['EffectScope']  const getCurrentInstance: typeof import('vue')['getCurrentInstance']  const getCurrentScope: typeof import('vue')['getCurrentScope']  const h: typeof import('vue')['h']  const inject: typeof import('vue')['inject']  const isReadonly: typeof import('vue')['isReadonly']  const isRef: typeof import('vue')['isRef']  const markRaw: typeof import('vue')['markRaw']  const nextTick: typeof import('vue')['nextTick']  const onActivated: typeof import('vue')['onActivated']  const onAddToFavorites: typeof import('@dcloudio/uni-app')['onAddToFavorites']  const onBackPress: typeof import('@dcloudio/uni-app')['onBackPress']  const onBeforeMount: typeof import('vue')['onBeforeMount']  const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']  const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']  const onDeactivated: typeof import('vue')['onDeactivated']  const onError: typeof import('@dcloudio/uni-app')['onError']  const onErrorCaptured: typeof import('vue')['onErrorCaptured']  const onHide: typeof import('@dcloudio/uni-app')['onHide']  const onLaunch: typeof import('@dcloudio/uni-app')['onLaunch']  const onLoad: typeof import('@dcloudio/uni-app')['onLoad']  const onMounted: typeof import('vue')['onMounted']  const onNavigationBarButtonTap: typeof import('@dcloudio/uni-app')['onNavigationBarButtonTap']  const onNavigationBarSearchInputChanged: typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputChanged']  const onNavigationBarSearchInputClicked: typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputClicked']  const onNavigationBarSearchInputConfirmed: typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputConfirmed']  const onNavigationBarSearchInputFocusChanged: typeof import('@dcloudio/uni-app')['onNavigationBarSearchInputFocusChanged']  const onPageNotFound: typeof import('@dcloudio/uni-app')['onPageNotFound']  const onPageScroll: typeof import('@dcloudio/uni-app')['onPageScroll']  const onPullDownRefresh: typeof import('@dcloudio/uni-app')['onPullDownRefresh']  const onReachBottom: typeof import('@dcloudio/uni-app')['onReachBottom']  const onReady: typeof import('@dcloudio/uni-app')['onReady']  const onRenderTracked: typeof import('vue')['onRenderTracked']  const onRenderTriggered: typeof import('vue')['onRenderTriggered']  const onResize: typeof import('@dcloudio/uni-app')['onResize']  const onScopeDispose: typeof import('vue')['onScopeDispose']  const onServerPrefetch: typeof import('vue')['onServerPrefetch']  const onShareAppMessage: typeof import('@dcloudio/uni-app')['onShareAppMessage']  const onShareTimeline: typeof import('@dcloudio/uni-app')['onShareTimeline']  const onShow: typeof import('@dcloudio/uni-app')['onShow']  const onTabItemTap: typeof import('@dcloudio/uni-app')['onTabItemTap']  const onThemeChange: typeof import('@dcloudio/uni-app')['onThemeChange']  const onUnhandledRejection: typeof import('@dcloudio/uni-app')['onUnhandledRejection']  const onUnload: typeof import('@dcloudio/uni-app')['onUnload']  const onUnmounted: typeof import('vue')['onUnmounted']  const onUpdated: typeof import('vue')['onUpdated']  const provide: typeof import('vue')['provide']  const reactive: typeof import('vue')['reactive']  const readonly: typeof import('vue')['readonly']  const ref: typeof import('vue')['ref']  const resolveComponent: typeof import('vue')['resolveComponent']  const ScrollSymbol: typeof import('@/hooks')['ScrollSymbol']  const shallowReactive: typeof import('vue')['shallowReactive']  const shallowReadonly: typeof import('vue')['shallowReadonly']  const shallowRef: typeof import('vue')['shallowRef']  const toRaw: typeof import('vue')['toRaw']  const toRef: typeof import('vue')['toRef']  const toRefs: typeof import('vue')['toRefs']  const triggerRef: typeof import('vue')['triggerRef']  const unref: typeof import('vue')['unref']  const useAttrs: typeof import('vue')['useAttrs']  const useCssModule: typeof import('vue')['useCssModule']  const useCssVars: typeof import('vue')['useCssVars']  const useQuery: typeof import('@/hooks')['useQuery']  const useScroll: typeof import('@/hooks')['useScroll']  const useSlots: typeof import('vue')['useSlots']  const watch: typeof import('vue')['watch']  const watchEffect: typeof import('vue')['watchEffect']}export {}//注意:在上一节 imports.config.ts 文件导出全局配置dts: 'declare/auto-imports.d.ts',

2、完善src文件工程结构

src下创建store文件,并完善工程文件(状态管理

//新建src/store/index.ts/** * @Author: Mr Chen  陈晓  * @Date: 2023-01-16 14:12:05 * @LastEditTime: 2023-02-09 09:04:03 * @Description: 请求封装 * 任何傻子都能写出电脑能识别的代码,但我能写出任何人都能看懂的代码 **/import { InjectionKey} from 'vue'import { createStore } from 'vuex'import { store as app, AppState, AppStore } from '@/store/modules/app'import getters from './getters'export const key: InjectionKey<Store> = Symbol()export interface RootState {  app: AppState}export type Store = AppStore<Pick<RootState, 'app'>>export const store = createStore<RootState>({   modules: {    app  },  getters})export function useStore(): Store {  return store as Store}
//新建src/store/getters.ts/** * @Author: Mr Chen  陈晓  * @Date: 2023-01-16 14:12:05 * @LastEditTime: 2023-02-09 09:15:22 * @Description: 请求封装 * 任何傻子都能写出电脑能识别的代码,但我能写出任何人都能看懂的代码 **/import { RootState } from '@/store'export default {  token: (state: RootState) => state.app.token,}
//新建modules src/store/modules/app/index.ts/** * @Author: Mr Chen  陈晓  * @Date: 2023-01-16 14:12:05 * @LastEditTime: 2023-02-09 09:19:59 * @Description: 请求封装 * 任何傻子都能写出电脑能识别的代码,但我能写出任何人都能看懂的代码 **/import { Store as VuexStore, CommitOptions, DispatchOptions, Module } from 'vuex'import { RootState } from '@/store'import { state } from './state'import { actions, Actions } from './ations'import { mutations, Mutations } from './mutations'import type { AppState } from './state'export { AppState }export type AppStore<S = AppState> = Omit<VuexStore<S>, 'getters' | 'commit' | 'dispatch'> & {  commit<K extends keyof Mutations, P extends Parameters<Mutations[K]>[1]>(    key: K,    payload: P,    options?: CommitOptions  ): ReturnType<Mutations[K]>} & {  dispatch<K extends keyof Actions>(    key: K,    payload: Parameters<Actions[K]>[1],    options?: DispatchOptions  ): ReturnType<Actions[K]>}export const store: Module<AppState, RootState> = {  state,  actions,  mutations,}
//新建modules src/store/modules/app/state.ts/** * @Author: Mr Chen  陈晓  * @Date: 2023-01-16 14:12:05 * @LastEditTime: 2023-02-09 09:19:59 * @Description: state * 任何傻子都能写出电脑能识别的代码,但我能写出任何人都能看懂的代码 **/import {reactive} from 'vue'export interface AppState {  token: string,  num:number,  userData: Array<any>}export const state: AppState = reactive({  token: '',  num:0,  userData:{}}) 
//新建modules src/store/modules/app/action-types.ts/** * @Author: Mr Chen  陈晓  * @Date: 2023-01-16 14:12:05 * @LastEditTime: 2023-02-09 09:22:12 * @Description:  action-types类型约束 * 任何傻子都能写出电脑能识别的代码,但我能写出任何人都能看懂的代码 **/export enum AppActionTypes {  ACTION_LOGIN = 'ACTION_LOGIN',  CLEAR_TOKEN = 'CLEAR_TOKEN',  EDIT_USER_MSG = 'EDIT_USER_MSG',  SET_NUM = 'SET_NUM'}
//新建modules src/store/modules/app/action.ts/** * @Author: Mr Chen  陈晓  * @Date: 2023-01-16 14:12:05 * @LastEditTime: 2023-02-09 09:20:58 * @Description: action * 任何傻子都能写出电脑能识别的代码,但我能写出任何人都能看懂的代码 **/import { ActionTree, ActionContext } from 'vuex'import { RootState } from '@/store'import { AppState } from './state'import { Mutations } from './mutations'import { AppActionTypes } from './action-types'import { AppMutationTypes } from './mutation-types'type AugmentedActionContext = {  commit<K extends keyof Mutations>(key: K, payload: Parameters<Mutations[K]>[1]): ReturnType<Mutations[K]>} & Omit<ActionContext<AppState, RootState>, 'commit'>// export interface Actions {//   [AppActionTypes.ACTION_RESET_TOKEN]({ commit }: AugmentedActionContext): void// }export const actions: ActionTree<AppState, RootState> & Actions = {  [AppActionTypes.ACTION_LOGIN]({ commit }: AugmentedActionContext, userData: object) {    commit(AppMutationTypes.SET_USER_MSG, userData)  },  [AppActionTypes.CLEAR_TOKEN]({ commit }: AugmentedActionContext) {    commit(AppMutationTypes.CLEAR_USER, null)  },  [AppActionTypes.CLEAR_TOKEN]({ commit }: AugmentedActionContext,userData: object) {    commit(AppMutationTypes.CLEAR_TOKEN, userData)  }, [AppActionTypes.SET_NUM]({ commit }: AugmentedActionContext,num: number) {   commit(AppMutationTypes.SET_NUM, num) },   }
//新建modules src/store/modules/app/mutation-types.ts/** * @Author: Mr Chen  陈晓  * @Date: 2023-01-16 14:12:05 * @LastEditTime: 2023-02-09 09:22:12 * @Description:  mutation-types类型约束 * 任何傻子都能写出电脑能识别的代码,但我能写出任何人都能看懂的代码 **/export enum AppMutationTypes {  SET_USER_MSG = 'SET_USER_MSG',  CLEAR_TOKEN = 'CLEAR_TOKEN',  EDIT_USER_MSG = 'EDIT_USER_MSG',  SET_NUM = 'SET_NUM'}
//新建modules src/store/modules/app/mutation.ts/** * @Author: Mr Chen  陈晓  * @Date: 2023-01-16 14:12:05 * @LastEditTime: 2023-02-09 09:22:12 * @Description:  mutation * 任何傻子都能写出电脑能识别的代码,但我能写出任何人都能看懂的代码 **/import { MutationTree } from 'vuex'import { AppState } from './state'import { AppMutationTypes } from './mutation-types'export type Mutations<S = AppState> = {  [AppMutationTypes.SET_TOKEN](state: S, token: string): void}export const mutations: MutationTree<AppState> & Mutations = {  [AppMutationTypes.SET_USER_MSG](state: AppState, userData: object) {	state.userData = userData  },  [AppMutationTypes.CLEAR_USER](state: AppState) {	state.userData = null  },  [AppMutationTypes.CLEAR_TOKEN](state: AppState, userData: object) {	state.userData = userData  },  [AppMutationTypes.SET_NUM](state: AppState, num: number) {  	state.num = num  }      }

src下创建type文件,并完善工程文件(约束类

//例如:分页参数,根据业务需要自行补充export interface PageParams {  data?: any  id?: string  from?: string}

src下创建styles文件,并完善工程文件(css样式)

//例如:styles/theme.scsspage {  --theme-color: #9ac2ff;}//例如:styles/index.scss@import './theme.scss'; //引入theme.scss

src下创建components文件,并完善工程文件(组件管理

//例如:components/drag-image.vue<template>  <view class="con">    <template v-if="viewWidth">      <movable-area v-if="show" class="area" :style="{ height: areaHeight }" @mouseenter="mouseenter"        @mouseleave="mouseleave">		<text v-if='imageList.length>0' class="tips_img">主</text>        <movable-view v-for="(item, index) in imageList" :key="item.id" class="view" direction="all" :y="item.y"          :x="item.x" :damping="40" :disabled="item.disable" @change="onChange($event, item)"          @touchstart="touchstart(item)" @mousedown="touchstart(item)" @touchend="touchend(item)"          @mouseup="touchend(item)" :style="{            width: viewWidth + 'px',            height: viewWidth + 'px',            'z-index': item.zIndex,            opacity: item.opacity          }">          <view class="area-con" :style="{            width: childWidth,            height: childWidth,            borderRadius: borderRadius + 'rpx',            transform: 'scale(' + item.scale + ')'          }">            <image class="pre-image" :src="item.src" mode="aspectFill"></image>			            <view class="del-con" @click="delImages(item, index)" @touchstart.stop="delImageMp(item, index)"              @touchend.stop="nothing()" @mousedown.stop="nothing()" @mouseup.stop="nothing()">              <view class="del-wrap">                <image class="del-image"                  src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAhCAYAAABX5MJvAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAhdEVYdENyZWF0aW9uIFRpbWUAMjAyMDowNzoyNSAyMTo1NDoyOU4TkJAAAADcSURBVFhH7ZfRCoMwDEXLvkjwwVf/bH/emmAyN6glTW9WBjsgwm28OeCLpj81Sil7zvlJ90UiONS/yY5VogsO6XrBg3IEQ5a/s8vRSWUAKmLqp2w5jz5BiNQEGMo3GbloDLtFXJ1IkaEuhAiiY6gEIqB4yqACSk9piIBiKQ8VUFpLviKg3C2rESKgWERCBZSWiEfgIfffYvrrsAgoISJ3Apy3zuTxcSxLQkV6ykNEPKVQkZEyiAiiZKgDIaC4upACSlcn5fM/+WuDCAHF1E/Z/N9AhkMZnPNDPI+UDjPIXgAQIGjNAAAAAElFTkSuQmCC">                </image>              </view>            </view>          </view>        </movable-view>        <view class="add" v-if="imageList.length < number"          :style="{ top: add.y, left: add.x, width: viewWidth + 'px', height: viewWidth + 'px' }" @click="addImages">          <view class="add-wrap" :style="{ width: childWidth, height: childWidth, borderRadius: borderRadius + 'rpx' }">           	<image  :style="{ width: childWidth, height: childWidth, borderRadius: borderRadius + 'rpx' }"  src='/static/images/addimg.png'></image>			<!-- <image style="width: 54rpx;height: 54rpx;"              src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADYAAAA2CAYAAACMRWrdAAABIUlEQVRoQ+2a2w2DMAxFeQzWrsMUbadAsEw3S1CqVgppKwLX8BEOP4iHTXx8uUgWdVXoVhdaV0VhSmf7vr/H8V3XzY6V3P9iD+nYOI5P7/01LMI596AwoZV0TIBXIUWFXhKLFBWYSFGhhxQN6SFFQ5i4ogITKSr0cEVDekjRECauqMBEigq9U7piOk2yAti27SUe5ljlTfPEQ6KZecTvwl4P3ytvOv06R2HDMNzes7+6aRrvnHvtf50L13Lp50rx88zcvNlS3JpwKQ67XyK04nq2nFbk/LqVjin0TvmBNgQ2S4UUDcliHgpMpKjQwxUN6SFFQ5i4ogITKSr0cEVDekjRECauqMAsVoph+hVPtYr5+03p9tbYQ96xrYtT4ootbAJGVxxVTapVswAAAABJRU5ErkJggg==">            </image> -->          </view>        </view>      </movable-area>    </template>  </view></template><script>export default {  emits: ['input', 'update:modelValue'],  props: {    // 排序图片    value: {      type: Array,      default: function () {        return []      }    },    // 排序图片    modelValue: {      type: Array,      default: function () {        return []      }    },    // 从 list 元素对象中读取的键名    keyName: {      type: String,      default: null    },    // 选择图片数量限制    number: {      type: Number,      default: 6    },    // 图片父容器宽度(实际显示的图片宽度为 imageWidth / 1.1 ),单位 rpx    // imageWidth > 0 则 cols 无效    imageWidth: {      type: Number,      default: 0    },    // 图片列数    cols: {      type: Number,      default: 3    },    // 图片圆角,单位 rpx    borderRadius: {      type: Number,      default: 0    },    // 图片周围空白填充,单位 rpx    padding: {      type: Number,      default: 10    },    // 拖动图片时放大倍数 [0, ∞)    scale: {      type: Number,      default: 1.1    },    // 拖动图片时不透明度    opacity: {      type: Number,      default: 0.7    },    // 自定义添加    addImage: {      type: Function,      default: null    },    // 删除确认    delImage: {      type: Function,      default: null    }  },  data() {    return {      imageList: [],      width: 0,      add: {        x: 0,        y: 0      },      colsValue: 0,      viewWidth: 0,      tempItem: null,      timer: null,      changeStatus: true,      preStatus: true,      first: true,      show: true,    }  },  computed: {    areaHeight() {      let height = ''      // return '285px'      if (this.imageList.length < this.number) {        height = (Math.ceil((this.imageList.length + 1) / this.colsValue) * this.viewWidth).toFixed() + 'px'      } else {        height = (Math.ceil(this.imageList.length / this.colsValue) * this.viewWidth).toFixed() + 'px'      }      console.log('areaHeight', height)      return height    },    childWidth() {      return this.viewWidth - this.rpx2px(this.padding) * 2 + 'px'    },  },  watch: {    areaHeight() {      this.show = false      this.$nextTick(() => {        this.show = true      })    },    value: {      handler(n) {        if (!this.first && this.changeStatus) {          console.log('watch', n)          let flag = false          for (let i = 0; i < n.length; i++) {            if (flag) {              this.addProperties(this.getSrc(n[i]))              continue            }            if (this.imageList.length === i || this.imageList[i].src !== this.getSrc(n[i])) {              flag = true              this.imageList.splice(i)              this.addProperties(this.getSrc(n[i]))            }          }        }      },      deep: true    },    modelValue: {      handler(n) {        if (!this.first && this.changeStatus) {          console.log('watch', n)          let flag = false          for (let i = 0; i < n.length; i++) {            if (flag) {              this.addProperties(this.getSrc(n[i]))              continue            }            if (this.imageList.length === i || this.imageList[i].src !== this.getSrc(n[i])) {              flag = true              this.imageList.splice(i)              this.addProperties(this.getSrc(n[i]))            }          }        }      },      deep: true    },  },  created() {    this.width = uni.getSystemInfoSync().windowWidth  },  mounted() {    const query = uni.createSelectorQuery().in(this)    query.select('.con').boundingClientRect(data => {      this.colsValue = this.cols      this.viewWidth = data.width / this.cols      if (this.imageWidth > 0) {        this.viewWidth = this.rpx2px(this.imageWidth)        this.colsValue = Math.floor(data.width / this.viewWidth)      }      let list = this.value      // #ifdef VUE3      list = this.modelValue      // #endif      for (let item of list) {        this.addProperties(this.getSrc(item))      }      this.first = false    })    query.exec()  },  methods: {    getSrc(item) {      if (this.keyName !== null) {        return item[this.keyName]      }      return item    },    onChange(e, item) {      if (!item) return      item.oldX = e.detail.x      item.oldY = e.detail.y      if (e.detail.source === 'touch') {        if (item.moveEnd) {          item.offset = Math.sqrt(Math.pow(item.oldX - item.absX * this.viewWidth, 2) + Math.pow(item.oldY - item            .absY * this.viewWidth, 2))        }        let x = Math.floor((e.detail.x + this.viewWidth / 2) / this.viewWidth)        if (x >= this.colsValue) return        let y = Math.floor((e.detail.y + this.viewWidth / 2) / this.viewWidth)        let index = this.colsValue * y + x        if (item.index != index && index < this.imageList.length) {          this.changeStatus = false          for (let obj of this.imageList) {            if (item.index > index && obj.index >= index && obj.index < item.index) {              this.change(obj, 1)            } else if (item.index < index && obj.index <= index && obj.index > item.index) {              this.change(obj, -1)            } else if (obj.id != item.id) {              obj.offset = 0              obj.x = obj.oldX              obj.y = obj.oldY              setTimeout(() => {                this.$nextTick(() => {                  obj.x = obj.absX * this.viewWidth                  obj.y = obj.absY * this.viewWidth                })              }, 0)            }          }          item.index = index          item.absX = x          item.absY = y          if (!item.moveEnd) {            setTimeout(() => {              this.$nextTick(() => {                item.x = item.absX * this.viewWidth                item.y = item.absY * this.viewWidth              })            }, 0)          }          // console.log('bbb', JSON.parse(JSON.stringify(item)));          this.sortList()        }      }    },    change(obj, i) {      obj.index += i      obj.offset = 0      obj.x = obj.oldX      obj.y = obj.oldY      obj.absX = obj.index % this.colsValue      obj.absY = Math.floor(obj.index / this.colsValue)      setTimeout(() => {        this.$nextTick(() => {          obj.x = obj.absX * this.viewWidth          obj.y = obj.absY * this.viewWidth        })      }, 0)    },    touchstart(item) {      this.imageList.forEach(v => {        v.zIndex = v.index + 9      })      item.zIndex = 99      item.moveEnd = true      this.tempItem = item      this.timer = setTimeout(() => {        item.scale = this.scale        item.opacity = this.opacity        clearTimeout(this.timer)        this.timer = null      }, 200)    },    touchend(item) {      this.previewImage(item)      item.scale = 1      item.opacity = 1      item.x = item.oldX      item.y = item.oldY      item.offset = 0      item.moveEnd = false      setTimeout(() => {        this.$nextTick(() => {          item.x = item.absX * this.viewWidth          item.y = item.absY * this.viewWidth          this.tempItem = null          this.changeStatus = true        })        // console.log('ccc', JSON.parse(JSON.stringify(item)));      }, 0)	   this.$emit('resetImg',this.imageList)      // console.log('ddd', JSON.parse(JSON.stringify(item)));    },    previewImage(item) {      if (this.timer && this.preStatus && this.changeStatus && item.offset < 28.28) {        clearTimeout(this.timer)        this.timer = null        const list = this.value || this.modelValue        let srcList = []		let numImg = ref(0)		this.imageList.map((tab, index) => {			srcList.push(item.src)			if(tab.src ==  item.src){				numImg.value = index			}		})		        uni.previewImage({          urls:srcList ,          current: srcList[numImg],          success: () => {            this.preStatus = false            setTimeout(() => {              this.preStatus = true            }, 600)          },          fail: (e) => {            console.log(e);          }        })      } else if (this.timer) {        clearTimeout(this.timer)        this.timer = null      }    },    mouseenter() {      //#ifdef H5      this.imageList.forEach(v => {        v.disable = false      })      //#endif    },    mouseleave() {      //#ifdef H5      if (this.tempItem) {        this.imageList.forEach(v => {          v.disable = true          v.zIndex = v.index + 9          v.offset = 0          v.moveEnd = false          if (v.id == this.tempItem.id) {            if (this.timer) {              clearTimeout(this.timer)              this.timer = null            }            v.scale = 1            v.opacity = 1            v.x = v.oldX            v.y = v.oldY            this.$nextTick(() => {              v.x = v.absX * this.viewWidth              v.y = v.absY * this.viewWidth              this.tempItem = null            })          }        })        this.changeStatus = true      }      //#endif    },    addImages() {		this.$emit('choiseImg')      // if (typeof this.addImage === 'function') {      //   this.addImage.bind(this.$parent)()      // } else {      //   let checkNumber = this.number - this.imageList.length      //   uni.chooseImage({      //     count: checkNumber,      //     sourceType: ['album', 'camera'],      //     success: res => {      //       let count = checkNumber <= res.tempFilePaths.length ? checkNumber : res.tempFilePaths.length      //       for (let i = 0; i < count; i++) {      //         this.addProperties(res.tempFilePaths[i])      //       }      //       this.sortList()      //     }      //   })      // }    },    delImages(item, index) {      if (typeof this.delImage === 'function') {        this.delImage.bind(this.$parent)(() => {          this.delImageHandle(item, index)        })      } else {        this.delImageHandle(item, index)      }    },    delImageHandle(item, index) {      this.imageList.splice(index, 1)	  this.$emit('resetImg',this.imageList)      for (let obj of this.imageList) {        if (obj.index > item.index) {          obj.index -= 1          obj.x = obj.oldX          obj.y = obj.oldY          obj.absX = obj.index % this.colsValue          obj.absY = Math.floor(obj.index / this.colsValue)          this.$nextTick(() => {            obj.x = obj.absX * this.viewWidth            obj.y = obj.absY * this.viewWidth          })        }      }      this.add.x = (this.imageList.length % this.colsValue) * this.viewWidth + 'px'      this.add.y = Math.floor(this.imageList.length / this.colsValue) * this.viewWidth + 'px'      this.sortList()    },    delImageMp(item, index) {      //#ifdef MP      this.delImages(item, index)      //#endif    },    sortList() {      console.log('sortList');      const result = []      let source = this.value      // #ifdef VUE3      source = this.modelValue      // #endif      let list = this.imageList.slice()      list.sort((a, b) => {        return a.index - b.index      })      for (let s of list) {        let item = source.find(d => this.getSrc(d) == s.src)        if (item) {          result.push(item)        } else {          if (this.keyName !== null) {            result.push({              [this.keyName]: s.src            })          } else {            result.push(s.src)          }        }      }      this.$emit("input", result);      this.$emit("update:modelValue", result);    },    addProperties(item) {      console.log(item);      let absX = this.imageList.length % this.colsValue      let absY = Math.floor(this.imageList.length / this.colsValue)      let x = absX * this.viewWidth      let y = absY * this.viewWidth      this.imageList.push({        src: item,        x,        y,        oldX: x,        oldY: y,        absX,        absY,        scale: 1,        zIndex: 9,        opacity: 1,        index: this.imageList.length,        id: this.guid(16),        disable: false,        offset: 0,        moveEnd: false      })      this.add.x = (this.imageList.length % this.colsValue) * this.viewWidth + 'px'      this.add.y = Math.floor(this.imageList.length / this.colsValue) * this.viewWidth + 'px'    },    nothing() { },    rpx2px(v) {      return this.width * v / 750    },    guid(len = 32) {      const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')      const uuid = []      const radix = chars.length      for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]      uuid.shift()      return `u${uuid.join('')}`    }  }}</script><style lang="scss" scoped>.con {  // padding: 30rpx;  .area {    width: 100%;	position: relative;	.tips_img{		position: absolute;		left:0rpx;		top:0rpx;		z-index: 999;		display: inline-block;		width:42rpx;		height:42rpx;		line-height: 42rpx;		text-align: center;		border-radius: 50%;		font-size: 20rpx;		background-color: rgba(0,0,0,.5);		color:#fff;	}    .view {      display: flex;      justify-content: center;      align-items: center;      .area-con {        position: relative;        overflow: hidden;		.tips_img{			position: absolute;			right:0rpx;			bottom:0rpx;			z-index: 999;			display: inline-block;			width:42rpx;			height:42rpx;			line-height: 42rpx;			text-align: center;			border-radius: 50%;			font-size: 20rpx;			background-color: rgba(0,0,0,.5);			color:#fff;					}        .pre-image {          width: 100%;          height: 100%;        }        .del-con {          position: absolute;          top: 0rpx;          right: 0rpx;          padding: 0 0 20rpx 20rpx;          .del-wrap {            width: 36rpx;            height: 36rpx;            background-color: rgba(0, 0, 0, 0.4);            border-radius: 0 0 0 10rpx;            display: flex;            justify-content: center;            align-items: center;            .del-image {              width: 20rpx;              height: 20rpx;            }          }        }      }    }    .add {      position: absolute;      display: flex;      justify-content: center;      align-items: center;      .add-wrap {        display: flex;        justify-content: center;        align-items: center;        background-color: #fff;      }    }  }}</style>

src下创建utils文件,并完善工程文件(工具类

//新建src/utils/requestClass.ts/** * @Author: Mr Chen  陈晓  * @Date: 2023-01-16 14:12:05 * @LastEditTime: 2023-02-09 09:59:03 * @Description: 请求封装requestClass类 * 任何傻子都能写出电脑能识别的代码,但我能写出任何人都能看懂的代码 **/const config = Symbol('config')const isCompleteURL = Symbol('isCompleteURL')const requestBefore = Symbol('requestBefore')const requestAfter = Symbol('requestAfter')class requestClass {  // 默认配置  [config]: { baseURL?: string } & UniApp.RequestOptions = {    baseURL: '',    url: '',    header: {      'content-type': 'application/x-www-form-urlencoded'    },    method: 'GET',    timeout: 3000,    dataType: 'json',    responseType: 'text'  }  // 拦截器  interceptors = {    request: (func: Fn) => {      if (func) {        requestClass[requestBefore] = func      } else {        requestClass[requestBefore] = (request) => request      }    },    response: (func: Fn) => {      if (func) {        requestClass[requestAfter] = func      } else {        requestClass[requestAfter] = (response) => response      }    },  }  // 请求之前,是默认配置  static [requestBefore](config: UniApp.RequestOptions) {    return config  }  // 请求之后,默认配置发生改变的话  static [requestAfter](response: any) {    return response  }  // 判断url是否完整  static [isCompleteURL](url: string) {    return /(http|https):\/\/([\w.]+\/?)\S*/.test(url)  }  request(options: UniApp.RequestOptions & { baseURL?: string }) {    options.baseURL = options.baseURL || this[config].baseURL    options.dataType = options.dataType || this[config].dataType    options.url = requestClass[isCompleteURL](options.url) ? options.url : (options.baseURL + options.url)	    options.data = options.data    options.header = { ...options.header, ...this[config].header }    options.method = options.method || this[config].method    options = { ...options, ...requestClass[requestBefore](options) }    return new Promise((resolve, reject) => {      options.success = function (res) {        resolve(requestClass[requestAfter](res))      }      options.fail = function (err) {        reject(requestClass[requestAfter](err))      }      uni.request(options)      // 中断请求实现方法      // let obj: any = {}      // obj[request.url] = uni.request(options)      // abortRequest() {      //   for (const key in obj) {      //     if (Object.prototype.hasOwnProperty.call(obj, key)) {      //       const element = obj[key];      //       element.abort()      //     }      //   }      // }    })  }  get(url: string, data: any = {}, options: Recordable = {}) {    return this.request({ ...options, url, data, method: 'GET' })  }  post(url: string, data: any = {}, options: Recordable = {}) {    return this.request({ ...options, url, data, method: 'POST' })  }  put(url: string, data: any = {}, options: Recordable = {}) {    return this.request({ ...options, url, data, method: 'PUT' })  }  delete(url: string, data: any = {}, options: Recordable = {}) {    return this.request({ ...options, url, data, method: 'DELETE' })  }  getConfig() {    return this[config]  }    // 修改默认配置的一个方法,可以修改请求地址,请求方式等等..  setConfig(func: Fn) {    this[config] = func(this[config])  }}export default requestClass
//新建src/utils/request.ts/** * @Author: Mr Chen  陈晓  * @Date: 2023-01-16 14:12:05 * @LastEditTime: 2023-02-09 09:59:03 * @Description: 请求封装request * 任何傻子都能写出电脑能识别的代码,但我能写出任何人都能看懂的代码 **/import requestClass from './requestClass'import { HTTP_REQUEST_URL_H5, HTTP_REQUEST_URL_APP } from '@/config/app'import { AppActionTypes } from '@/store/modules/app/action-types'import qs from 'qs'import { useStore } from 'vuex'const Request = new requestClass()const platform = uni.getSystemInfoSync().platform// 请求拦截器Request.interceptors.request((request: any) => {	request.header['device-os'] = platform	  if (request.header.contentType) {    request.header['content-type'] = request.header.contentType    delete request.header.contentType  }  if(uni.getStorageSync('userData')){	request.header['token'] = uni.getStorageSync('userData').token	// request.header['id'] = uni.getStorageSync('userData').id	// request.header['uid'] = uni.getStorageSync('userData').userIdBuss	// request.header['pid'] = uni.getStorageSync('userData').lmpt_userid  }  if (request.method === 'GET') {    request.data = qs.stringify(request.data)    request.url = request.url + '?' + request.data  }  return request})// 响应拦截器Request.interceptors.response((response: any) => {  const token = uni.getStorageSync('userData').token  if (response.data.code === 102) {    uni.showToast({      title: token ? '请重新登录' : '请先登录',      icon: 'none',      duration: 2000,    })       uni.removeStorageSync('userData')	// console.log(store)	// store.dispatch(AppActionTypes.ACTION_LOGIN, {})	const url = '/pages/template/user/index'	setTimeout(		function() {			uni.switchTab({ url })		}, 2000)  }  return response})// 设置默认配置Request.setConfig((config: any) => {	config.header['device-os'] = platform	// #ifdef APP-PLUS	config.baseURL = HTTP_REQUEST_URL_APP	// #endif	// #ifndef APP-PLUS	config.baseURL = HTTP_REQUEST_URL_H5	// #endif  if (uni.getStorageSync('userData')) {    config.header['token'] = uni.getStorageSync('userData').token	// config.header['id'] = uni.getStorageSync('userData').id	// config.header['uid'] = uni.getStorageSync('userData').userIdBuss	// config.header['pid'] = uni.getStorageSync('userData').lmpt_userid	  }  return config})export default Request

src下创建app文件,并完善工程文件

//在app文件下创建api文件夹 如:app/api/index.tsimport request from '@/utils/request' //导入request/** * API 数据总操作类 * Author Chenxiao * Time 2023-02-09 * 任何傻子都能写出电脑能识别的代码,但我能写出任何人都能看懂的代码 */const options = {  header: { 'content-type': 'application/x-www-form-urlencoded'},  token: uni.getStorageSync('userData').token}/** * @method 不同请求通用写法接口 */export function testGet(data :any) {  return request.get('', data)}export function testPost(data :any) {  return request.post('', data, options)}export function testPut(data :any) {  return request.post('', data)}export function testDelete(data :any) {  return request.delete('', data)}/** * @method 正式接口 *  */}export default API

下一节我们继续把剩余的几个配置做一个完善,例如,底部菜单数据载入,全局静态参数配置,文件自动混入等

欢迎大家收藏点赞转发,我们一起学习成长!

标签: #mysqluuiduuid