封装基础框架

main
ihzero 2024-04-24 16:04:31 +08:00
parent 6e2cd9fe2a
commit 020b2b001f
11 changed files with 376 additions and 520 deletions

View File

@ -0,0 +1,56 @@
<template>
<BaesData :data="data" :colums="colums">
<template v-slot="{ data, slotName }">
<slot :slotName="slotName" :data="data"> </slot>
</template>
</BaesData>
</template>
<script setup>
import { onBeforeMount } from 'vue'
import { http } from '@/utils/request'
import { ref } from 'vue'
import BaesData from './base-data.vue'
const props = defineProps({
colums: {
type: Array,
default: () => [],
},
apiUrl: {
type: String,
default: '',
},
data: {
type: Object,
},
params: {
type: Object,
},
method: {
type: String,
default: 'GET',
},
header: {
type: Object,
},
})
const data = ref({})
onBeforeMount(async () => {
init()
})
const init = async () => {
if (!props.apiUrl) return
try {
const resData = await http.request({
url: props.apiUrl,
method: props.method,
data: props.data,
params: props.params,
header: props.header,
})
data.value = resData
} catch (error) {}
}
</script>

View File

@ -0,0 +1,59 @@
<template>
<!-- <uv-list v-if="colums.length && data && Object.keys(data).length">
<template v-for="(item, i) in columsList" :key="i">
<slot :slotName="item.dataIndex" :data="item">
<uv-list-item :title="item.title" :right-text="item?.value">
</uv-list-item>
</slot>
</template>
</uv-list> -->
<uv-form labelWidth="160rpx">
<template v-for="(item, i) in columsList" :key="i">
<slot :slotName="item.dataIndex" :data="item">
<uv-form-item :label="item.title" :labelPosition="item.labelPosition">
<uv-input inputAlign="right" :border="`none`" v-model="item.value"></uv-input>
</uv-form-item>
</slot>
</template>
</uv-form>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({
colums: {
type: Array,
default: () => [],
},
data: {
type: Object,
default: () => {},
},
})
const columsList = computed(() => {
const arr = []
props.colums.forEach((e) => {
const { dataIndex, format } = e
// console.log(props.data)
// props.data[dataIndex]
let str =getValue(props.data,dataIndex)
if (isFunction(format)) {
str = format(str)
}
arr.push({
...e,
value: str,
})
})
return arr
})
const getValue = (obj, path) => {
return path.split('.').reduce((acc, key) => (acc ? acc[key] : undefined), obj)
}
const isFunction = (fn) => {
return typeof fn === 'function'
}
</script>

View File

@ -62,4 +62,6 @@ const upCallback = async (mescroll) => {
mescroll.endErr() //
})
}
</script>

View File

@ -0,0 +1,57 @@
/**
* nuxt/composables/http.ts
*/
// 基于useFetch()的网络请求封装
//全局基础URL
const BASEURL: string = "http://127.xxx.xxx:3000"; //全局后台服务器请求地址
//定义ts变量类型接口
interface HttpParms {
baseURL?: string, //请求的基本URL即后台服务器地址若服务器请求地址只有一个可不填
url: string, //请求api接口地址
method?: any, //请求方法
query?: any, //添加查询搜索参数到URL
body?: any //请求体
}
/**
*
* @param obj
* @returns
*/
export const http = (obj: HttpParms) => {
const res = new Promise<void>((resolve, reject) => {
useFetch(
(obj.baseURL ?? BASEURL) + obj.url,
{
method: obj.method ?? "GET",
query: obj?.query ?? null,
body: obj?.body ?? null,
onRequest({ request, options }) {
// 设置请求报头
options.headers = options.headers || {}
/**如果接口需求携带token请求则可先自行使用官方的useCookie()方法设置Cookie存储后再使用useCookie()方法取出token使用。如下例子*/
//const token = useCookie('token')
//@ts-ignore
//options.headers.Authorization = token.value||null
},
onRequestError({ request, options, error }) {
// 处理请求错误
console.log("服务器链接失败!")
reject(error)
},
onResponse({ request, response, options }) {
// 处理响应数据
resolve(response._data)
},
onResponseError({ request, response, options }) {
// 处理响应错误
}
},
)
})
return res;
}

View File

@ -1,316 +0,0 @@
{
"pages": [
{
"path": "pages/login/index",
"style": {
"navigationBarTitleText": "登录"
}
},
{
"path": "pages/home/index",
"style": {
"navigationBarTitleText": "首页"
}
},
{
"path": "pages/revert/index",
"style": {
"navigationBarTitleText": "上报"
}
},
{
"path": "pages/statement/index",
"style": {
"navigationBarTitleText": "报表"
}
},
{
"path": "pages/mine/index",
"style": {
"navigationBarTitleText": "我的"
}
}
],
"subPackages": [
{
"root": "pages/data",
"pages": [
{
"path": "brokerage/index",
"style": {
"navigationBarTitleText": "提成数据"
}
},
{
"path": "performance/index",
"style": {
"navigationBarTitleText": "业绩数据"
}
},
{
"path": "upload/index",
"style": {
"navigationBarTitleText": "上传数据"
}
}
]
},
{
"root": "pages/user",
"pages": [
{
"path": "index",
"style": {
"navigationBarTitleText": "员工管理"
}
},
{
"path": "update",
"style": {
"navigationBarTitleText": "修改信息"
}
},
{
"path": "detail",
"style": {
"navigationBarTitleText": "员工详情"
}
}
]
},
{
"root": "pages/setting",
"pages": [
{
"path": "index",
"style": {
"navigationBarTitleText": "设置"
}
},
{
"path": "password",
"style": {
"navigationBarTitleText": "修改密码"
}
},
{
"path": "complain",
"style": {
"navigationBarTitleText": "举报投诉"
}
},
{
"path": "suggestion",
"style": {
"navigationBarTitleText": "意见箱"
}
}
]
},
{
"root": "pages/task",
"pages": [
{
"path": "index",
"style": {
"navigationBarTitleText": "任务列表"
}
},
{
"path": "submit",
"style": {
"navigationBarTitleText": "任务提交"
}
},
{
"path": "task_hygienes_submit",
"style": {
"navigationBarTitleText": "清洁任务提交"
}
},
{
"path": "task_ledgers_submit",
"style": {
"navigationBarTitleText": "数据上报"
}
},
{
"path": "detail",
"style": {
"navigationBarTitleText": "任务详情"
}
}
]
},
{
"root": "pages/expense-account",
"pages": [
{
"path": "index",
"style": {
"navigationBarTitleText": "报销管理"
}
},
{
"path": "submit",
"style": {
"navigationBarTitleText": "报销提交"
}
}
]
},
{
"root": "pages/work",
"pages": [
{
"path": "list",
"style": {
"navigationBarTitleText": "升职申请"
}
},
{
"path": "detail",
"style": {
"navigationBarTitleText": "升职申请"
}
},
{
"path": "create",
"style": {
"navigationBarTitleText": "升职申请"
}
}
]
},
{
"root": "pages/make-card",
"pages": [
{
"path": "list",
"style": {
"navigationBarTitleText": "补卡申请"
}
},
{
"path": "create",
"style": {
"navigationBarTitleText": "补卡申请"
}
},
{
"path": "detail",
"style": {
"navigationBarTitleText": "补卡审核"
}
}
]
},
{
"root": "pages/ask-leave",
"pages": [
{
"path": "list",
"style": {
"navigationBarTitleText": "请假申请"
}
},
{
"path": "create",
"style": {
"navigationBarTitleText": "请假申请"
}
},
{
"path": "detail",
"style": {
"navigationBarTitleText": "请假详情"
}
}
]
},
{
"root": "pages/train-books",
"pages": [
{
"path": "index",
"style": {
"navigationBarTitleText": "培训课件"
}
},
{
"path": "detail",
"style": {
"navigationBarTitleText": "培训课件"
}
}
]
},
{
"root": "pages/examination",
"pages": [
{
"path": "index",
"style": {
"navigationBarTitleText": "培训考试"
}
},
{
"path": "detail",
"style": {
"navigationBarTitleText": "培训考试"
}
}
]
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#FFFFFF",
"backgroundColor": "#FFFFFF",
"navigationStyle": "custom",
"backgroundColorTop": "#FFFFFF",
"app-plus": {
"bounce": "none",
"scrollIndicator": "none"
}
},
"tabBar": {
"color": "#333",
"selectedColor": "#ff3c2a",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [
{
"pagePath": "pages/home/index",
"selectedIconPath": "static/images/home.png",
"iconPath": "static/images/home.png",
"text": "首页"
},
{
"pagePath": "pages/revert/index",
"selectedIconPath": "static/images/home.png",
"iconPath": "static/images/home.png",
"text": "上报"
},
{
"pagePath": "pages/statement/index",
"selectedIconPath": "static/images/home.png",
"iconPath": "static/images/home.png",
"text": "报表"
},
{
"pagePath": "pages/mine/index",
"selectedIconPath": "static/images/home.png",
"iconPath": "static/images/home.png",
"text": "我的"
}
]
},
"easycom": {
"autoscan": true,
"custom": {
"^uv-(.*)": "@climblee/uv-ui/components/uv-$1/uv-$1.vue"
}
}
}

View File

@ -1,14 +1,13 @@
<template>
<view>
<CuNavbar title="提成数据" isBack></CuNavbar>
<mescroll-body @init="mescrollInit" @down="downCallback" @up="upCallback">
<MescrollItem :top="44" :i="0" apiUrl="/account/store-master-commissions">
<view class="space-y-20rpx px-base mt-20rpx">
<view v-for="(item, i) in list" :key="i">
<Item :data="item"></Item>
</view>
</view>
</mescroll-body>
</MescrollItem>
</view>
</template>
@ -18,33 +17,10 @@ import Item from './components/item.vue'
import { onLoad } from '@dcloudio/uni-app'
import { http } from '@/utils/request'
import { ref } from 'vue'
import MescrollItem from '@/components/mescroll-api/one'
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
import useMescroll from '@/uni_modules/mescroll-uni/hooks/useMescroll.js'
const { mescrollInit, downCallback, getMescroll } = useMescroll(
onPageScroll,
onReachBottom
)
const list = ref([])
import useMescrollComp from '@/uni_modules/mescroll-uni/hooks/useMescrollComp.js'
const { mescrollItem } = useMescrollComp(onPageScroll, onReachBottom)
const upCallback = async (mescroll) => {
const { size, num } = mescroll
try {
const resData = await http.get('/account/store-master-commissions', {
params: {
per_page: size,
page: num,
},
})
const curPageData = resData.data || []
if (num === 1) list.value = []
list.value = list.value.concat(curPageData)
mescroll.endSuccess(curPageData.length)
} catch (error) {
mescroll.endErr() // ,
}
}
</script>

View File

@ -15,102 +15,110 @@
<view class="card" v-for="(item, i) in opList" :key="i">
<TitleComp :title="item.title"></TitleComp>
<view class="grid grid-cols-3 mt-20rpx gap-20rpx">
<OpItem v-for="(child, ii) in item.children" :key="ii" :data="child"></OpItem>
<template v-for="(child, ii) in item.children" :key="ii">
<OpItem
:data="child"
v-if="child?.rouls ? checkPermission(child.rouls) : true"
></OpItem>
</template>
</view>
</view>
</view>
</view>
</template>
<script setup>
import TitleComp from "@/components/title-comp/index"
import OpItem from "./components/op-item.vue"
import CuNavbar from "@/components/cu-navbar/index"
import TitleComp from '@/components/title-comp/index'
import OpItem from './components/op-item.vue'
import CuNavbar from '@/components/cu-navbar/index'
import checkPermission from '@/utils/permission'
const opList = [
{
title: "门店数据",
title: '门店数据',
children: [
{
icon: "order",
title: "业绩数据",
url: "/pages/data/performance/index"
icon: 'order',
title: '业绩数据',
url: '/pages/data/performance/index',
},
{
icon: "folder",
title: "提成数据",
url: "/pages/data/brokerage/index"
}
]
icon: 'folder',
title: '提成数据',
url: '/pages/data/brokerage/index',
},
],
},
{
title: "办公管理",
title: '办公管理',
children: [
{
icon: "photo-fill",
title: "员工管理",
url: "/pages/user/index"
icon: 'photo-fill',
title: '员工管理',
url: '/pages/user/index',
rouls: ['admin'],
},
{
icon: "lock",
title: "我的任务",
url: "/pages/task/index"
icon: 'lock',
title: '我的任务',
url: '/pages/task/index',
},
{
icon: "home-fill",
title: "报销管理",
url: "/pages/expense-account/index"
icon: 'home-fill',
title: '报销管理',
url: '/pages/expense-account/index',
},
{
icon: "map-fill",
title: "升职申请",
url: "/pages/work/list"
icon: 'map-fill',
title: '升职申请',
url: '/pages/work/list',
},
{
icon: "grid-fill",
title: "补卡申请",
url: "/pages/make-card/list"
icon: 'grid-fill',
title: '补卡申请',
url: '/pages/make-card/list',
},
{
icon: "car",
title: "请假申请",
url: "/pages/ask-leave/list"
icon: 'car',
title: '请假申请',
url: '/pages/ask-leave/list',
},
{
icon: "setting-fill",
title: "出差报备",
url: "/pages/business/list"
icon: 'setting-fill',
title: '出差报备',
url: '/pages/business/list',
},
{
icon: "server-man",
title: "加班报备",
url: "/pages/overtime/list"
icon: 'server-man',
title: '加班报备',
url: '/pages/overtime/list',
},
{
icon: "camera",
title: "合同管理",
url: "/pages/contract/list"
}
]
icon: 'camera',
title: '合同管理',
url: '/pages/contract/list',
},
],
},
{
title: "天天向上",
title: '天天向上',
children: [
{
icon: "account",
title: "培训课件",
url: "/pages/train-books/index"
icon: 'account',
title: '培训课件',
url: '/pages/train-books/index',
},
{
icon: "twitte",
title: "培训考试",
url: "/pages/examination/index"
}
]
}
icon: 'twitte',
title: '培训考试',
url: '/pages/examination/index',
},
],
},
]
const goPath = url => {
const goPath = (url) => {
uni.navigateTo({
url
url,
})
}
</script>

View File

@ -17,19 +17,10 @@
任务时间{{ timeFormat(item.start_at, 'yyyy年mm月dd日') }} -
{{ timeFormat(item.end_at, 'yyyy年mm月dd日') }}
</view>
<template v-if="item.taskable.status == 2">
<view class="py-10rpx">
<uv-line></uv-line>
</view>
<view class="flex justify-end">
<view @click.stop="onTask">
<uv-button type="primary" size="mini">去完成</uv-button>
</view>
</view>
</template>
</view>
</template>
<script setup>
import { computed } from 'vue'
import statusFun from '@/utils/status'
import { timeFormat } from '@climblee/uv-ui/libs/function/index'
const props = defineProps({
@ -37,9 +28,21 @@ const props = defineProps({
})
const onClick = () => {
console.log(props.item)
const type = props.item.taskable_type
const { status } = props.item.taskable
let url
if (type === 'task_hygienes') {
if (status === 2 || status == 4) {
url = `/pages/task/task_hygienes_submit?id=${props.item.id}`
} else {
url = `/pages/task/detail?id=${props.item.id}`
}
} else if (type === 'task_ledgers') {
url = `/pages/task/${type}_submit?id=${props.item.id}`
}
uni.navigateTo({
url: `/pages/task/${type}_submit?id=${props.item.id}`,
url: url,
})
}

View File

@ -0,0 +1,76 @@
<template>
<view class="px-base">
<CuNavbar title="任务详情"></CuNavbar>
<view
class="mt-30rpx card-shadow bg-white rounded-19rpx px-base text-[#333333] text-27rpx"
>
<view class="py-20rpx flex items-center justify-between">
<view>申请人</view>
<view class="text-hex-999999">测试人</view>
</view>
<uv-line></uv-line>
<view class="py-20rpx flex items-center justify-between">
<view>所属门店</view>
<view class="text-hex-999999">具体门店名称</view>
</view>
<uv-line></uv-line>
<view class="py-20rpx flex items-center justify-between">
<view>电话号码</view>
<view class="text-hex-999999">具体门店名称</view>
</view>
<uv-line></uv-line>
<view class="py-20rpx flex items-center justify-between">
<view>申请时间</view>
<view class="text-hex-999999">具体门店名称</view>
</view>
<uv-line></uv-line>
<view class="py-20rpx">
<view>申请范围</view>
<view class="text-hex-999999 mt-20rpx">具体门店名称</view>
</view>
<uv-line></uv-line>
<view class="py-20rpx">
<view>清洁结果</view>
<view class="text-hex-999999 mt-20rpx">
<view class="bg-gray-50 b-solid w-130rpx h-130rpx"></view>
</view>
</view>
</view>
<view class="h-100rpx">
<view
class="fixed bottom-0 left-0 right-0 h-120rpx bg-white flex items-center px-base space-x-30rpx"
>
<view class="flex-1">
<uv-button color="#999999" shape="circle" plain block>
拒绝
</uv-button>
</view>
<view class="flex-1">
<uv-button type="primary" shape="circle" block> 通过 </uv-button>
</view>
</view>
</view>
</view>
</template>
<script setup>
import CuNavbar from '@/components/cu-navbar/index'
import { onLoad } from '@dcloudio/uni-app'
import { http } from '@/utils/request'
import { ref } from 'vue'
const id = ref(null)
onLoad((opt) => {
id.value = opt.id
getDetail()
})
const getDetail = async () => {
const resdata = await http.get(`/tasks/${id.value}`, {
params: {
id: id.value,
},
})
console.log(resdata);
}
</script>

View File

@ -1,47 +1,23 @@
<template>
<view class="px-base">
<CuNavbar title="任务详情"></CuNavbar>
<view
class="mt-30rpx card-shadow bg-white rounded-19rpx px-base text-[#333333] text-27rpx"
>
<view class="py-20rpx flex items-center justify-between">
<view>申请人</view>
<view class="text-hex-999999">测试人</view>
</view>
<uv-line></uv-line>
<view class="py-20rpx flex items-center justify-between">
<view>所属门店</view>
<view class="text-hex-999999">具体门店名称</view>
</view>
<uv-line></uv-line>
<view class="py-20rpx flex items-center justify-between">
<view>电话号码</view>
<view class="text-hex-999999">具体门店名称</view>
</view>
<uv-line></uv-line>
<view class="py-20rpx flex items-center justify-between">
<view>申请时间</view>
<view class="text-hex-999999">具体门店名称</view>
</view>
<uv-line></uv-line>
<view class="py-20rpx">
<view>申请范围</view>
<view class="text-hex-999999 mt-20rpx">具体门店名称</view>
</view>
<uv-line></uv-line>
<view class="py-20rpx">
<view>清洁结果</view>
<view class="text-hex-999999 mt-20rpx">
<view class="bg-gray-50 b-solid w-130rpx h-130rpx"></view>
<BaseCompApi :apiUrl="`/tasks/${id}`" :colums="baseColums">
<template v-slot="{ slotName, data }">
<view v-if="slotName == 'taskable.description'">
{{ data }}
</view>
</view>
</view>
</template>
</BaseCompApi>
<view class="h-100rpx">
<view
class="fixed bottom-0 left-0 right-0 h-120rpx bg-white flex items-center px-base space-x-30rpx"
>
<view class="flex-1">
<uv-button color="#999999" shape="circle" plain block> 拒绝 </uv-button>
<uv-button color="#999999" shape="circle" plain block>
拒绝
</uv-button>
</view>
<view class="flex-1">
<uv-button type="primary" shape="circle" block> 通过 </uv-button>
@ -52,4 +28,37 @@
</template>
<script setup>
import CuNavbar from '@/components/cu-navbar/index'
import { onLoad } from '@dcloudio/uni-app'
import { ref } from 'vue'
import BaseCompApi from '@/components/base-comp/base-api.vue'
import { timeFormat } from '@climblee/uv-ui/libs/function'
const baseColums = [
{
title: '申请人',
dataIndex: 'name',
},
{
title: '所属门店',
dataIndex: 'taskable.store.address',
},
{
title: '电话号码',
dataIndex: '',
},
{
title: '申请时间',
dataIndex: 'created_at',
format: timeFormat,
},
{
title: '清洁范围',
dataIndex: 'taskable.description',
labelPosition: 'top',
},
]
const id = ref(null)
onLoad((opt) => {
id.value = opt.id
})
</script>

View File

@ -1,74 +0,0 @@
<template>
<view>
<CuNavbar title="我的任务"></CuNavbar>
<uv-sticky bgColor="#fff">
<uv-tabs
:activeStyle="{ color: '#ee2c37' }"
:scrollable="false"
lineColor="#ee2c37"
:list="tabList"
></uv-tabs>
</uv-sticky>
<mescroll-body @init="mescrollInit" @down="downCallback" @up="upCallback">
<view class="px-base space-y-20rpx mt-30rpx">
<view
v-for="item in 4"
class="card-shadow bg-white rounded-19rpx p-base space-y-10rpx"
>
<view class="text-30rpx">月度清洁任务</view>
<view class="text-24rpx text-hex-999999">
任务时间2022年03月01号 - 2022年03月31号
</view>
<view class="text-24rpx text-hex-999999">待完成</view>
</view>
</view>
</mescroll-body>
</view>
</template>
<script setup>
import { http } from '@/utils/request'
import CuNavbar from '@/components/cu-navbar/index'
import { computed, reactive, ref } from 'vue'
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
import useMescroll from '@/uni_modules/mescroll-uni/hooks/useMescroll.js'
const { mescrollInit, downCallback, getMescroll } = useMescroll(
onPageScroll,
onReachBottom
)
const list = ref([])
const tabList = ref([
{
name: '任务列表',
apiUrl: '/tasks',
},
{
name: '任务审核',
apiUrl: '/workflow',
params:{
}
},
])
const upCallback = async (mescroll) => {
const { size, num } = mescroll
try {
const resData = await http.get('/tasks', {
params: {
per_page: size,
page: num,
},
})
const curPageData = resData.data || []
if (num === 1) list.value = []
list.value = list.value.concat(curPageData)
mescroll.endSuccess(curPageData.length)
} catch (error) {
console.log(error)
mescroll.endErr() // ,
} finally {
// firstloading.value = false
}
}
</script>