修改bug
parent
4a45fb37ed
commit
27e7f93ae1
|
|
@ -56,6 +56,7 @@
|
||||||
"@dcloudio/uni-mp-xhs": "3.0.0-3090920231225001",
|
"@dcloudio/uni-mp-xhs": "3.0.0-3090920231225001",
|
||||||
"@dcloudio/uni-quickapp-webview": "3.0.0-3090920231225001",
|
"@dcloudio/uni-quickapp-webview": "3.0.0-3090920231225001",
|
||||||
"@qiun/ucharts": "^2.5.0-20230101",
|
"@qiun/ucharts": "^2.5.0-20230101",
|
||||||
|
"dayjs": "^1.11.11",
|
||||||
"luch-request": "^3.1.1",
|
"luch-request": "^3.1.1",
|
||||||
"pinia": "2.0.33",
|
"pinia": "2.0.33",
|
||||||
"pinia-plugin-persistedstate": "^3.2.1",
|
"pinia-plugin-persistedstate": "^3.2.1",
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,12 @@
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "考勤记录"
|
"navigationBarTitleText": "考勤记录"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/userInfo/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "个人信息"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"subPackages": [
|
"subPackages": [
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
</uv-form-item>
|
</uv-form-item>
|
||||||
<uv-line color="#f5f5f5"></uv-line>
|
<uv-line color="#f5f5f5"></uv-line>
|
||||||
<uv-form-item required label="请假理由" prop="reason" labelPosition="top">
|
<uv-form-item required label="请假理由" prop="reason" labelPosition="top">
|
||||||
<uv-textarea v-model="form.reason" count placeholder="请输入" :border="`none`" :maxlength="200"></uv-textarea>
|
<uv-textarea :customStyle="{ padding: '0' }" v-model="form.reason" count placeholder="请输入" :border="`none`" :maxlength="200"></uv-textarea>
|
||||||
</uv-form-item>
|
</uv-form-item>
|
||||||
</uv-form>
|
</uv-form>
|
||||||
</view>
|
</view>
|
||||||
|
|
|
||||||
|
|
@ -221,15 +221,15 @@ export default {
|
||||||
}, {
|
}, {
|
||||||
title: '申请人',
|
title: '申请人',
|
||||||
dataIndex: 'check.subject.employee.name',
|
dataIndex: 'check.subject.employee.name',
|
||||||
|
}, {
|
||||||
|
title: '申请时间',
|
||||||
|
dataIndex: 'check.subject.created_format',
|
||||||
}, {
|
}, {
|
||||||
title: '所属门店',
|
title: '所属门店',
|
||||||
dataIndex: 'check.subject.store.title',
|
dataIndex: 'check.subject.store.title',
|
||||||
}, {
|
}, {
|
||||||
title: '电话号码',
|
title: '电话号码',
|
||||||
dataIndex: 'check.subject.employee.phone'
|
dataIndex: 'check.subject.employee.phone'
|
||||||
}, {
|
|
||||||
title: '申请时间',
|
|
||||||
dataIndex: 'check.subject.created_format',
|
|
||||||
}, {
|
}, {
|
||||||
title: '请假类型',
|
title: '请假类型',
|
||||||
dataIndex: 'check.subject.type.name',
|
dataIndex: 'check.subject.type.name',
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
>
|
>
|
||||||
<view class="flex-1" v-if="modelOptions.isValue">
|
<view class="flex-1" v-if="modelOptions.isValue">
|
||||||
<view class="w-full">
|
<view class="w-full">
|
||||||
<uv-textarea v-model="value" placeholder="请输入未通过原因"></uv-textarea>
|
<uv-textarea v-model="value" placeholder="请输入拒绝理由"></uv-textarea>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</uv-modal>
|
</uv-modal>
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,13 @@
|
||||||
<view class="card-shadow px-base">
|
<view class="card-shadow px-base">
|
||||||
<uv-form labelPosition="left" :model="form" :rules="rules" ref="formRef" errorType="toast" labelWidth="250rpx">
|
<uv-form labelPosition="left" :model="form" :rules="rules" ref="formRef" errorType="toast" labelWidth="250rpx">
|
||||||
<uv-form-item required label="目的地" prop="address">
|
<uv-form-item required label="目的地" prop="address">
|
||||||
<uv-input placeholder="请选择" inputAlign="right" :border="`none`" v-model="form.address">
|
<uv-input placeholder="请输入目的地" inputAlign="right" :border="`none`" v-model="form.address">
|
||||||
</uv-input>
|
</uv-input>
|
||||||
</uv-form-item>
|
</uv-form-item>
|
||||||
<uv-line color="#f5f5f5"></uv-line>
|
<uv-line color="#f5f5f5"></uv-line>
|
||||||
<uv-form-item required label="出差开始时间" prop="start_at">
|
<uv-form-item required label="出差开始时间" prop="start_at">
|
||||||
<uv-input
|
<uv-input
|
||||||
placeholder="请选择日期"
|
placeholder="请选择出差开始时间"
|
||||||
readonly
|
readonly
|
||||||
@click="openStartDatePicker"
|
@click="openStartDatePicker"
|
||||||
inputAlign="right"
|
inputAlign="right"
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
</uv-form-item>
|
</uv-form-item>
|
||||||
<uv-form-item required label="出差结束时间" prop="end_at">
|
<uv-form-item required label="出差结束时间" prop="end_at">
|
||||||
<uv-input
|
<uv-input
|
||||||
placeholder="请选择日期"
|
placeholder="请选择出差结束时间"
|
||||||
readonly
|
readonly
|
||||||
@click="openEndDatePicker"
|
@click="openEndDatePicker"
|
||||||
inputAlign="right"
|
inputAlign="right"
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
</uv-form-item>
|
</uv-form-item>
|
||||||
<uv-line color="#f5f5f5"></uv-line>
|
<uv-line color="#f5f5f5"></uv-line>
|
||||||
<uv-form-item required label="出差事由" prop="reason" labelPosition="top">
|
<uv-form-item required label="出差事由" prop="reason" labelPosition="top">
|
||||||
<uv-textarea v-model="form.reason" count placeholder="请输入" :border="`none`" :maxlength="200"></uv-textarea>
|
<uv-textarea :customStyle="{ padding: '0' }" v-model="form.reason" count placeholder="请输入出差事由" :border="`none`" :maxlength="200"></uv-textarea>
|
||||||
</uv-form-item>
|
</uv-form-item>
|
||||||
</uv-form>
|
</uv-form>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -94,10 +94,11 @@ const confirmEndDatePicker = e => {
|
||||||
form.end_at = timeFormat(e.value, "yyyy-mm-dd hh:MM:ss")
|
form.end_at = timeFormat(e.value, "yyyy-mm-dd hh:MM:ss")
|
||||||
}
|
}
|
||||||
const rules = reactive({
|
const rules = reactive({
|
||||||
start_at: [{ required: true, message: "请选择时间" }],
|
address: [{ required: true, message: "请输入目的地" }],
|
||||||
end_at: [{ required: true, message: "请选择时间" }],
|
start_at: [{ required: true, message: "请选择出差开始时间" }],
|
||||||
reason: [{ required: true, message: "请输入出差理由" }],
|
end_at: [{ required: true, message: "请选择出差结束时间" }],
|
||||||
address: [{ required: true, message: "请输入目的地" }]
|
reason: [{ required: true, message: "请输入出差事由" }],
|
||||||
|
|
||||||
})
|
})
|
||||||
onLoad(options => {
|
onLoad(options => {
|
||||||
http
|
http
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,14 @@
|
||||||
:label="op.text"
|
:label="op.text"
|
||||||
:name="i"
|
:name="i"
|
||||||
>
|
>
|
||||||
|
<view class="flex items-center">
|
||||||
|
<view>{{ op.text }}</view>
|
||||||
|
<uv-icon
|
||||||
|
v-if="op.selected"
|
||||||
|
:color="op.is_true ? '#ee2c37' : '#5ac725'"
|
||||||
|
:name="op.is_true ? 'checkbox-mark' : 'close'"
|
||||||
|
></uv-icon>
|
||||||
|
</view>
|
||||||
</uv-checkbox>
|
</uv-checkbox>
|
||||||
</uv-checkbox-group>
|
</uv-checkbox-group>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -63,6 +71,14 @@
|
||||||
:label="op.text"
|
:label="op.text"
|
||||||
:name="i"
|
:name="i"
|
||||||
>
|
>
|
||||||
|
<view class="flex items-center">
|
||||||
|
<view>{{ op.text }}</view>
|
||||||
|
<uv-icon
|
||||||
|
v-if="op.selected"
|
||||||
|
:color="op.is_true ? '#ee2c37' : '#5ac725'"
|
||||||
|
:name="op.is_true ? 'checkbox-mark' : 'close'"
|
||||||
|
></uv-icon>
|
||||||
|
</view>
|
||||||
</uv-radio>
|
</uv-radio>
|
||||||
</uv-radio-group>
|
</uv-radio-group>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -101,7 +117,7 @@ const loading = ref(false)
|
||||||
const list = computed(() => {
|
const list = computed(() => {
|
||||||
const content = info.value?.content ?? []
|
const content = info.value?.content ?? []
|
||||||
content.forEach((item) => {
|
content.forEach((item) => {
|
||||||
if (item.score == 1) {
|
if (item.cate == 1) {
|
||||||
item.answer = item.user_answer?.[0] ?? ''
|
item.answer = item.user_answer?.[0] ?? ''
|
||||||
} else {
|
} else {
|
||||||
item.answer = item.user_answer ?? []
|
item.answer = item.user_answer ?? []
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,14 @@
|
||||||
cancelText="取消"
|
cancelText="取消"
|
||||||
>
|
>
|
||||||
</uv-action-sheet>
|
</uv-action-sheet>
|
||||||
|
|
||||||
|
<uv-modal
|
||||||
|
ref="modalRef"
|
||||||
|
title="提示"
|
||||||
|
content="确定删除吗?"
|
||||||
|
@confirm="onDelete"
|
||||||
|
:showCancelButton="true"
|
||||||
|
></uv-modal>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
|
|
@ -31,32 +39,32 @@ import BaseData from '@/pages/audits/base-data.vue'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { onLoad } from '@dcloudio/uni-app'
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
import { http } from '@/utils/request'
|
import { http } from '@/utils/request'
|
||||||
|
const modalRef = ref(null)
|
||||||
const actionlist = ref([
|
const actionlist = ref([
|
||||||
{name: '修改', value: 'edit'},
|
{ name: '修改', value: 'edit' },
|
||||||
{name: '删除', value: 'delete'},
|
{ name: '删除', value: 'delete' },
|
||||||
])
|
])
|
||||||
|
|
||||||
const colums = [
|
const colums = [
|
||||||
{
|
{
|
||||||
title: "审核状态",
|
title: '审核状态',
|
||||||
dataIndex: "workflow_check.check_status_text",
|
dataIndex: 'workflow_check.check_status_text',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "申请人",
|
title: '申请人',
|
||||||
dataIndex: "employee.name"
|
dataIndex: 'employee.name',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "所属门店",
|
title: '所属门店',
|
||||||
dataIndex: "store.title"
|
dataIndex: 'store.title',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "电话号码",
|
title: '电话号码',
|
||||||
dataIndex: "employee.phone"
|
dataIndex: 'employee.phone',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "申请时间",
|
title: '申请时间',
|
||||||
dataIndex: "created_format"
|
dataIndex: 'created_format',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '报销分类',
|
title: '报销分类',
|
||||||
|
|
@ -96,11 +104,24 @@ const open = () => {
|
||||||
const select = (e) => {
|
const select = (e) => {
|
||||||
if (e.value == 'edit') {
|
if (e.value == 'edit') {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: `/pages/expense-account/submit?id=${id.value}`
|
url: `/pages/expense-account/submit?id=${id.value}`,
|
||||||
})
|
})
|
||||||
|
} else if (e.value == 'delete') {
|
||||||
|
modalRef.value.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onDelete = () => {
|
||||||
|
http.delete(`/reimbursements/${id.value}`).then(() => {
|
||||||
|
uni.$emit('refresh')
|
||||||
|
uni.navigateBack()
|
||||||
|
uni.showToast({
|
||||||
|
title: '删除成功',
|
||||||
|
icon: 'none',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
onLoad((option) => {
|
onLoad((option) => {
|
||||||
id.value = option.id
|
id.value = option.id
|
||||||
getDetail()
|
getDetail()
|
||||||
|
|
@ -109,7 +130,7 @@ onLoad((option) => {
|
||||||
const getDetail = () => {
|
const getDetail = () => {
|
||||||
http.get(`/reimbursements/${id.value}`).then((res) => {
|
http.get(`/reimbursements/${id.value}`).then((res) => {
|
||||||
data.value = res
|
data.value = res
|
||||||
if ([2,3].indexOf(res.workflow_check.check_status) != -1) {
|
if ([2, 3].indexOf(res.workflow_check.check_status) != -1) {
|
||||||
actionlist.value = []
|
actionlist.value = []
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<view class="flex-center h-44px text-white">
|
<view class="flex-center h-44px text-white" :style="{ color: color }">
|
||||||
<view class="flex-center flex-1" @click="openRegions">
|
<view class="flex-center flex-1" @click="openRegions">
|
||||||
<view class="max-w-190rpx line-clamp-1">{{ regionseText }}</view>
|
<view class="max-w-190rpx line-clamp-1">{{ regionseText }}</view>
|
||||||
<uv-icon
|
<uv-icon
|
||||||
color="white"
|
:color="color"
|
||||||
class="ml-10rpx"
|
class="ml-10rpx"
|
||||||
size="20rpx"
|
size="20rpx"
|
||||||
name="arrow-down-fill"
|
name="arrow-down-fill"
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
<view class="flex-center flex-1" @click="openStore">
|
<view class="flex-center flex-1" @click="openStore">
|
||||||
<view>{{ storeText }}</view>
|
<view>{{ storeText }}</view>
|
||||||
<uv-icon
|
<uv-icon
|
||||||
color="white"
|
:color="color"
|
||||||
class="ml-10rpx"
|
class="ml-10rpx"
|
||||||
size="20rpx"
|
size="20rpx"
|
||||||
name="arrow-down-fill"
|
name="arrow-down-fill"
|
||||||
|
|
@ -42,7 +42,12 @@
|
||||||
import { http } from '@/utils/request'
|
import { http } from '@/utils/request'
|
||||||
import { onMounted, ref, reactive, computed, toRaw } from 'vue'
|
import { onMounted, ref, reactive, computed, toRaw } from 'vue'
|
||||||
import debounce from '@climblee/uv-ui/libs/function/debounce'
|
import debounce from '@climblee/uv-ui/libs/function/debounce'
|
||||||
|
const props = defineProps({
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: '#fff'
|
||||||
|
}
|
||||||
|
})
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getData()
|
getData()
|
||||||
getStoreData()
|
getStoreData()
|
||||||
|
|
@ -99,13 +104,21 @@ const selectMenu = (e) => {
|
||||||
|
|
||||||
debounce(
|
debounce(
|
||||||
() => {
|
() => {
|
||||||
emit('change', toRaw(result.value))
|
emit('change', toRaw(arrayToObject(result.value)))
|
||||||
},
|
},
|
||||||
200,
|
500,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function arrayToObject(arr) {
|
||||||
|
const obj = {};
|
||||||
|
arr.forEach(item => {
|
||||||
|
obj[item.name] = item.value;
|
||||||
|
});
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
const getData = async () => {
|
const getData = async () => {
|
||||||
http.get('/region').then((res) => {
|
http.get('/region').then((res) => {
|
||||||
regions.value = res
|
regions.value = res
|
||||||
|
|
@ -147,7 +160,7 @@ const getStoreData = () => {
|
||||||
// params: params,
|
// params: params,
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
store.value = [{ title: '全部门店', id: 'all' }].concat(res)
|
store.value = [{ title: '全部门店', id: null }].concat(res)
|
||||||
storeConfirm({ value: [store.value[0]] })
|
storeConfirm({ value: [store.value[0]] })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,8 @@
|
||||||
<view>
|
<view>
|
||||||
<CuNavbar :isBack="false" title="首页">
|
<CuNavbar :isBack="false" title="首页">
|
||||||
<template #center>
|
<template #center>
|
||||||
<view class="w-full">
|
<view class="w-full" v-if="checkPermission(['admin'])">
|
||||||
<StoreDown></StoreDown>
|
<StoreDown @change="storeChange"></StoreDown>
|
||||||
<!-- <StoreDropDown></StoreDropDown> -->
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
</CuNavbar>
|
</CuNavbar>
|
||||||
|
|
@ -60,6 +59,9 @@ import { http } from '@/utils/request'
|
||||||
import { onShow } from '@dcloudio/uni-app'
|
import { onShow } from '@dcloudio/uni-app'
|
||||||
import { timeFormat } from '@climblee/uv-ui/libs/function'
|
import { timeFormat } from '@climblee/uv-ui/libs/function'
|
||||||
import StoreDown from './components/store-down.vue'
|
import StoreDown from './components/store-down.vue'
|
||||||
|
import { useUserStore } from "@/store/modules/user";
|
||||||
|
import checkPermission from '@/utils/permission'
|
||||||
|
const userStore = useUserStore()
|
||||||
const opts = {
|
const opts = {
|
||||||
color: ['#ee2c37'],
|
color: ['#ee2c37'],
|
||||||
dataLabel: false,
|
dataLabel: false,
|
||||||
|
|
@ -118,6 +120,9 @@ const yesterday = computed(() => {
|
||||||
})
|
})
|
||||||
const tabObj = computed(() => list.value[tabIndex.value])
|
const tabObj = computed(() => list.value[tabIndex.value])
|
||||||
|
|
||||||
|
const storeChange = (e)=>{
|
||||||
|
getData(e)
|
||||||
|
}
|
||||||
|
|
||||||
const onTabClick = (e) => {
|
const onTabClick = (e) => {
|
||||||
tabIndex.value = e.index
|
tabIndex.value = e.index
|
||||||
|
|
@ -150,11 +155,16 @@ onShow(() => {
|
||||||
getData()
|
getData()
|
||||||
})
|
})
|
||||||
|
|
||||||
const getData = () => {
|
const getData = (e={}) => {
|
||||||
|
|
||||||
|
if(!checkPermission(['admin'])){
|
||||||
|
e.store_id = userStore?.userInfo?.store?.id
|
||||||
|
}
|
||||||
http
|
http
|
||||||
.get('/statistics/dashboard', {
|
.get('/statistics/dashboard', {
|
||||||
params: {
|
params: {
|
||||||
date: yesterday.value,
|
date: yesterday.value,
|
||||||
|
...e
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,14 @@
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import Layout from './Layout.vue'
|
import Layout from './Layout.vue'
|
||||||
import { onLoad } from '@dcloudio/uni-app'
|
import { onLoad, onBackPress } from '@dcloudio/uni-app'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
</script>
|
|
||||||
|
onBackPress((options) => {
|
||||||
|
if (options.from == 'backbutton') {
|
||||||
|
return true
|
||||||
|
} else if (options.from == 'navigateBack') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,18 @@
|
||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<CuNavbar title="补卡申请">
|
<CuNavbar title="补卡申请"> </CuNavbar>
|
||||||
</CuNavbar>
|
|
||||||
<view class="card-shadow px-base">
|
<view class="card-shadow px-base">
|
||||||
<uv-form labelPosition="left" :model="form" :rules="rules" ref="formRef" errorType="toast" labelWidth="250rpx">
|
<uv-form
|
||||||
|
labelPosition="left"
|
||||||
|
:model="form"
|
||||||
|
:rules="rules"
|
||||||
|
ref="formRef"
|
||||||
|
errorType="toast"
|
||||||
|
labelWidth="250rpx"
|
||||||
|
>
|
||||||
<uv-form-item required label="补卡时间" prop="date">
|
<uv-form-item required label="补卡时间" prop="date">
|
||||||
<uv-input
|
<uv-input
|
||||||
placeholder="请选择日期"
|
placeholder="请选择补卡时间"
|
||||||
readonly
|
readonly
|
||||||
@click="openDatePicker"
|
@click="openDatePicker"
|
||||||
inputAlign="right"
|
inputAlign="right"
|
||||||
|
|
@ -18,7 +24,7 @@
|
||||||
<uv-line color="#f5f5f5"></uv-line>
|
<uv-line color="#f5f5f5"></uv-line>
|
||||||
<uv-form-item required label="补卡类型" prop="sign_time">
|
<uv-form-item required label="补卡类型" prop="sign_time">
|
||||||
<uv-input
|
<uv-input
|
||||||
placeholder="请选择"
|
placeholder="请选择补卡类型"
|
||||||
@click="openPicker"
|
@click="openPicker"
|
||||||
readonly
|
readonly
|
||||||
inputAlign="right"
|
inputAlign="right"
|
||||||
|
|
@ -28,8 +34,20 @@
|
||||||
</uv-input>
|
</uv-input>
|
||||||
</uv-form-item>
|
</uv-form-item>
|
||||||
<uv-line color="#f5f5f5"></uv-line>
|
<uv-line color="#f5f5f5"></uv-line>
|
||||||
<uv-form-item required label="补卡理由" prop="reason" labelPosition="top">
|
<uv-form-item
|
||||||
<uv-textarea v-model="form.reason" count placeholder="请输入" :border="`none`" :maxlength="200"></uv-textarea>
|
required
|
||||||
|
label="请输入补卡理由"
|
||||||
|
prop="reason"
|
||||||
|
labelPosition="top"
|
||||||
|
>
|
||||||
|
<uv-textarea
|
||||||
|
v-model="form.reason"
|
||||||
|
count
|
||||||
|
placeholder="请输入"
|
||||||
|
:border="`none`"
|
||||||
|
:maxlength="200"
|
||||||
|
:customStyle="{ padding: '0' }"
|
||||||
|
></uv-textarea>
|
||||||
</uv-form-item>
|
</uv-form-item>
|
||||||
<uv-line color="#f5f5f5"></uv-line>
|
<uv-line color="#f5f5f5"></uv-line>
|
||||||
<uv-form-item label="外勤" prop="isOutSide">
|
<uv-form-item label="外勤" prop="isOutSide">
|
||||||
|
|
@ -37,12 +55,19 @@
|
||||||
<uv-switch size="20" v-model="form.isOutSide"></uv-switch>
|
<uv-switch size="20" v-model="form.isOutSide"></uv-switch>
|
||||||
</view>
|
</view>
|
||||||
</uv-form-item>
|
</uv-form-item>
|
||||||
<uv-form-item v-if="form.isOutSide" required label="外勤事由" prop="outside_remarks" labelPosition="top">
|
<uv-form-item
|
||||||
|
v-if="form.isOutSide"
|
||||||
|
required
|
||||||
|
label="外勤事由"
|
||||||
|
prop="outside_remarks"
|
||||||
|
labelPosition="top"
|
||||||
|
>
|
||||||
<uv-textarea
|
<uv-textarea
|
||||||
v-model="form.outside_remarks"
|
v-model="form.outside_remarks"
|
||||||
count
|
count
|
||||||
placeholder="请输入"
|
placeholder="请输入"
|
||||||
:border="`none`"
|
:border="`none`"
|
||||||
|
:customStyle="{ padding: '0' }"
|
||||||
:maxlength="200"
|
:maxlength="200"
|
||||||
></uv-textarea>
|
></uv-textarea>
|
||||||
</uv-form-item>
|
</uv-form-item>
|
||||||
|
|
@ -51,7 +76,11 @@
|
||||||
<view class="mt-20rpx px-base">
|
<view class="mt-20rpx px-base">
|
||||||
<uv-button type="primary" @click="submit">提交</uv-button>
|
<uv-button type="primary" @click="submit">提交</uv-button>
|
||||||
</view>
|
</view>
|
||||||
<uv-picker ref="pickerRef" :columns="columns" @confirm="confirmPicker"></uv-picker>
|
<uv-picker
|
||||||
|
ref="pickerRef"
|
||||||
|
:columns="columns"
|
||||||
|
@confirm="confirmPicker"
|
||||||
|
></uv-picker>
|
||||||
<uv-datetime-picker
|
<uv-datetime-picker
|
||||||
v-model="value"
|
v-model="value"
|
||||||
placeholder="请选择日期"
|
placeholder="请选择日期"
|
||||||
|
|
@ -61,16 +90,22 @@
|
||||||
@confirm="confirmDatePicker"
|
@confirm="confirmDatePicker"
|
||||||
>
|
>
|
||||||
</uv-datetime-picker>
|
</uv-datetime-picker>
|
||||||
<uv-modal ref="modalRef" title="提示" content="确定提交吗?" @confirm="onSubmit" :showCancelButton="true"></uv-modal>
|
<uv-modal
|
||||||
|
ref="modalRef"
|
||||||
|
title="提示"
|
||||||
|
content="确定提交吗?"
|
||||||
|
@confirm="onSubmit"
|
||||||
|
:showCancelButton="true"
|
||||||
|
></uv-modal>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import CuNavbar from "@/components/cu-navbar/index"
|
import CuNavbar from '@/components/cu-navbar/index'
|
||||||
import { ref, reactive, computed } from "vue"
|
import { ref, reactive, computed } from 'vue'
|
||||||
import { onLoad } from "@dcloudio/uni-app"
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
import { http } from "@/utils/request"
|
import { http } from '@/utils/request'
|
||||||
import { timeFormat } from "@climblee/uv-ui/libs/function/index"
|
import { timeFormat } from '@climblee/uv-ui/libs/function/index'
|
||||||
const columns = [["上班补卡", "下班补卡"]]
|
const columns = [['上班补卡', '下班补卡']]
|
||||||
const formRef = ref(null)
|
const formRef = ref(null)
|
||||||
const datetimePicker = ref(null)
|
const datetimePicker = ref(null)
|
||||||
const pickerRef = ref(null)
|
const pickerRef = ref(null)
|
||||||
|
|
@ -79,11 +114,11 @@ const value = ref(Number(new Date()))
|
||||||
const id = ref(0)
|
const id = ref(0)
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
date: "",
|
date: '',
|
||||||
sign_time: "",
|
sign_time: '',
|
||||||
reason: "",
|
reason: '',
|
||||||
outside_remarks: "",
|
outside_remarks: '',
|
||||||
isOutSide: false
|
isOutSide: false,
|
||||||
})
|
})
|
||||||
const openPicker = () => {
|
const openPicker = () => {
|
||||||
pickerRef.value.open()
|
pickerRef.value.open()
|
||||||
|
|
@ -91,69 +126,75 @@ const openPicker = () => {
|
||||||
const openDatePicker = () => {
|
const openDatePicker = () => {
|
||||||
datetimePicker.value.open()
|
datetimePicker.value.open()
|
||||||
}
|
}
|
||||||
const confirmDatePicker = e => {
|
const confirmDatePicker = (e) => {
|
||||||
form.date = timeFormat(e.value, "yyyy-mm-dd hh:MM")
|
form.date = timeFormat(e.value, 'yyyy-mm-dd hh:MM')
|
||||||
}
|
}
|
||||||
const confirmPicker = e => {
|
const confirmPicker = (e) => {
|
||||||
form.sign_time = e.value[0]
|
form.sign_time = e.value[0]
|
||||||
}
|
}
|
||||||
const rules = reactive({
|
const rules = reactive({
|
||||||
date: [{ required: true, message: "请选择时间" }],
|
date: [{ required: true, message: '请选择补卡时间' }],
|
||||||
sign_time: [{ required: true, message: "请选择类型" }],
|
sign_time: [{ required: true, message: '请选择补卡类型' }],
|
||||||
reason: [{ required: true, message: "请输入补卡理由" }],
|
reason: [{ required: true, message: '请输入补卡理由' }],
|
||||||
outside_remarks: [{ required: true, message: "请输入补卡理由" }]
|
outside_remarks: [{ required: true, message: '请输入外勤事由' }],
|
||||||
})
|
})
|
||||||
onLoad(options => {
|
onLoad((options) => {
|
||||||
id.value = options.id
|
id.value = options.id
|
||||||
|
if (options.type) {
|
||||||
|
form.sign_time = options.type == 1 ? '上班补卡' : '下班补卡'
|
||||||
|
}
|
||||||
if (id.value) {
|
if (id.value) {
|
||||||
http
|
http
|
||||||
.request({
|
.request({
|
||||||
url: `/hr/sign-repairs/${options.id}`,
|
url: `/hr/sign-repairs/${options.id}`,
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
header: {
|
header: {
|
||||||
Accept: "application/json"
|
Accept: 'application/json',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
.then(res => {
|
.then((res) => {
|
||||||
value.value = res.date * 1000
|
value.value = res.date * 1000
|
||||||
form.date = timeFormat(res.date, "yyyy-mm-dd hh:MM")
|
form.date = timeFormat(res.date, 'yyyy-mm-dd hh:MM')
|
||||||
form.reason = res.reason
|
form.reason = res.reason
|
||||||
form.isOutSide = res.sign_type == 1 ? false : true
|
form.isOutSide = res.sign_type == 1 ? false : true
|
||||||
form.outside_remarks = res.outside_remarks
|
form.outside_remarks = res.outside_remarks
|
||||||
form.sign_time = res.sign_time == 1 ? "上班补卡" : "下班补卡"
|
form.sign_time = res.sign_time == 1 ? '上班补卡' : '下班补卡'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
formRef.value.validate().then(res => {
|
formRef.value
|
||||||
modalRef.value.open()
|
.validate()
|
||||||
}).catch(error => {})
|
.then((res) => {
|
||||||
|
modalRef.value.open()
|
||||||
|
})
|
||||||
|
.catch((error) => {})
|
||||||
}
|
}
|
||||||
|
|
||||||
const onSubmit = async () => {
|
const onSubmit = async () => {
|
||||||
if (loading.value) return
|
if (loading.value) return
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
let url = id.value ? `/hr/sign-repairs/${id.value}` : "/hr/sign-repairs"
|
let url = id.value ? `/hr/sign-repairs/${id.value}` : '/hr/sign-repairs'
|
||||||
let method = id.value ? "PUT" : "POST"
|
let method = id.value ? 'PUT' : 'POST'
|
||||||
await http.request({
|
await http.request({
|
||||||
url: url,
|
url: url,
|
||||||
method: method,
|
method: method,
|
||||||
header: {
|
header: {
|
||||||
Accept: "application/json"
|
Accept: 'application/json',
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
date: form.date,
|
date: form.date,
|
||||||
sign_time: form.sign_time == "上班补卡" ? 1 : 2,
|
sign_time: form.sign_time == '上班补卡' ? 1 : 2,
|
||||||
reason: form.reason,
|
reason: form.reason,
|
||||||
outside_remarks: form.outside_remarks,
|
outside_remarks: form.outside_remarks,
|
||||||
sign_type: form.isOutSide ? 2 : 1
|
sign_type: form.isOutSide ? 2 : 1,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: "提交成功",
|
title: '提交成功',
|
||||||
icon: "none"
|
icon: 'none',
|
||||||
})
|
})
|
||||||
formRef.value.resetFields()
|
formRef.value.resetFields()
|
||||||
uni.$emit('refresh')
|
uni.$emit('refresh')
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@
|
||||||
<view class="ml-20rpx">
|
<view class="ml-20rpx">
|
||||||
<view class="text-28rpx font-medium flex items-center">
|
<view class="text-28rpx font-medium flex items-center">
|
||||||
<view>{{ userInfo.name }}</view>
|
<view>{{ userInfo.name }}</view>
|
||||||
|
<view class="ml-20rpx" @click="goPath('/pages/userInfo/index')">
|
||||||
|
<uv-icon size="36rpx" name="edit-pen"></uv-icon>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="text-26rpx">{{ userInfo.phone }}</view>
|
<view class="text-26rpx">{{ userInfo.phone }}</view>
|
||||||
<view class="flex">
|
<view class="flex">
|
||||||
|
|
@ -34,8 +37,23 @@
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="absolute right-base top-base">
|
<view class="absolute right-base top-base">
|
||||||
<view class="flex items-center" @click="goPath('/pages/clockout/index')">
|
<view class="flex items-center">
|
||||||
<image class="w-40rpx h-40rpx" src="@/static/images/rl.svg"></image>
|
<view
|
||||||
|
class="flex items-center mr-10rpx"
|
||||||
|
@click="goPath('/pages/clockout/index')"
|
||||||
|
>
|
||||||
|
<image
|
||||||
|
class="w-40rpx h-40rpx"
|
||||||
|
src="@/static/images/rl.svg"
|
||||||
|
></image>
|
||||||
|
</view>
|
||||||
|
<uv-icon
|
||||||
|
@click="goPath('/pages/message/index')"
|
||||||
|
color="#8a8a8a"
|
||||||
|
size="48rpx"
|
||||||
|
name="chat"
|
||||||
|
></uv-icon
|
||||||
|
>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -103,7 +121,7 @@ const opList = [
|
||||||
icon: userIcon,
|
icon: userIcon,
|
||||||
title: '员工管理',
|
title: '员工管理',
|
||||||
url: '/pages/user/index',
|
url: '/pages/user/index',
|
||||||
rouls: ['store', 'admin', 'store_user'],
|
rouls: ['store', 'admin'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: taskIcon,
|
icon: taskIcon,
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
<uv-form labelPosition="left" :model="form" :rules="rules" ref="formRef" errorType="toast" labelWidth="250rpx">
|
<uv-form labelPosition="left" :model="form" :rules="rules" ref="formRef" errorType="toast" labelWidth="250rpx">
|
||||||
<uv-form-item required label="日期" prop="date">
|
<uv-form-item required label="日期" prop="date">
|
||||||
<uv-input
|
<uv-input
|
||||||
placeholder="请选择"
|
placeholder="请选择日期"
|
||||||
readonly
|
readonly
|
||||||
@click="openDate"
|
@click="openDate"
|
||||||
inputAlign="right"
|
inputAlign="right"
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
<uv-line color="#f5f5f5"></uv-line>
|
<uv-line color="#f5f5f5"></uv-line>
|
||||||
<uv-form-item required label="加班开始时间" prop="start_at">
|
<uv-form-item required label="加班开始时间" prop="start_at">
|
||||||
<uv-input
|
<uv-input
|
||||||
placeholder="请选择时间"
|
placeholder="请选择加班开始时间"
|
||||||
readonly
|
readonly
|
||||||
@click="openStartDatePicker"
|
@click="openStartDatePicker"
|
||||||
inputAlign="right"
|
inputAlign="right"
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
</uv-form-item>
|
</uv-form-item>
|
||||||
<uv-form-item required label="加班结束时间" prop="end_at">
|
<uv-form-item required label="加班结束时间" prop="end_at">
|
||||||
<uv-input
|
<uv-input
|
||||||
placeholder="请选择时间"
|
placeholder="请选择加班结束时间"
|
||||||
readonly
|
readonly
|
||||||
@click="openEndDatePicker"
|
@click="openEndDatePicker"
|
||||||
inputAlign="right"
|
inputAlign="right"
|
||||||
|
|
@ -42,8 +42,8 @@
|
||||||
</uv-input>
|
</uv-input>
|
||||||
</uv-form-item>
|
</uv-form-item>
|
||||||
<uv-line color="#f5f5f5"></uv-line>
|
<uv-line color="#f5f5f5"></uv-line>
|
||||||
<uv-form-item required label="加班事由" prop="reason" labelPosition="top">
|
<uv-form-item required label="请输入加班事由" prop="reason" labelPosition="top">
|
||||||
<uv-textarea v-model="form.reason" count placeholder="请输入" :border="`none`" :maxlength="200"></uv-textarea>
|
<uv-textarea :customStyle="{ padding: '0' }" v-model="form.reason" count placeholder="请输入" :border="`none`" :maxlength="200"></uv-textarea>
|
||||||
</uv-form-item>
|
</uv-form-item>
|
||||||
</uv-form>
|
</uv-form>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -117,8 +117,8 @@ const confirmEndDatePicker = e => {
|
||||||
form.end_at = timeFormat(e.value, "yyyy-mm-dd hh:MM:ss")
|
form.end_at = timeFormat(e.value, "yyyy-mm-dd hh:MM:ss")
|
||||||
}
|
}
|
||||||
const rules = reactive({
|
const rules = reactive({
|
||||||
start_at: [{ required: true, message: "请选择时间" }],
|
start_at: [{ required: true, message: "请选择加班开始时间" }],
|
||||||
end_at: [{ required: true, message: "请选择时间" }],
|
end_at: [{ required: true, message: "请选择加班结束时间" }],
|
||||||
reason: [{ required: true, message: "请输入加班事由" }],
|
reason: [{ required: true, message: "请输入加班事由" }],
|
||||||
date: [{ required: true, message: "请选择日期" }]
|
date: [{ required: true, message: "请选择日期" }]
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,34 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="px-base" v-if="detail">
|
<view class="px-base" v-if="detail">
|
||||||
<CuNavbar title="加班审核">
|
<CuNavbar title="加班申请">
|
||||||
<template v-if="actions.length > 0" #right>
|
<template v-if="actions.length > 0" #right>
|
||||||
<uv-icon color="white" @click="open" name="more-dot-fill"></uv-icon>
|
<uv-icon color="white" @click="open" name="more-dot-fill"></uv-icon>
|
||||||
</template>
|
</template>
|
||||||
</CuNavbar>
|
</CuNavbar>
|
||||||
<view class="mt-30rpx card-shadow bg-white rounded-19rpx px-base text-[#333333] text-27rpx">
|
<view
|
||||||
|
class="mt-30rpx card-shadow bg-white rounded-19rpx px-base text-[#333333] text-27rpx"
|
||||||
|
>
|
||||||
<BaseData :data="detail" :colums="columns" />
|
<BaseData :data="detail" :colums="columns" />
|
||||||
</view>
|
</view>
|
||||||
<uv-action-sheet ref="pickerRef" :actions="actions" @select="confirmPicker" />
|
<uv-action-sheet
|
||||||
<uv-modal ref="modalRef" title="提示" content="确定删除吗?" @confirm="onSubmit" :showCancelButton="true"></uv-modal>
|
ref="pickerRef"
|
||||||
|
:actions="actions"
|
||||||
|
@select="confirmPicker"
|
||||||
|
/>
|
||||||
|
<uv-modal
|
||||||
|
ref="modalRef"
|
||||||
|
title="提示"
|
||||||
|
content="确定删除吗?"
|
||||||
|
@confirm="onSubmit"
|
||||||
|
:showCancelButton="true"
|
||||||
|
></uv-modal>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import CuNavbar from "@/components/cu-navbar/index"
|
import CuNavbar from '@/components/cu-navbar/index'
|
||||||
import { http } from "@/utils/request"
|
import { http } from '@/utils/request'
|
||||||
import { onLoad } from "@dcloudio/uni-app"
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
import { ref } from "vue"
|
import { ref } from 'vue'
|
||||||
import BaseData from '../audits/base-data'
|
import BaseData from '../audits/base-data'
|
||||||
|
|
||||||
const modalRef = ref(null)
|
const modalRef = ref(null)
|
||||||
|
|
@ -30,11 +42,16 @@ const id = ref(0)
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{ title: '审核状态', dataIndex: 'workflow_check.check_status_text' },
|
{ title: '审核状态', dataIndex: 'workflow_check.check_status_text' },
|
||||||
{ title: '拒绝原因', dataIndex: 'workflow_check.check_remarks', labelPosition: 'top', isShow: (data) => data?.workflow_check?.check_status == 4 },
|
{
|
||||||
|
title: '拒绝原因',
|
||||||
|
dataIndex: 'workflow_check.check_remarks',
|
||||||
|
labelPosition: 'top',
|
||||||
|
isShow: (data) => data?.workflow_check?.check_status == 4,
|
||||||
|
},
|
||||||
{ title: '申请人', dataIndex: 'employee.name' },
|
{ title: '申请人', dataIndex: 'employee.name' },
|
||||||
|
{ title: '申请时间', dataIndex: 'created_format' },
|
||||||
{ title: '所属门店', dataIndex: 'store.title' },
|
{ title: '所属门店', dataIndex: 'store.title' },
|
||||||
{ title: '电话号码', dataIndex: 'employee.phone' },
|
{ title: '电话号码', dataIndex: 'employee.phone' },
|
||||||
{ title: '申请时间', dataIndex: 'created_format' },
|
|
||||||
{ title: '加班日期', dataIndex: 'date_format' },
|
{ title: '加班日期', dataIndex: 'date_format' },
|
||||||
{ title: '开始时间', dataIndex: 'start_format' },
|
{ title: '开始时间', dataIndex: 'start_format' },
|
||||||
{ title: '结束时间', dataIndex: 'end_format' },
|
{ title: '结束时间', dataIndex: 'end_format' },
|
||||||
|
|
@ -44,10 +61,10 @@ const columns = [
|
||||||
const open = () => {
|
const open = () => {
|
||||||
pickerRef.value.open()
|
pickerRef.value.open()
|
||||||
}
|
}
|
||||||
const confirmPicker = e => {
|
const confirmPicker = (e) => {
|
||||||
if (e.value == 'edit') {
|
if (e.value == 'edit') {
|
||||||
return uni.navigateTo({
|
return uni.navigateTo({
|
||||||
url: `/pages/overtime/create?id=${id.value}`
|
url: `/pages/overtime/create?id=${id.value}`,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (e.value == 'delete') {
|
if (e.value == 'delete') {
|
||||||
|
|
@ -58,14 +75,14 @@ const onSubmit = async () => {
|
||||||
try {
|
try {
|
||||||
await http.request({
|
await http.request({
|
||||||
url: `/hr/overtimes/${id.value}`,
|
url: `/hr/overtimes/${id.value}`,
|
||||||
method: "DELETE",
|
method: 'DELETE',
|
||||||
header: {
|
header: {
|
||||||
Accept: "application/json"
|
Accept: 'application/json',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: "删除成功",
|
title: '删除成功',
|
||||||
icon: "none"
|
icon: 'none',
|
||||||
})
|
})
|
||||||
uni.navigateBack()
|
uni.navigateBack()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -74,17 +91,17 @@ const onSubmit = async () => {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onLoad(options => {
|
onLoad((options) => {
|
||||||
id.value = options.id
|
id.value = options.id
|
||||||
http
|
http
|
||||||
.request({
|
.request({
|
||||||
url: `/hr/overtimes/${options.id}`,
|
url: `/hr/overtimes/${options.id}`,
|
||||||
method: "GET",
|
method: 'GET',
|
||||||
header: {
|
header: {
|
||||||
Accept: "application/json"
|
Accept: 'application/json',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
.then(res => {
|
.then((res) => {
|
||||||
detail.value = res
|
detail.value = res
|
||||||
if ([2, 3].indexOf(res.workflow_check.check_status) != -1) {
|
if ([2, 3].indexOf(res.workflow_check.check_status) != -1) {
|
||||||
actions.value = []
|
actions.value = []
|
||||||
|
|
|
||||||
|
|
@ -53,8 +53,8 @@
|
||||||
<ListItem
|
<ListItem
|
||||||
v-for="item in list" :key="item.id"
|
v-for="item in list" :key="item.id"
|
||||||
title="加班报备"
|
title="加班报备"
|
||||||
:status-text="item.workflow_check.check_status_text"
|
:status-text="item.check_status_text"
|
||||||
:status-color="statusFun( item.workflow_check.check_status,'statusExpense','color')"
|
:status-color="statusFun( item.check_status,'statusExpense','color')"
|
||||||
:body="[
|
:body="[
|
||||||
{ label:'申请人: ', value: item.check.subject.employee.name },
|
{ label:'申请人: ', value: item.check.subject.employee.name },
|
||||||
{ label:'加班日期: ', value: item.check.subject.date_format },
|
{ label:'加班日期: ', value: item.check.subject.date_format },
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<CuNavbar :isBack="false" title="上报"></CuNavbar>
|
<CuNavbar :isBack="false" title="数据上报"></CuNavbar>
|
||||||
|
|
||||||
<view
|
<view
|
||||||
:class="[
|
:class="[
|
||||||
|
|
@ -82,12 +82,12 @@
|
||||||
></uv-input>
|
></uv-input>
|
||||||
</uv-form-item>
|
</uv-form-item>
|
||||||
<uv-line color="#f5f5f5"></uv-line>
|
<uv-line color="#f5f5f5"></uv-line>
|
||||||
<uv-form-item label="兑奖合计" prop="expenditure">
|
<uv-form-item :label="`${store?.is_lottery_store?'兑奖':'支出'}合计`" prop="expenditure">
|
||||||
<uv-input
|
<uv-input
|
||||||
type="digit"
|
type="digit"
|
||||||
:border="`none`"
|
:border="`none`"
|
||||||
v-model="form.expenditure"
|
v-model="form.expenditure"
|
||||||
placeholder="请输入电总账兑奖金额"
|
placeholder="请输入总账兑奖金额"
|
||||||
></uv-input>
|
></uv-input>
|
||||||
</uv-form-item>
|
</uv-form-item>
|
||||||
<uv-line color="#f5f5f5"></uv-line>
|
<uv-line color="#f5f5f5"></uv-line>
|
||||||
|
|
@ -185,7 +185,7 @@ import { http } from '@/utils/request'
|
||||||
import CuNavbar from '@/components/cu-navbar/index'
|
import CuNavbar from '@/components/cu-navbar/index'
|
||||||
import TitleComp from '@/components/title-comp/index'
|
import TitleComp from '@/components/title-comp/index'
|
||||||
import { addUnit, sys } from '@climblee/uv-ui/libs/function/index'
|
import { addUnit, sys } from '@climblee/uv-ui/libs/function/index'
|
||||||
import { computed, ref, onBeforeMount, reactive, onMounted, watch } from 'vue'
|
import { computed, ref, onBeforeMount, reactive, onMounted, watch,nextTick } from 'vue'
|
||||||
import { useUserStore } from '@/store/modules/user'
|
import { useUserStore } from '@/store/modules/user'
|
||||||
import { timeFormat } from '@climblee/uv-ui/libs/function/index'
|
import { timeFormat } from '@climblee/uv-ui/libs/function/index'
|
||||||
import { add } from '@/utils/index'
|
import { add } from '@/utils/index'
|
||||||
|
|
@ -220,6 +220,18 @@ const rules = reactive({
|
||||||
message: '请输入交账金额',
|
message: '请输入交账金额',
|
||||||
trigger: ['change'],
|
trigger: ['change'],
|
||||||
},
|
},
|
||||||
|
sales: {
|
||||||
|
required: true,
|
||||||
|
message: '请输入销售额',
|
||||||
|
},
|
||||||
|
expenditure: {
|
||||||
|
required: true,
|
||||||
|
message: '请输入支出额',
|
||||||
|
},
|
||||||
|
new_customers: {
|
||||||
|
required: true,
|
||||||
|
message: '请输入新增客户数',
|
||||||
|
},
|
||||||
photos: {
|
photos: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
required: true,
|
required: true,
|
||||||
|
|
@ -373,15 +385,20 @@ const deletePic = (event) => {
|
||||||
form[event.name].splice(event.index, 1)
|
form[event.name].splice(event.index, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const salesChange = () => {
|
const salesChange = async() => {
|
||||||
|
|
||||||
|
await nextTick()
|
||||||
const val = form?.items || []
|
const val = form?.items || []
|
||||||
const sales = val.reduce((a, b) => {
|
const sales = val.reduce((a, b) => {
|
||||||
return add(a, b?.sales ?? 0)
|
return add(a, b?.sales ?? 0)
|
||||||
}, 0)
|
}, 0)
|
||||||
|
console.log(sales);
|
||||||
|
|
||||||
form.sales = sales || null
|
form.sales = sales || null
|
||||||
}
|
}
|
||||||
|
|
||||||
const expenditureChange = () => {
|
const expenditureChange = () => {
|
||||||
|
await nextTick()
|
||||||
const val = form?.items || []
|
const val = form?.items || []
|
||||||
const expenditure = val.reduce((a, b) => {
|
const expenditure = val.reduce((a, b) => {
|
||||||
return add(a, b?.expenditure ?? 0)
|
return add(a, b?.expenditure ?? 0)
|
||||||
|
|
@ -392,12 +409,12 @@ const expenditureChange = () => {
|
||||||
watch(
|
watch(
|
||||||
() => form.items,
|
() => form.items,
|
||||||
(val) => {
|
(val) => {
|
||||||
const sales = val.reduce((a, b) => {
|
// const sales = val.reduce((a, b) => {
|
||||||
return add(a, b?.sales ?? 0)
|
// return add(a, b?.sales ?? 0)
|
||||||
}, 0)
|
// }, 0)
|
||||||
const expenditure = val.reduce((a, b) => {
|
// const expenditure = val.reduce((a, b) => {
|
||||||
return add(a, b?.expenditure ?? 0)
|
// return add(a, b?.expenditure ?? 0)
|
||||||
}, 0)
|
// }, 0)
|
||||||
// form.sales = sales || null
|
// form.sales = sales || null
|
||||||
// form.expenditure = expenditure || null
|
// form.expenditure = expenditure || null
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,35 @@
|
||||||
>
|
>
|
||||||
<view>
|
<view>
|
||||||
<template v-for="(item, i) in list" :key="i">
|
<template v-for="(item, i) in list" :key="i">
|
||||||
<view v-if="i == 0" class="flex items-center w-full text-24rpx b-solid b-b-1px">
|
<view
|
||||||
|
v-if="i == 0"
|
||||||
|
class="flex items-center w-full text-24rpx b-solid b-b-1px"
|
||||||
|
>
|
||||||
<view class="w-140rpx text-center flex-none"> 日期 </view>
|
<view class="w-140rpx text-center flex-none"> 日期 </view>
|
||||||
<view class="w-300rpx text-center leading-60rpx flex-none b-r-solid b-r-1px b-l-solid b-l-1px">
|
|
||||||
|
<view
|
||||||
|
class="w-300rpx text-center leading-60rpx flex-none b-r-solid b-r-1px b-l-solid b-l-1px"
|
||||||
|
>
|
||||||
<view class="h-60rpx b-b-solid b-1px">总账</view>
|
<view class="h-60rpx b-b-solid b-1px">总账</view>
|
||||||
<view class="h-60rpx grid grid-cols-3">
|
<template v-if="checkPermission(['admin'])">
|
||||||
<view>销售</view>
|
<view class="h-60rpx grid grid-cols-3">
|
||||||
<view>支出</view>
|
<view>销售</view>
|
||||||
<view>新增客户</view>
|
<view>支出</view>
|
||||||
</view>
|
<view>新增客户</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="isLotteryStore">
|
||||||
|
<view class="h-60rpx grid grid-cols-2">
|
||||||
|
<view>销售</view>
|
||||||
|
<view>兑奖</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<view class="h-60rpx grid grid-cols-2">
|
||||||
|
<view>销售</view>
|
||||||
|
<view>支出</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
</view>
|
</view>
|
||||||
<view
|
<view
|
||||||
class="text-center leading-60rpx w-140rpx flex-none"
|
class="text-center leading-60rpx w-140rpx flex-none"
|
||||||
|
|
@ -35,10 +55,24 @@
|
||||||
<view class="flex-1 w-140rpx flex-none">{{
|
<view class="flex-1 w-140rpx flex-none">{{
|
||||||
timeFormat(item.date, 'mm-dd')
|
timeFormat(item.date, 'mm-dd')
|
||||||
}}</view>
|
}}</view>
|
||||||
|
|
||||||
<!-- 总账 -->
|
<!-- 总账 -->
|
||||||
<view class="flex-1">{{ item.ledger.sales }}</view>
|
<view class="w-300rpx flex flex-none">
|
||||||
<view class="flex-1">{{ item.ledger.expenditure }}</view>
|
<template v-if="checkPermission(['admin'])">
|
||||||
<view class="flex-1">{{ item.ledger.new_customers }}</view>
|
<view class="flex-1">{{ item.ledger.sales }}</view>
|
||||||
|
<view class="flex-1">{{ item.ledger.expenditure }}</view>
|
||||||
|
<view class="flex-1">{{ item.ledger.new_customers }}</view>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="isLotteryStore">
|
||||||
|
<view class="flex-1">{{ item.ledger.sales }}</view>
|
||||||
|
<view class="flex-1">{{ item.ledger.expenditure }}</view>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<view class="flex-1">{{ item.ledger.sales }}</view>
|
||||||
|
<view class="flex-1">{{ item.ledger.expenditure }}</view>
|
||||||
|
</template>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 种类 -->
|
<!-- 种类 -->
|
||||||
<template v-for="(ty, j) in item.lottery_types" :key="j">
|
<template v-for="(ty, j) in item.lottery_types" :key="j">
|
||||||
<view class="flex-1">{{ ty.sales }}</view>
|
<view class="flex-1">{{ ty.sales }}</view>
|
||||||
|
|
@ -51,7 +85,16 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import checkPermission from '@/utils/permission'
|
||||||
import { timeFormat } from '@climblee/uv-ui/libs/function'
|
import { timeFormat } from '@climblee/uv-ui/libs/function'
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { useUserStore } from '@/store/modules/user'
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
const isLotteryStore = computed(
|
||||||
|
() => userStore.userInfo?.store?.is_lottery_store
|
||||||
|
)
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
list: {
|
list: {
|
||||||
type: Array,
|
type: Array,
|
||||||
|
|
|
||||||
|
|
@ -5,23 +5,36 @@
|
||||||
>
|
>
|
||||||
<view class="flex-1">排名</view>
|
<view class="flex-1">排名</view>
|
||||||
<view class="flex-1">门店</view>
|
<view class="flex-1">门店</view>
|
||||||
<view class="flex-1">累计客户</view>
|
<view class="flex-1" v-if="checkPermission(['admin'])">累计客户</view>
|
||||||
<view class="flex-1">销售额</view>
|
<view class="flex-1" v-if="checkPermission(['admin'])">销售额</view>
|
||||||
</view>
|
</view>
|
||||||
<view
|
<view
|
||||||
class="flex justify-between text-center text-24rpx items-center bg-white rounded-19rpx h-80rpx"
|
class="flex justify-between text-center text-24rpx items-center bg-white rounded-19rpx h-80rpx"
|
||||||
v-for="(item, i) in list"
|
v-for="(item, i) in list"
|
||||||
:key="i"
|
:key="i"
|
||||||
>
|
>
|
||||||
<view class="flex-1">{{ item.ranking }}</view>
|
<view class="flex-1">
|
||||||
|
<view v-if="i < 3">
|
||||||
|
<image
|
||||||
|
class="w-40rpx h-40rpx"
|
||||||
|
:src="`/static/images/${i + 1}.jpg`"
|
||||||
|
></image>
|
||||||
|
</view>
|
||||||
|
<view v-else> {{ item.ranking }}</view>
|
||||||
|
</view>
|
||||||
<view class="flex-1">{{ item.store.title }}</view>
|
<view class="flex-1">{{ item.store.title }}</view>
|
||||||
<view class="flex-1">{{ item.expenditure }}</view>
|
<view class="flex-1" v-if="checkPermission(['admin'])">{{
|
||||||
<view class="flex-1">{{ item.sales }}</view>
|
item.expenditure
|
||||||
|
}}</view>
|
||||||
|
<view class="flex-1" v-if="checkPermission(['admin'])">{{
|
||||||
|
item.sales
|
||||||
|
}}</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import checkPermission from '@/utils/permission'
|
||||||
import { timeFormat } from '@climblee/uv-ui/libs/function'
|
import { timeFormat } from '@climblee/uv-ui/libs/function'
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
list: {
|
list: {
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,39 @@
|
||||||
<template>
|
<template>
|
||||||
<view>
|
<view>
|
||||||
<CuNavbar title="数据报表"></CuNavbar>
|
<CuNavbar title="数据报表"></CuNavbar>
|
||||||
|
<uv-sticky bgColor="#fff" v-if="checkPermission(['admin'])">
|
||||||
|
<StoreDown color="#333333" @change="storeChange"></StoreDown>
|
||||||
|
</uv-sticky>
|
||||||
<view class="card">
|
<view class="card">
|
||||||
<uv-tabs
|
<uv-tabs
|
||||||
:lineColor="'#ee2c37'"
|
:lineColor="'#ee2c37'"
|
||||||
:list="tabsList"
|
:list="tabsList"
|
||||||
:scrollable="false"
|
:scrollable="false"
|
||||||
:current="tabIndex"
|
:current="tabIndex"
|
||||||
|
keyName="label"
|
||||||
@change="tabChange"
|
@change="tabChange"
|
||||||
></uv-tabs>
|
></uv-tabs>
|
||||||
|
|
||||||
<view class="text-center text-28rpx" v-if="tabIndex != 0"
|
<view class="text-center text-28rpx py-4rpx" v-if="tabIndex != 0"
|
||||||
>{{ currentTabs.start }} 至 {{ currentTabs.end }}
|
>{{ currentC.start }} 至 {{ currentC.end }}
|
||||||
</view>
|
</view>
|
||||||
<view class="text-center text-28rpx" v-else>{{ currentTabs.start }}</view>
|
<view class="text-center text-28rpx" v-else>{{ currentC.start }}</view>
|
||||||
<view class="flex my-20rpx items-center">
|
<view class="flex my-20rpx items-center">
|
||||||
<view class="text-center flex-1">
|
<view class="text-center flex-1">
|
||||||
<view>销售金额</view>
|
<view v-if="!isLotteryStore">
|
||||||
|
<view>兑奖金额</view>
|
||||||
|
</view>
|
||||||
|
<view v-else>销售金额</view>
|
||||||
<view class="font-600">{{ ledger.sales }}</view>
|
<view class="font-600">{{ ledger.sales }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="h-60rpx">
|
<view class="h-60rpx">
|
||||||
<uv-line direction="col"></uv-line>
|
<uv-line direction="col"></uv-line>
|
||||||
</view>
|
</view>
|
||||||
<view class="text-center flex-1">
|
<view class="text-center flex-1">
|
||||||
<view>兑奖金额</view>
|
<view v-if="!isLotteryStore || checkPermission(['admin'])">
|
||||||
|
<view>支出金额</view>
|
||||||
|
</view>
|
||||||
|
<view v-else>兑奖金额</view>
|
||||||
<view class="font-600">{{ ledger.sales }}</view>
|
<view class="font-600">{{ ledger.sales }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="h-60rpx">
|
<view class="h-60rpx">
|
||||||
|
|
@ -32,7 +41,8 @@
|
||||||
</view>
|
</view>
|
||||||
<view class="text-center flex-1">
|
<view class="text-center flex-1">
|
||||||
<view>销售涨幅</view>
|
<view>销售涨幅</view>
|
||||||
<view class="text-primary font-600"
|
<view class="font-600"
|
||||||
|
:class="[ ledger.sales_growth_rate < 0 ? 'text-primary' : 'text-green' ]"
|
||||||
>{{ ledger.sales_growth_rate }}%</view
|
>{{ ledger.sales_growth_rate }}%</view
|
||||||
>
|
>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -54,6 +64,7 @@
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import StoreDown from '@/pages/home/components/store-down.vue'
|
||||||
import CuNavbar from '@/components/cu-navbar/index'
|
import CuNavbar from '@/components/cu-navbar/index'
|
||||||
import { computed, reactive, ref } from 'vue'
|
import { computed, reactive, ref } from 'vue'
|
||||||
import { timeFormat } from '@climblee/uv-ui/libs/function/index'
|
import { timeFormat } from '@climblee/uv-ui/libs/function/index'
|
||||||
|
|
@ -61,56 +72,40 @@ import { onShow } from '@dcloudio/uni-app'
|
||||||
import { http } from '@/utils/request'
|
import { http } from '@/utils/request'
|
||||||
import List0 from './components/list0.vue'
|
import List0 from './components/list0.vue'
|
||||||
import List1 from './components/list1.vue'
|
import List1 from './components/list1.vue'
|
||||||
|
import checkPermission from '@/utils/permission'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
|
import { useUserStore } from '@/store/modules/user'
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
const isLotteryStore = computed(
|
||||||
|
() => userStore.userInfo?.store?.is_lottery_store
|
||||||
|
)
|
||||||
const tabIndex1 = ref(0)
|
const tabIndex1 = ref(0)
|
||||||
const tabIndex = ref(0)
|
const tabIndex = ref(0)
|
||||||
const tabsList = ref(generateTimeArray())
|
const tabsList = ref(generateTimeArrayWithLastPeriod())
|
||||||
const list = ref([])
|
const list = ref([])
|
||||||
const currentTabs = computed(() => tabsList.value[tabIndex.value])
|
const currentTabs = computed(() => tabsList.value[tabIndex.value])
|
||||||
|
const currentC = computed(() => {
|
||||||
const dropDownData = reactive({
|
const ob = currentTabs.value.current
|
||||||
area: {
|
return {
|
||||||
label: '全部区域',
|
start: timeFormat(ob.startDate),
|
||||||
value: 'all',
|
end: timeFormat(ob.endDate),
|
||||||
activeIndex: 0,
|
}
|
||||||
color: '#333',
|
|
||||||
activeColor: '#2878ff',
|
|
||||||
child: [
|
|
||||||
{
|
|
||||||
label: '全部区域',
|
|
||||||
value: 'all',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '重庆',
|
|
||||||
value: 'cq',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '北京',
|
|
||||||
value: 'bj',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
store: {
|
|
||||||
label: '全部门店',
|
|
||||||
value: 'all',
|
|
||||||
activeIndex: 0,
|
|
||||||
color: '#333',
|
|
||||||
activeColor: '#2878ff',
|
|
||||||
child: [
|
|
||||||
{
|
|
||||||
label: '全部门店',
|
|
||||||
value: 'all',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '门店1',
|
|
||||||
value: 'new',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '门店2',
|
|
||||||
value: 'money',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
const currentL = computed(() => {
|
||||||
|
const ob = currentTabs.value.lastPeriod
|
||||||
|
return {
|
||||||
|
start: timeFormat(ob.startDate),
|
||||||
|
end: timeFormat(ob.endDate),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const shoreInfo = ref({})
|
||||||
|
|
||||||
|
if (!checkPermission(['admin'])) {
|
||||||
|
shoreInfo.value = { store_id: userStore?.userInfo?.store?.id }
|
||||||
|
}
|
||||||
|
|
||||||
const result = ref([])
|
const result = ref([])
|
||||||
const ledger = ref({
|
const ledger = ref({
|
||||||
|
|
@ -126,77 +121,130 @@ onShow(() => {
|
||||||
getList()
|
getList()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const storeChange = (e) => {
|
||||||
|
shoreInfo.value = e
|
||||||
|
getCount()
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
const getCount = async () => {
|
const getCount = async () => {
|
||||||
const resData = await http.get('/statistics/ledger', {
|
const resData = await http.get('/statistics/ledger', {
|
||||||
params: {
|
params: {
|
||||||
start_at: currentTabs.value.start,
|
start_at: currentC.value.start,
|
||||||
end_at: currentTabs.value.end,
|
end_at: currentC.value.end,
|
||||||
before_start_at: currentTabs.value.start,
|
before_start_at: currentL.value.start,
|
||||||
before_end_at: currentTabs.value.end,
|
before_end_at: currentL.value.end,
|
||||||
|
...shoreInfo.value,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
ledger.value = resData
|
ledger.value = resData
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectMenu = (e) => {
|
function generateTimeArrayWithLastPeriod() {
|
||||||
const { name, active, type } = e
|
const today = dayjs()
|
||||||
activeName.value = name
|
const yesterday = today.subtract(1, 'day')
|
||||||
const find = result.value.find((item) => item.name == activeName.value)
|
|
||||||
if (find) {
|
let currentWeekStart = today.startOf('week').add(1, 'day') // 本周一
|
||||||
const findIndex = dropDownData[activeName.value].child.findIndex(
|
if (today.isBefore(currentWeekStart, 'day')) {
|
||||||
(item) => item.label == find.label && item.value == find.value
|
currentWeekStart = currentWeekStart.subtract(1, 'week')
|
||||||
)
|
|
||||||
dropDownData[activeName.value].activeIndex = findIndex
|
|
||||||
} else {
|
|
||||||
dropDownData[activeName.value].activeIndex = 0
|
|
||||||
}
|
}
|
||||||
}
|
const currentWeekEnd = today
|
||||||
|
|
||||||
function generateTimeRange(name, start, end) {
|
let lastWeekStart = currentWeekStart.subtract(1, 'week')
|
||||||
start = timeFormat(start, 'yyyy-mm-dd')
|
const lastWeekEnd = currentWeekStart.subtract(1, 'day')
|
||||||
end = timeFormat(end, 'yyyy-mm-dd')
|
|
||||||
return { name, start, end }
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStartOfWeek(date) {
|
let currentMonthStart = today.startOf('month')
|
||||||
const dayOfWeek = date.getDay()
|
if (today.isBefore(currentMonthStart, 'day')) {
|
||||||
const diff = date.getDate() - dayOfWeek + (dayOfWeek === 0 ? -6 : 1) // 如果今天是周日,从上周一开始
|
currentMonthStart = currentMonthStart.subtract(1, 'month')
|
||||||
return new Date(date.setDate(diff))
|
}
|
||||||
}
|
const currentMonthEnd = today.endOf('day') // 本月最后一天到当天结束
|
||||||
|
|
||||||
function getStartOfMonth(date) {
|
let lastMonthStart = currentMonthStart.subtract(1, 'month')
|
||||||
return new Date(date.getFullYear(), date.getMonth(), 1)
|
const lastMonthEnd = currentMonthStart.subtract(1, 'day')
|
||||||
}
|
|
||||||
|
|
||||||
function generateTimeArray() {
|
const timeArray = [
|
||||||
const today = new Date()
|
generateTimeRange('昨日', yesterday),
|
||||||
const yesterday = new Date(today)
|
|
||||||
yesterday.setDate(today.getDate() - 1)
|
|
||||||
|
|
||||||
const currentWeekStart = getStartOfWeek(today) // 获取本周第一天
|
|
||||||
const currentWeekEnd = new Date(today)
|
|
||||||
currentWeekEnd.setDate(currentWeekStart.getDate() + 6)
|
|
||||||
|
|
||||||
const lastWeekStart = new Date(currentWeekStart)
|
|
||||||
lastWeekStart.setDate(currentWeekStart.getDate() - 7)
|
|
||||||
const lastWeekEnd = new Date(currentWeekEnd)
|
|
||||||
lastWeekEnd.setDate(currentWeekEnd.getDate() - 7)
|
|
||||||
|
|
||||||
const currentMonthStart = getStartOfMonth(today) // 获取本月第一天
|
|
||||||
const currentMonthEnd = new Date(today.getFullYear(), today.getMonth() + 1, 0)
|
|
||||||
|
|
||||||
const lastMonthStart = new Date(currentMonthStart)
|
|
||||||
lastMonthStart.setMonth(lastMonthStart.getMonth() - 1)
|
|
||||||
const lastMonthEnd = new Date(currentMonthEnd)
|
|
||||||
lastMonthEnd.setMonth(lastMonthEnd.getMonth() - 1)
|
|
||||||
|
|
||||||
return [
|
|
||||||
generateTimeRange('昨日', yesterday, yesterday),
|
|
||||||
generateTimeRange('本周', currentWeekStart, currentWeekEnd),
|
generateTimeRange('本周', currentWeekStart, currentWeekEnd),
|
||||||
generateTimeRange('上周', lastWeekStart, lastWeekEnd),
|
generateTimeRange('上周', lastWeekStart, lastWeekEnd),
|
||||||
generateTimeRange('本月', currentMonthStart, currentMonthEnd),
|
generateTimeRange('本月', currentMonthStart, currentMonthEnd),
|
||||||
generateTimeRange('上月', lastMonthStart, lastMonthEnd),
|
generateTimeRange('上月', lastMonthStart, lastMonthEnd),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const lastPeriodTimeRanges = {}
|
||||||
|
|
||||||
|
// 计算同期的上次开始和结束时间
|
||||||
|
timeArray.forEach((timeRange) => {
|
||||||
|
switch (timeRange.label) {
|
||||||
|
case '昨日':
|
||||||
|
lastPeriodTimeRanges['昨日'] = {
|
||||||
|
startDate: dayjs(timeRange.current.startDate)
|
||||||
|
.subtract(1, 'day')
|
||||||
|
.toDate(),
|
||||||
|
endDate: dayjs(timeRange.current.endDate).subtract(1, 'day').toDate(),
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case '本周':
|
||||||
|
lastPeriodTimeRanges['本周'] = {
|
||||||
|
startDate: dayjs(timeRange.current.startDate)
|
||||||
|
.subtract(1, 'week')
|
||||||
|
.toDate(),
|
||||||
|
endDate: dayjs(timeRange.current.endDate)
|
||||||
|
.subtract(1, 'week')
|
||||||
|
.toDate(),
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case '上周':
|
||||||
|
lastPeriodTimeRanges['上周'] = {
|
||||||
|
startDate: dayjs(timeRange.current.startDate)
|
||||||
|
.subtract(2, 'week')
|
||||||
|
.toDate(),
|
||||||
|
endDate: dayjs(timeRange.current.endDate)
|
||||||
|
.subtract(2, 'week')
|
||||||
|
.toDate(),
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case '本月':
|
||||||
|
lastPeriodTimeRanges['本月'] = {
|
||||||
|
startDate: dayjs(timeRange.current.startDate)
|
||||||
|
.subtract(1, 'month')
|
||||||
|
.toDate(),
|
||||||
|
endDate: dayjs(timeRange.current.endDate)
|
||||||
|
.subtract(1, 'month')
|
||||||
|
.toDate(),
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case '上月':
|
||||||
|
lastPeriodTimeRanges['上月'] = {
|
||||||
|
startDate: dayjs(timeRange.current.startDate)
|
||||||
|
.subtract(2, 'month')
|
||||||
|
.toDate(),
|
||||||
|
endDate: dayjs(timeRange.current.endDate)
|
||||||
|
.subtract(2, 'month')
|
||||||
|
.toDate(),
|
||||||
|
}
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 更新 timeArray 中的 lastPeriod 字段
|
||||||
|
timeArray.forEach((timeRange) => {
|
||||||
|
timeRange.lastPeriod = lastPeriodTimeRanges[timeRange.label]
|
||||||
|
})
|
||||||
|
|
||||||
|
return timeArray
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateTimeRange(label, startDate, endDate) {
|
||||||
|
return {
|
||||||
|
label,
|
||||||
|
current: {
|
||||||
|
startDate: startDate.toDate(),
|
||||||
|
endDate: (endDate || startDate).toDate(),
|
||||||
|
},
|
||||||
|
lastPeriod: { startDate: null, endDate: null },
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const tabChange = (e) => {
|
const tabChange = (e) => {
|
||||||
|
|
@ -216,8 +264,9 @@ const getList = async () => {
|
||||||
const url = tabIndex1.value == 0 ? '/statistics/sales' : '/statistics/stores'
|
const url = tabIndex1.value == 0 ? '/statistics/sales' : '/statistics/stores'
|
||||||
const resData = await http.get(url, {
|
const resData = await http.get(url, {
|
||||||
params: {
|
params: {
|
||||||
start_at: currentTabs.value.start,
|
start_at: currentC.value.start,
|
||||||
end_at: currentTabs.value.end,
|
end_at: currentC.value.end,
|
||||||
|
...shoreInfo.value,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
list.value = resData
|
list.value = resData
|
||||||
|
|
|
||||||
|
|
@ -84,17 +84,39 @@ const downloadFile = (url) => {
|
||||||
(d, status) => {
|
(d, status) => {
|
||||||
if (status == 200) {
|
if (status == 200) {
|
||||||
let fileSaveUrl = plus.io.convertLocalFileSystemURL(d.filename)
|
let fileSaveUrl = plus.io.convertLocalFileSystemURL(d.filename)
|
||||||
this.$u.toast('文件下载成功')
|
// saveFile(fileSaveUrl)
|
||||||
|
uni.showToast({
|
||||||
|
title: '下载成功',
|
||||||
|
icon: 'none',
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
//下载失败
|
//下载失败
|
||||||
this.$u.toast('下载失败')
|
uni.showToast({
|
||||||
|
title: '下载失败',
|
||||||
|
})
|
||||||
plus.downloader.clear() //清除下载任务
|
plus.downloader.clear() //清除下载任务
|
||||||
}
|
}
|
||||||
|
console.log(d)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
dtask.start()
|
dtask.start()
|
||||||
// #endif
|
// #endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const saveFile = (filePath) => {
|
||||||
|
uni.saveFile({
|
||||||
|
tempFilePath: filePath,
|
||||||
|
success: (res) => {
|
||||||
|
uni.showToast({
|
||||||
|
title: '文件保存成功',
|
||||||
|
})
|
||||||
|
console.log('文件保存成功,路径为:' + res.savedFilePath)
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.log('文件保存失败:' + err)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
page {
|
page {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,9 @@
|
||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
</CuNavbar>
|
</CuNavbar>
|
||||||
<StoreDropDown></StoreDropDown>
|
<uv-sticky bgColor="#fff" v-if="checkPermission(['admin'])">
|
||||||
|
<StoreDown color="#333333" @change="storeChange"></StoreDown>
|
||||||
|
</uv-sticky>
|
||||||
<MescrollApiOne
|
<MescrollApiOne
|
||||||
:top="88"
|
:top="88"
|
||||||
ref="mescrollItem"
|
ref="mescrollItem"
|
||||||
|
|
@ -25,20 +27,30 @@
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import StoreDown from '@/pages/home/components/store-down.vue'
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import checkPermission from '@/utils/permission'
|
||||||
import CuNavbar from '@/components/cu-navbar/index'
|
import CuNavbar from '@/components/cu-navbar/index'
|
||||||
import StoreDropDown from '@/pages/home/components/store-drop-down/index.vue'
|
|
||||||
import Item from './components/item.vue'
|
import Item from './components/item.vue'
|
||||||
import MescrollApiOne from '@/components/mescroll-api/one'
|
import MescrollApiOne from '@/components/mescroll-api/one'
|
||||||
import { onPageScroll, onReachBottom, onLoad } from '@dcloudio/uni-app'
|
import { onPageScroll, onReachBottom, onLoad } from '@dcloudio/uni-app'
|
||||||
import useMescrollComp from '@/uni_modules/mescroll-uni/hooks/useMescrollComp.js'
|
import useMescrollComp from '@/uni_modules/mescroll-uni/hooks/useMescrollComp.js'
|
||||||
const { mescrollItem } = useMescrollComp(onPageScroll, onReachBottom)
|
const { mescrollItem } = useMescrollComp(onPageScroll, onReachBottom)
|
||||||
const params = ref(null)
|
|
||||||
|
|
||||||
onLoad(()=>{
|
const storeInfo = ref({})
|
||||||
uni.$on('user:onRefresh',onRefresh)
|
const params = computed(()=>{
|
||||||
|
return storeInfo.value
|
||||||
})
|
})
|
||||||
|
|
||||||
|
onLoad(()=>{
|
||||||
|
uni.$on('user:onRefresh',()=>{
|
||||||
|
onRefresh()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
const storeChange = (data) => {
|
||||||
|
storeInfo.value = data
|
||||||
|
onRefresh()
|
||||||
|
}
|
||||||
const onRefresh = () => {
|
const onRefresh = () => {
|
||||||
mescrollItem.value.getMescroll().resetUpScroll()
|
mescrollItem.value.getMescroll().resetUpScroll()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
<template>
|
||||||
|
<view class="px-base">
|
||||||
|
<CuNavbar title="修改个人资料">
|
||||||
|
<template #right>
|
||||||
|
<view class="text-24rpx text-white" @click="submit">保存</view>
|
||||||
|
</template>
|
||||||
|
</CuNavbar>
|
||||||
|
<view class="card-shadow bg-white rounded-19rpx p-base">
|
||||||
|
<uv-form-item label="头像" prop="avatar">
|
||||||
|
<view class="flex justify-end w-full" @click="chooseAvatar">
|
||||||
|
<view class="w-90rpx h-90rpx overflow-hidden">
|
||||||
|
<image class="w-full h-full" :src="form.avatar"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uv-form-item>
|
||||||
|
<uv-line color="#f5f5f5"></uv-line>
|
||||||
|
<uv-form
|
||||||
|
labelWidth="150rpx"
|
||||||
|
:model="form"
|
||||||
|
ref="formRef"
|
||||||
|
errorType="toast"
|
||||||
|
:rules="rules"
|
||||||
|
>
|
||||||
|
<uv-form-item label="姓名" prop="name">
|
||||||
|
<uv-input
|
||||||
|
v-model="form.name"
|
||||||
|
inputAlign="right"
|
||||||
|
:border="`none`"
|
||||||
|
placeholder="请输入姓名"
|
||||||
|
type="text"
|
||||||
|
></uv-input>
|
||||||
|
</uv-form-item>
|
||||||
|
<uv-line color="#f5f5f5"></uv-line>
|
||||||
|
<uv-form-item label="手机号" prop="phone">
|
||||||
|
<uv-input
|
||||||
|
v-model="form.phone"
|
||||||
|
inputAlign="right"
|
||||||
|
placeholder="请输入手机号"
|
||||||
|
:border="`none`"
|
||||||
|
type="number"
|
||||||
|
maxlength="11"
|
||||||
|
></uv-input>
|
||||||
|
</uv-form-item>
|
||||||
|
</uv-form>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<uv-modal
|
||||||
|
ref="modalRef"
|
||||||
|
title="提示"
|
||||||
|
content="确定修改?"
|
||||||
|
@confirm="onUpdateUserInfo"
|
||||||
|
:showCancelButton="true"
|
||||||
|
></uv-modal>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import CuNavbar from '@/components/cu-navbar/index.vue'
|
||||||
|
import { ref, reactive, computed, watch } from 'vue'
|
||||||
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
|
import { http } from '@/utils/request'
|
||||||
|
import { useUserStore } from '@/store/modules/user'
|
||||||
|
const userStore = useUserStore()
|
||||||
|
const modalRef = ref(null)
|
||||||
|
const userInfo = computed(() => {
|
||||||
|
return userStore.userInfo
|
||||||
|
})
|
||||||
|
|
||||||
|
const formRef = ref(null)
|
||||||
|
const form = reactive({
|
||||||
|
name: '',
|
||||||
|
phone: '',
|
||||||
|
avatar: '',
|
||||||
|
})
|
||||||
|
const rules = reactive({
|
||||||
|
name: [{ required: true, message: '请输入姓名' }],
|
||||||
|
phone: [{ required: true, message: '请输入手机号' }],
|
||||||
|
avatar: [{ required: true, message: '请上传头像' }],
|
||||||
|
})
|
||||||
|
|
||||||
|
const submit = () => {
|
||||||
|
formRef.value.validate().then(() => {
|
||||||
|
modalRef.value.open()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const onUpdateUserInfo = () => {
|
||||||
|
http.post('/auth/profile', form).then(() => {
|
||||||
|
uni.showToast({
|
||||||
|
title: '修改成功',
|
||||||
|
icon: 'success',
|
||||||
|
})
|
||||||
|
userStore.fetchUserInfo()
|
||||||
|
uni.navigateBack()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const uploadFilePromise = (url) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
http
|
||||||
|
.upload('/fileupload', {
|
||||||
|
filePath: url,
|
||||||
|
name: 'file',
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
resolve(res.url)
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
reject(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const chooseAvatar = () => {
|
||||||
|
uni.chooseImage({
|
||||||
|
count: 1,
|
||||||
|
success: async (res) => {
|
||||||
|
const data = await uploadFilePromise(res.tempFilePaths[0])
|
||||||
|
form.avatar = data
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
userInfo,
|
||||||
|
(val) => {
|
||||||
|
form.name = val.name
|
||||||
|
form.phone = val.phone
|
||||||
|
form.avatar = val.avatar
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
deep: true,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
@ -126,21 +126,21 @@
|
||||||
<template v-if="type == 1">
|
<template v-if="type == 1">
|
||||||
<BaseData :data="detail.employee_data" :colums="userColumns" />
|
<BaseData :data="detail.employee_data" :colums="userColumns" />
|
||||||
<uv-line color="#f5f5f5"></uv-line>
|
<uv-line color="#f5f5f5"></uv-line>
|
||||||
<uv-form-item
|
<uv-form-item
|
||||||
label="推荐理由"
|
label="推荐理由"
|
||||||
prop="reason"
|
prop="reason"
|
||||||
required
|
required
|
||||||
labelPosition="top"
|
labelPosition="top"
|
||||||
>
|
>
|
||||||
<uv-textarea
|
<uv-textarea
|
||||||
:customStyle="{ padding: '0' }"
|
:customStyle="{ padding: '0' }"
|
||||||
v-model="form.reason"
|
v-model="form.reason"
|
||||||
count
|
count
|
||||||
placeholder="请输入推荐理由"
|
placeholder="请输入推荐理由"
|
||||||
:border="`none`"
|
:border="`none`"
|
||||||
:maxlength="200"
|
:maxlength="200"
|
||||||
></uv-textarea>
|
></uv-textarea>
|
||||||
</uv-form-item>
|
</uv-form-item>
|
||||||
</template>
|
</template>
|
||||||
</uv-form>
|
</uv-form>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -160,8 +160,9 @@
|
||||||
<uv-datetime-picker
|
<uv-datetime-picker
|
||||||
placeholder="请选择日期"
|
placeholder="请选择日期"
|
||||||
ref="datetimePicker"
|
ref="datetimePicker"
|
||||||
|
:maxDate="Number(new Date())"
|
||||||
|
v-model="datetimeV"
|
||||||
mode="year-month"
|
mode="year-month"
|
||||||
:minDate="(new Date(0)).getTime()"
|
|
||||||
@confirm="confirmDatePicker"
|
@confirm="confirmDatePicker"
|
||||||
>
|
>
|
||||||
</uv-datetime-picker>
|
</uv-datetime-picker>
|
||||||
|
|
@ -181,7 +182,7 @@ import { onLoad } from '@dcloudio/uni-app'
|
||||||
import { http } from '@/utils/request'
|
import { http } from '@/utils/request'
|
||||||
import { ref, reactive, computed, onBeforeMount } from 'vue'
|
import { ref, reactive, computed, onBeforeMount } from 'vue'
|
||||||
import { timeFormat } from '@climblee/uv-ui/libs/function/index'
|
import { timeFormat } from '@climblee/uv-ui/libs/function/index'
|
||||||
|
const datetimeV = ref(Number(new Date()))
|
||||||
const detail = ref({})
|
const detail = ref({})
|
||||||
const actionSheet = ref(null)
|
const actionSheet = ref(null)
|
||||||
const columns = [['男', '女']]
|
const columns = [['男', '女']]
|
||||||
|
|
@ -227,7 +228,7 @@ const openDatePicker = () => {
|
||||||
datetimePicker.value.open()
|
datetimePicker.value.open()
|
||||||
}
|
}
|
||||||
const confirmDatePicker = (e) => {
|
const confirmDatePicker = (e) => {
|
||||||
let date = new Date(e.value);
|
let date = new Date(e.value)
|
||||||
let month = date.getMonth() + 1
|
let month = date.getMonth() + 1
|
||||||
if (month < 10) {
|
if (month < 10) {
|
||||||
month = '0' + month
|
month = '0' + month
|
||||||
|
|
@ -251,17 +252,20 @@ const rules = reactive({
|
||||||
|
|
||||||
onLoad((options) => {
|
onLoad((options) => {
|
||||||
type.value = options.type
|
type.value = options.type
|
||||||
http.get(`/hr/promotion/${options.id}`).then(res => {
|
http.get(`/hr/promotion/${options.id}`).then((res) => {
|
||||||
detail.value = res
|
detail.value = res
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
formRef.value.validate().then((res) => {
|
formRef.value
|
||||||
modalRef.value.open()
|
.validate()
|
||||||
}).catch(error => {
|
.then((res) => {
|
||||||
console.log(error)
|
modalRef.value.open()
|
||||||
})
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const onSubmit = async () => {
|
const onSubmit = async () => {
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
|
|
@ -3044,6 +3044,11 @@ csstype@^2.6.8:
|
||||||
resolved "https://registry.npmmirror.com/csstype/-/csstype-2.6.21.tgz"
|
resolved "https://registry.npmmirror.com/csstype/-/csstype-2.6.21.tgz"
|
||||||
integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==
|
integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==
|
||||||
|
|
||||||
|
dayjs@^1.11.11:
|
||||||
|
version "1.11.11"
|
||||||
|
resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.11.tgz#dfe0e9d54c5f8b68ccf8ca5f72ac603e7e5ed59e"
|
||||||
|
integrity sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==
|
||||||
|
|
||||||
debug@2.6.9:
|
debug@2.6.9:
|
||||||
version "2.6.9"
|
version "2.6.9"
|
||||||
resolved "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz"
|
resolved "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue