【需求】uni app目录

dev
zengchenxi 6 months ago
parent 60eeb85fe7
commit 4080be50d8

@ -1,16 +0,0 @@
{
"version" : "1.0",
"configurations" : [
{
"playground" : "standard",
"type" : "uni-app:app-android"
},
{
"app-plus" :
{
"launchtype" : "local"
},
"type" : "uniCloud"
}
]
}

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

@ -1,39 +0,0 @@
### 技术栈
- 前端框架:[uni-app](https://uniapp.dcloud.net.cn/) (Vue3 + TS)
- 状态管理:[pinia](https://pinia.vuejs.org/zh/)
- 组件库:[uni-ui](https://uniapp.dcloud.net.cn/component/uniui/uni-ui.html)
### 开发环境
- 开发工具: VS Code 、 HbuilderX 、 微信开发者工具
- Node 版本: v16.15.0
- pnpm 版本v8.6.10
### 运行程序
1. 安装依赖
```shell
# npm
npm i --registry=https://registry.npmmirror.com
# pnpm
pnpm i --registry=https://registry.npmmirror.com
```
2. 运行程序
```shell
# 微信小程序端
npm run dev:mp-weixin
# H5端
npm run dev:h5
# App端
需 HbuilderX 工具,运行 - 运行到手机或模拟器
```
3. 微信开发者工具导入 `/dist/dev/mp-weixin` 目录

@ -1,32 +0,0 @@
#!/usr/bin/env sh
# 确保脚本抛出遇到的错误
set -e
# 1. 先提交 master
git push git@github.com:xxx.git master:master
# 2. 打包生成静态文件
# npm run build:h5
# 注意:项目使用了 uniClound需在 HbuilderX 打包 H5 网站,否则无法使用云功能
cli publish --platform h5 --project erabbit-uni-app --spaceId mp-2fac390c-2ea7-4d12-9726-f5b9a3bb6c37
# 3. 生成流水线.yml
mkdir -p "./dist/build/h5/.github/workflows"
cp "./deploy.yml" "./dist/build/h5/.github/workflows/deploy.yml"
# 4. 进入生成的文件夹,提交到主仓库 gh-pages 分支
# 如果是发布到自定义域名
# echo 'www.example.com' > CNAME
cd dist/build/h5
git init -b master
git add -A
git commit -m 'deploy: gh-pages'
# 如果发布到 https://<USERNAME>.github.io/<REPO>
# git push -f git@gitee.com:<USERNAME>/<REPO>.git master:gh-pages
git push -f git@github.com:xxx.git master:gh-pages
cd -

@ -1,36 +0,0 @@
name: deploy
on:
push:
branches: [gh-pages]
pull_request:
branches: [gh-pages]
jobs:
gitee:
runs-on: ubuntu-latest
steps:
- name: Sync To Gitee
uses: wearerequired/git-mirror-action@master
env:
# 注意在 Settings->Secrets 配置 GITEE_RSA_PRIVATE_KEY
SSH_PRIVATE_KEY: ${{ secrets.GITEE_RSA_PRIVATE_KEY }}
with:
# 注意替换为你的 GitHub 源仓库地址
source-repo: git@github.com:xxx.git
# 注意替换为你的 Gitee 目标仓库地址
destination-repo: git@gitee.com:xxx.git
# dry-run: true
- name: Build Gitee Pages
uses: yanglbme/gitee-pages-action@main
with:
# 注意替换为你的 Gitee 用户名
gitee-username: xxx
# 注意在 Settings->Secrets 配置 GITEE_PASSWORD
gitee-password: ${{ secrets.GITEE_PASSWORD }}
# 注意替换为你的 Gitee 仓库,仓库名严格区分大小写,请准确填写,否则会出错
gitee-repo: Megasu/uniapp-shop-vue3-ts
# 要部署的分支,默认是 master若是其他分支则需要指定指定的分支必须存在
branch: gh-pages
# directory: docs/.vitepress/dist

@ -1,42 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<script>
var coverSupport =
'CSS' in window &&
typeof CSS.supports === 'function' &&
(CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') +
'" />',
)
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app">
<!--app-html-->
</div>
<script type="module" src="/src/main.ts"></script>
//
<script>
// var _hmt = _hmt || []
// ;(function () {
// var hm = document.createElement('script')
// hm.src = 'https://hm.baidu.com/hm.js?47837f06b6f8cf8ba80165ca9a80711'
// var s = document.getElementsByTagName('script')[0]
// s.parentNode.insertBefore(hm, s)
// })()
//
</script>
</body>
</html>

@ -1,94 +0,0 @@
{
"name": "uni-app-personal",
"version": "0.0.0",
"scripts": {
"dev:app": "uni -p app",
"dev:app-android": "uni -p app-android",
"dev:app-ios": "uni -p app-ios",
"dev:custom": "uni -p",
"dev:h5": "uni",
"dev:h5:ssr": "uni --ssr",
"dev:mp-alipay": "uni -p mp-alipay",
"dev:mp-baidu": "uni -p mp-baidu",
"dev:mp-kuaishou": "uni -p mp-kuaishou",
"dev:mp-lark": "uni -p mp-lark",
"dev:mp-qq": "uni -p mp-qq",
"dev:mp-toutiao": "uni -p mp-toutiao",
"dev:mp-weixin": "uni -p mp-weixin",
"dev:quickapp-webview": "uni -p quickapp-webview",
"dev:quickapp-webview-huawei": "uni -p quickapp-webview-huawei",
"dev:quickapp-webview-union": "uni -p quickapp-webview-union",
"build:app": "uni build -p app",
"build:app-android": "uni build -p app-android",
"build:app-ios": "uni build -p app-ios",
"build:custom": "uni build -p",
"build:h5": "uni build",
"build:h5:ssr": "uni build --ssr",
"build:mp-alipay": "uni build -p mp-alipay",
"build:mp-baidu": "uni build -p mp-baidu",
"build:mp-kuaishou": "uni build -p mp-kuaishou",
"build:mp-lark": "uni build -p mp-lark",
"build:mp-qq": "uni build -p mp-qq",
"build:mp-toutiao": "uni build -p mp-toutiao",
"build:mp-weixin": "uni build -p mp-weixin",
"build:quickapp-webview": "uni build -p quickapp-webview",
"build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei",
"build:quickapp-webview-union": "uni build -p quickapp-webview-union",
"tsc": "vue-tsc --noEmit --skipLibCheck",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
"prepare": "husky install",
"lint-staged": "lint-staged"
},
"lint-staged": {
"*.{js,ts,vue}": [
"eslint --fix"
]
},
"dependencies": {
"@dcloudio/uni-app": "3.0.0-3090920231225001",
"@dcloudio/uni-app-plus": "3.0.0-3090920231225001",
"@dcloudio/uni-components": "3.0.0-3090920231225001",
"@dcloudio/uni-h5": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-alipay": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-baidu": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-jd": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-kuaishou": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-lark": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-qq": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-toutiao": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-weixin": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-xhs": "3.0.0-3090920231225001",
"@dcloudio/uni-quickapp-webview": "3.0.0-3090920231225001",
"@dcloudio/uni-ui": "^1.4.28",
"pinia": "2.0.27",
"pinia-plugin-persistedstate": "^3.2.0",
"vue": "3.4.21",
"vue-i18n": "9.10.1"
},
"devDependencies": {
"@dcloudio/types": "3.4.8",
"@dcloudio/uni-automator": "3.0.0-3090920231225001",
"@dcloudio/uni-cli-shared": "3.0.0-3090920231225001",
"@dcloudio/uni-stacktracey": "3.0.0-3090920231225001",
"@dcloudio/uni-vue-devtools": "3.0.0-alpha-3080220230511001",
"@dcloudio/vite-plugin-uni": "3.0.0-3090920231225001",
"@rushstack/eslint-patch": "^1.1.4",
"@types/node": "^18.11.9",
"@uni-helper/uni-app-types": "^0.5.12",
"@uni-helper/uni-ui-types": "^0.5.11",
"@vue/eslint-config-prettier": "^7.0.0",
"@vue/eslint-config-typescript": "^11.0.0",
"@vue/runtime-core": "3.4.21",
"@vue/tsconfig": "^0.4.0",
"eslint": "^8.22.0",
"eslint-plugin-vue": "^9.3.0",
"husky": "^8.0.0",
"lint-staged": "^13.0.3",
"miniprogram-api-typings": "^3.12.0",
"prettier": "^2.7.1",
"sass": "^1.56.1",
"typescript": "^5.1.6",
"vite": "4.0.3",
"vue-tsc": "^1.8.8"
}
}

@ -1,28 +0,0 @@
{
"appid": "wxa29fe397274614b5",
"compileType": "miniprogram",
"libVersion": "3.3.0",
"packOptions": {
"ignore": [],
"include": []
},
"setting": {
"coverView": true,
"es6": true,
"postcss": true,
"minified": true,
"enhance": true,
"showShadowRootInWxmlPanel": true,
"packNpmRelationList": [],
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
}
},
"condition": {},
"editorSetting": {
"tabIndent": "insertSpaces",
"tabSize": 4
}
}

@ -1,7 +0,0 @@
{
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
"projectname": "app-nx-personal",
"setting": {
"compileHotReLoad": true
}
}

@ -1,28 +0,0 @@
<!--
* @Author: 王文杰
* @Date: 2024-01-04 12:54:56
* @LastEditors: 王文杰
* @LastEditTime: 2024-03-26 14:34:58
* @FilePath: /app-nx-personal/src/App.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<script setup lang="ts">
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app'
import { updateManager } from '@/utils/index'
onLaunch(() => {
console.log('App Launch')
updateManager()
})
onShow(() => {
console.log('App Show')
})
onHide(() => {
console.log('App Hide')
})
</script>
<style lang="scss">
//
@import '@/styles/fonts.scss';
@import '@/styles/base.scss';
</style>

@ -1,152 +0,0 @@
<script setup lang="ts">
// import { getHomeGoodsGuessLikeAPI } from '@/services/home'
import type { PageParams } from '@/types/global'
import type { GuessItem } from '@/types/home'
import { onMounted, ref } from 'vue'
//
const pageParams: Required<PageParams> = {
page: 1,
pageSize: 10,
}
//
const guessList = ref<GuessItem[]>([])
//
const finish = ref(false)
//
const getHomeGoodsGuessLikeData = async () => {
// 退
if (finish.value === true) {
return uni.showToast({ icon: 'none', title: '没有更多数据~' })
}
// const res = await getHomeGoodsGuessLikeAPI(pageParams)
// guessList.value = res.result.items
//
guessList.value.push(...res.result.items)
//
if (pageParams.page < res.result.pages) {
//
pageParams.page++
} else {
finish.value = true
}
}
//
const resetData = () => {
pageParams.page = 1
guessList.value = []
finish.value = false
}
//
onMounted(() => {
getHomeGoodsGuessLikeData()
})
//
defineExpose({
resetData,
getMore: getHomeGoodsGuessLikeData,
})
</script>
<template>
<!-- 猜你喜欢 -->
<view class="caption">
<text class="text">猜你喜欢</text>
</view>
<view class="guess">
<navigator
class="guess-item"
v-for="item in guessList"
:key="item.id"
:url="`/pages/goods/goods?id=${item.id}`"
>
<image class="image" mode="aspectFill" :src="item.picture"></image>
<view class="name"> {{ item.name }} </view>
<view class="price">
<text class="small">¥</text>
<text>{{ item.price }}</text>
</view>
</navigator>
</view>
<view class="loading-text">
{{ finish ? '没有更多数据~' : '正在加载...' }}
</view>
</template>
<style lang="scss">
:host {
display: block;
}
/* 分类标题 */
.caption {
display: flex;
justify-content: center;
line-height: 1;
padding: 36rpx 0 40rpx;
font-size: 32rpx;
color: #262626;
.text {
display: flex;
justify-content: center;
align-items: center;
padding: 0 28rpx 0 30rpx;
&::before,
&::after {
content: '';
width: 20rpx;
height: 20rpx;
background-image: url(@/static/images/bubble.png);
background-size: contain;
margin: 0 10rpx;
}
}
}
/* 猜你喜欢 */
.guess {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 0 20rpx;
.guess-item {
width: 345rpx;
padding: 24rpx 20rpx 20rpx;
margin-bottom: 20rpx;
border-radius: 10rpx;
overflow: hidden;
background-color: #fff;
}
.image {
width: 304rpx;
height: 304rpx;
}
.name {
height: 75rpx;
margin: 10rpx 0;
font-size: 26rpx;
color: #262626;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.price {
line-height: 1;
padding-top: 4rpx;
color: #cf4444;
font-size: 26rpx;
}
.small {
font-size: 80%;
}
}
//
.loading-text {
text-align: center;
font-size: 28rpx;
color: #666;
padding: 20rpx 0;
}
</style>

@ -1,40 +0,0 @@
<script setup lang="ts">
import type { BannerItem } from '@/types/home'
import { ref } from 'vue'
const activeIndex = ref(0)
// swiper
const onChange: UniHelper.SwiperOnChange = (ev) => {
activeIndex.value = ev.detail.current
}
// props
defineProps<{
list: BannerItem[]
}>()
</script>
<template>
<view class="carousel">
<swiper :circular="true" :autoplay="false" :interval="3000" @change="onChange">
<swiper-item v-for="item in list" :key="item.id">
<navigator url="/pages/index/index" hover-class="none" class="navigator">
<image mode="aspectFill" class="image" :src="item.imgUrl"></image>
</navigator>
</swiper-item>
</swiper>
<!-- 指示点 -->
<view class="indicator">
<text
v-for="(item, index) in list"
:key="item.id"
class="dot"
:class="{ active: index === activeIndex }"
></text>
</view>
</view>
</template>
<style lang="scss">
@import './styles/XtxSwiper.scss';
</style>

@ -1,31 +0,0 @@
/* 轮播图 */
.carousel {
height: 280rpx;
position: relative;
overflow: hidden;
transform: translateY(0);
background-color: #efefef;
.indicator {
position: absolute;
left: 0;
right: 0;
bottom: 16rpx;
display: flex;
justify-content: center;
.dot {
width: 30rpx;
height: 6rpx;
margin: 0 8rpx;
border-radius: 6rpx;
background-color: rgba(255, 255, 255, 0.4);
}
.active {
background-color: #fff;
}
}
.navigator,
.image {
width: 100%;
height: 100%;
}
}

@ -1,145 +0,0 @@
import { Component } from '@uni-helper/uni-app-types'
/** SKU 弹出层 */
export type SkuPopup = Component<SkuPopupProps>
/** SKU 弹出层实例 */
export type SkuPopupInstance = InstanceType<SkuPopup>
/** SKU 弹出层属性 */
export type SkuPopupProps = {
/** 双向绑定true 为打开组件false 为关闭组件 */
modelValue: boolean
/** 商品信息本地数据源 */
localdata: SkuPopupLocaldata
/** 按钮模式 1:都显示 2:只显示购物车 3:只显示立即购买 */
mode?: 1 | 2 | 3
/** 该商品已抢完时的按钮文字 */
noStockText?: string
/** 库存文字 */
stockText?: string
/** 点击遮罩是否关闭组件 */
maskCloseAble?: boolean
/** 顶部圆角值 */
borderRadius?: string | number
/** 最小购买数量 */
minBuyNum?: number
/** 最大购买数量 */
maxBuyNum?: number
/** 每次点击后的数量 */
stepBuyNum?: number
/** 是否只能输入 step 的倍数 */
stepStrictly?: boolean
/** 是否隐藏库存的显示 */
hideStock?: false
/** 主题风格 */
theme?: 'default' | 'red-black' | 'black-white' | 'coffee' | 'green'
/** 默认金额会除以100即100=1元若设置为0则不会除以100即1=1元 */
amountType?: 1 | 0
/** 自定义获取商品信息的函数已知支付宝不支持支付宝请改用localdata属性 */
customAction?: () => void
/** 是否显示右上角关闭按钮 */
showClose?: boolean
/** 关闭按钮的图片地址 */
closeImage?: string
/** 价格的字体颜色 */
priceColor?: string
/** 立即购买 - 按钮的文字 */
buyNowText?: string
/** 立即购买 - 按钮的字体颜色 */
buyNowColor?: string
/** 立即购买 - 按钮的背景颜色 */
buyNowBackgroundColor?: string
/** 加入购物车 - 按钮的文字 */
addCartText?: string
/** 加入购物车 - 按钮的字体颜色 */
addCartColor?: string
/** 加入购物车 - 按钮的背景颜色 */
addCartBackgroundColor?: string
/** 商品缩略图背景颜色 */
goodsThumbBackgroundColor?: string
/** 样式 - 不可点击时,按钮的样式 */
disableStyle?: object
/** 样式 - 按钮点击时的样式 */
activedStyle?: object
/** 样式 - 按钮常态的样式 */
btnStyle?: object
/** 字段名 - 商品表id的字段名 */
goodsIdName?: string
/** 字段名 - sku表id的字段名 */
skuIdName?: string
/** 字段名 - 商品对应的sku列表的字段名 */
skuListName?: string
/** 字段名 - 商品规格名称的字段名 */
specListName?: string
/** 字段名 - sku库存的字段名 */
stockName?: string
/** 字段名 - sku组合路径的字段名 */
skuArrName?: string
/** 字段名 - 商品缩略图字段名(未选择sku时) */
goodsThumbName?: string
/** 被选中的值 */
selectArr?: string[]
/** 打开弹出层 */
onOpen: () => void
/** 关闭弹出层 */
onClose: () => void
/** 点击加入购物车时需选择完SKU才会触发*/
onAddCart: (event: SkuPopupEvent) => void
/** 点击立即购买时需选择完SKU才会触发*/
onBuyNow: (event: SkuPopupEvent) => void
}
/** 商品信息本地数据源 */
export type SkuPopupLocaldata = {
/** 商品 ID */
_id: string
/** 商品名称 */
name: string
/** 商品图片 */
goods_thumb: string
/** 商品规格列表 */
spec_list: SkuPopupSpecItem[]
/** 商品SKU列表 */
sku_list: SkuPopupSkuItem[]
}
/** 商品规格名称的集合 */
export type SkuPopupSpecItem = {
/** 规格名称 */
name: string
/** 规格集合 */
list: { name: string }[]
}
/** 商品SKU列表 */
export type SkuPopupSkuItem = {
/** SKU ID */
_id: string
/** 商品 ID */
goods_id: string
/** 商品名称 */
goods_name: string
/** 商品图片 */
image: string
/** SKU 价格 * 100, 注意:需要乘以 100 */
price: number
/** SKU 规格组成, 注意:需要与 spec_list 数组顺序对应 */
sku_name_arr: string[]
/** SKU 库存 */
stock: number
}
/** 当前选择的sku数据 */
export type SkuPopupEvent = SkuPopupSkuItem & {
/** 商品购买数量 */
buy_num: number
}
/** 全局组件类型声明 */
declare module '@vue/runtime-core' {
export interface GlobalComponents {
'vk-data-goods-sku-popup': SkuPopup
}
}

@ -1,52 +0,0 @@
import { Component } from '@uni-helper/uni-app-types'
/** 步进器 */
export type InputNumberBox = Component<InputNumberBoxProps>
/** 步进器实例 */
export type InputNumberBoxInstance = InstanceType<InputNumberBox>
/** 步进器属性 */
export type InputNumberBoxProps = {
/** 输入框初始值默认1 */
modelValue: number
/** 用户可输入的最小值默认0 */
min: number
/** 用户可输入的最大值默认99999 */
max: number
/** 步长每次加或减的值默认1 */
step: number
/** 是否禁用操作,包括输入框,加减按钮 */
disabled: boolean
/** 输入框宽度单位rpx默认80 */
inputWidth: string | number
/** 输入框和按钮的高度单位rpx默认50 */
inputHeight: string | number
/** 输入框和按钮的背景颜色(默认#F2F3F5 */
bgColor: string
/** 步进器标识符 */
index: string
/** 输入框内容发生变化时触发 */
onChange: (event: InputNumberBoxEvent) => void
/** 输入框失去焦点时触发 */
onBlur: (event: InputNumberBoxEvent) => void
/** 点击增加按钮时触发 */
onPlus: (event: InputNumberBoxEvent) => void
/** 点击减少按钮时触发 */
onMinus: (event: InputNumberBoxEvent) => void
}
/** 步进器事件对象 */
export type InputNumberBoxEvent = {
/** 输入框当前值 */
value: number
/** 步进器标识符 */
index: string
}
/** 全局组件类型声明 */
declare module '@vue/runtime-core' {
export interface GlobalComponents {
'vk-data-input-number-box': InputNumberBox
}
}

@ -1,458 +0,0 @@
<!-- 步进器 -->
<template>
<view class="vk-data-input-number-box">
<view
class="u-icon-minus"
:class="{ 'u-icon-disabled': disabled || inputVal <= min }"
:style="{
background: bgColor,
height: inputHeight + 'rpx',
color: color,
fontSize: size + 'rpx',
minHeight: '1.4em',
}"
@touchstart.prevent="btnTouchStart('minus')"
@touchend.stop.prevent="clearTimer"
>
<view :style="'font-size:' + (Number(size) + 10) + 'rpx'" class="num-btn"></view>
</view>
<input
v-model="inputVal"
:disabled="disabledInput || disabled"
:cursor-spacing="getCursorSpacing"
:class="{ 'u-input-disabled': disabled }"
class="u-number-input"
type="number"
:style="{
color: color,
fontSize: size + 'rpx',
background: bgColor,
height: inputHeight + 'rpx',
width: inputWidth + 'rpx',
}"
@blur="onBlur"
/>
<view
class="u-icon-plus"
:class="{ 'u-icon-disabled': disabled || inputVal >= max }"
:style="{
background: bgColor,
height: inputHeight + 'rpx',
color: color,
fontSize: size + 'rpx',
minHeight: '1.4em',
}"
@touchstart.prevent="btnTouchStart('plus')"
@touchend.stop.prevent="clearTimer"
>
<view :style="'font-size:' + (Number(size) + 10) + 'rpx'" class="num-btn"></view>
</view>
</view>
</template>
<script>
/* eslint-disable */
/**
* numberBox 步进器此为uview组件改造
* @description 该组件一般用于商城购物选择物品数量的场景注意该输入框只能输入大于或等于0的整数不支持小数输入
* @tutorial https://www.uviewui.com/components/numberBox.html
* @property {Number} value 输入框初始值默认1
* @property {String} bg-color 输入框和按钮的背景颜色默认#F2F3F5
* @property {Number} min 用户可输入的最小值默认0
* @property {Number} max 用户可输入的最大值默认99999
* @property {Number} step 步长每次加或减的值默认1
* @property {Number} stepFirst 步进值首次增加或最后减的值(默认step值和一致
* @property {Boolean} disabled 是否禁用操作禁用后无法加减或手动修改输入框的值默认false
* @property {Boolean} disabled-input 是否禁止输入框手动输入值默认false
* @property {Boolean} positive-integer 是否只能输入正整数默认true
* @property {String | Number} size 输入框文字和按钮字体大小单位rpx默认26
* @property {String} color 输入框文字和加减按钮图标的颜色默认#323233
* @property {String | Number} input-width 输入框宽度单位rpx默认80
* @property {String | Number} input-height 输入框和按钮的高度单位rpx默认50
* @property {String | Number} index 事件回调时用以区分当前发生变化的是哪个输入框
* @property {Boolean} long-press 是否开启长按连续递增或递减(默认true)
* @property {String | Number} press-time 开启长按触发后每触发一次需要多久单位ms(默认250)
* @property {String | Number} cursor-spacing 指定光标于键盘的距离避免键盘遮挡输入框单位rpx默认200
* @event {Function} change 输入框内容发生变化时触发对象形式
* @event {Function} blur 输入框失去焦点时触发对象形式
* @event {Function} minus 点击减少按钮时触发(按钮可点击情况下)对象形式
* @event {Function} plus 点击增加按钮时触发(按钮可点击情况下)对象形式
* @example <vk-data-input-number-box :min="1" :max="100"></vk-data-input-number-box>
*/
export default {
name: 'vk-data-input-number-box',
emits: ['update:modelValue', 'input', 'change', 'blur', 'plus', 'minus'],
props: {
//
value: {
type: Number,
default: 1,
},
modelValue: {
type: Number,
default: 1,
},
//
bgColor: {
type: String,
default: '#F2F3F5',
},
//
min: {
type: Number,
default: 0,
},
//
max: {
type: Number,
default: 99999,
},
//
step: {
type: Number,
default: 1,
},
//
stepFirst: {
type: Number,
default: 0,
},
// step
stepStrictly: {
type: Boolean,
default: false,
},
//
disabled: {
type: Boolean,
default: false,
},
// inputrpx
size: {
type: [Number, String],
default: 26,
},
//
color: {
type: String,
default: '#323233',
},
// inputrpx
inputWidth: {
type: [Number, String],
default: 80,
},
// inputrpx
inputHeight: {
type: [Number, String],
default: 50,
},
// index使numberbox使forindex
index: {
type: [Number, String],
default: '',
},
// disabledOR
// disabledfalsedisabledInputtrue
disabledInput: {
type: Boolean,
default: false,
},
//
cursorSpacing: {
type: [Number, String],
default: 100,
},
//
longPress: {
type: Boolean,
default: true,
},
//
pressTime: {
type: [Number, String],
default: 250,
},
// 0()
positiveInteger: {
type: Boolean,
default: true,
},
},
watch: {
valueCom(v1, v2) {
// valueinputVal
if (!this.changeFromInner) {
this.inputVal = v1
// inputValthis.handleChange()changeFromInnertrue
// this.$nextTick
// changeFromInnerfalse
this.$nextTick(function () {
this.changeFromInner = false
})
}
},
inputVal(v1, v2) {
//
if (v1 == '') return
let value = 0
// minmax使
let tmp = this.isNumber(v1)
if (tmp && v1 >= this.min && v1 <= this.max) value = v1
else value = v2
// 0
if (this.positiveInteger) {
// 0
if (v1 < 0 || String(v1).indexOf('.') !== -1) {
value = v2
// input使$nextTick
this.$nextTick(() => {
this.inputVal = v2
})
}
}
// change
this.handleChange(value, 'change')
},
min(v1) {
if (v1 !== undefined && v1 != '' && this.valueCom < v1) {
this.$emit('input', v1)
this.$emit('update:modelValue', v1)
}
},
max(v1) {
if (v1 !== undefined && v1 != '' && this.valueCom > v1) {
this.$emit('input', v1)
this.$emit('update:modelValue', v1)
}
},
},
data() {
return {
inputVal: 1, // 使propsvalueprops
timer: null, //
changeFromInner: false, //
innerChangeTimer: null, //
}
},
created() {
this.inputVal = Number(this.valueCom)
},
computed: {
valueCom() {
// #ifndef VUE3
return this.value
// #endif
// #ifdef VUE3
return this.modelValue
// #endif
},
getCursorSpacing() {
// px
return Number(uni.upx2px(this.cursorSpacing))
},
},
methods: {
// 退
btnTouchStart(callback) {
// clearTimer
this[callback]()
//
if (!this.longPress) return
clearInterval(this.timer) //
this.timer = null
this.timer = setInterval(() => {
//
this[callback]()
}, this.pressTime)
},
clearTimer() {
this.$nextTick(() => {
clearInterval(this.timer)
this.timer = null
})
},
minus() {
this.computeVal('minus')
},
plus() {
this.computeVal('plus')
},
//
calcPlus(num1, num2) {
let baseNum, baseNum1, baseNum2
try {
baseNum1 = num1.toString().split('.')[1].length
} catch (e) {
baseNum1 = 0
}
try {
baseNum2 = num2.toString().split('.')[1].length
} catch (e) {
baseNum2 = 0
}
baseNum = Math.pow(10, Math.max(baseNum1, baseNum2))
let precision = baseNum1 >= baseNum2 ? baseNum1 : baseNum2 //
return ((num1 * baseNum + num2 * baseNum) / baseNum).toFixed(precision)
},
//
calcMinus(num1, num2) {
let baseNum, baseNum1, baseNum2
try {
baseNum1 = num1.toString().split('.')[1].length
} catch (e) {
baseNum1 = 0
}
try {
baseNum2 = num2.toString().split('.')[1].length
} catch (e) {
baseNum2 = 0
}
baseNum = Math.pow(10, Math.max(baseNum1, baseNum2))
let precision = baseNum1 >= baseNum2 ? baseNum1 : baseNum2
return ((num1 * baseNum - num2 * baseNum) / baseNum).toFixed(precision)
},
computeVal(type) {
uni.hideKeyboard()
if (this.disabled) return
let value = 0
// stepFirst
//
if (type === 'minus') {
if (this.stepFirst > 0 && this.inputVal == this.stepFirst) {
value = this.min
} else {
value = this.calcMinus(this.inputVal, this.step)
}
} else if (type === 'plus') {
if (this.stepFirst > 0 && this.inputVal < this.stepFirst) {
value = this.stepFirst
} else {
value = this.calcPlus(this.inputVal, this.step)
}
}
if (this.stepStrictly) {
let strictly = value % this.step
if (strictly > 0) {
value -= strictly
}
}
if (value > this.max) {
value = this.max
} else if (value < this.min) {
value = this.min
}
// stepFirst
this.inputVal = value
this.handleChange(value, type)
},
//
onBlur(event) {
let val = 0
let value = event.detail.value
// 0-90min
// props min0
if (!/(^\d+$)/.test(value) || value[0] == 0) val = this.min
val = +value
// stepFirst
if (this.stepFirst > 0 && this.inputVal < this.stepFirst && this.inputVal > 0) {
val = this.stepFirst
}
// stepFirst
if (this.stepStrictly) {
let strictly = val % this.step
if (strictly > 0) {
val -= strictly
}
}
if (val > this.max) {
val = this.max
} else if (val < this.min) {
val = this.min
}
this.$nextTick(() => {
this.inputVal = val
})
this.handleChange(val, 'blur')
},
handleChange(value, type) {
if (this.disabled) return
//
if (this.innerChangeTimer) {
clearTimeout(this.innerChangeTimer)
this.innerChangeTimer = null
}
// inputv-model
this.changeFromInner = true
// changeFromInner
// value
this.innerChangeTimer = setTimeout(() => {
this.changeFromInner = false
}, 150)
this.$emit('input', Number(value))
this.$emit('update:modelValue', Number(value))
this.$emit(type, {
// Number
value: Number(value),
index: this.index,
})
},
/**
* 验证十进制数字
*/
isNumber(value) {
return /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value)
},
},
}
</script>
<style lang="scss" scoped>
.vk-data-input-number-box {
display: inline-flex;
align-items: center;
}
.u-number-input {
position: relative;
text-align: center;
padding: 0;
margin: 0 6rpx;
display: flex;
align-items: center;
justify-content: center;
}
.u-icon-plus,
.u-icon-minus {
width: 60rpx;
display: flex;
justify-content: center;
align-items: center;
}
.u-icon-plus {
border-radius: 0 8rpx 8rpx 0;
}
.u-icon-minus {
border-radius: 8rpx 0 0 8rpx;
}
.u-icon-disabled {
color: #c8c9cc !important;
background: #f7f8fa !important;
}
.u-input-disabled {
color: #c8c9cc !important;
background-color: #f2f3f5 !important;
}
.num-btn {
font-weight: 550;
position: relative;
top: -4rpx;
}
</style>

@ -1,21 +0,0 @@
import type { XtxGuessInstance } from '@/types/components'
import { ref } from 'vue'
/**
*
*/
export const useGuessList = () => {
// 获取猜你喜欢组件实例
const guessRef = ref<XtxGuessInstance>()
// 滚动触底事件
const onScrolltolower = () => {
guessRef.value?.getMore()
}
// 返回 ref 和事件处理函数
return {
guessRef,
onScrolltolower,
}
}

@ -1,8 +0,0 @@
/// <reference types="vite/client" />
declare module '*.vue' {
//@ts-ignore
import { DefineComponent } from 'vue'
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>
export default component
}

@ -1,923 +0,0 @@
/*
* @Author: 王文杰
* @Date: 2019-03-05 14:39:24
* @LastEditors: 王文杰
* @LastEditTime: 2024-01-30 16:59:47
* @FilePath: /app-nx-recycle/src/libs/qqmap-wx-jssdk1.2/qqmap-wx-jssdk.min.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
var ERROR_CONF = {
KEY_ERR: 311,
KEY_ERR_MSG: 'key格式错误',
PARAM_ERR: 310,
PARAM_ERR_MSG: '请求参数信息有误',
SYSTEM_ERR: 600,
SYSTEM_ERR_MSG: '系统错误',
WX_ERR_CODE: 1000,
WX_OK_CODE: 200,
}
var BASE_URL = 'https://apis.map.qq.com/ws/'
var URL_SEARCH = BASE_URL + 'place/v1/search'
var URL_SUGGESTION = BASE_URL + 'place/v1/suggestion'
var URL_GET_GEOCODER = BASE_URL + 'geocoder/v1/'
var URL_CITY_LIST = BASE_URL + 'district/v1/list'
var URL_AREA_LIST = BASE_URL + 'district/v1/getchildren'
var URL_DISTANCE = BASE_URL + 'distance/v1/'
var URL_DIRECTION = BASE_URL + 'direction/v1/'
var MODE = { driving: 'driving', transit: 'transit' }
var EARTH_RADIUS = 6378136.49
var Utils = {
safeAdd(x, y) {
var lsw = (x & 0xffff) + (y & 0xffff)
var msw = (x >> 16) + (y >> 16) + (lsw >> 16)
return (msw << 16) | (lsw & 0xffff)
},
bitRotateLeft(num, cnt) {
return (num << cnt) | (num >>> (32 - cnt))
},
md5cmn(q, a, b, x, s, t) {
return this.safeAdd(
this.bitRotateLeft(this.safeAdd(this.safeAdd(a, q), this.safeAdd(x, t)), s),
b,
)
},
md5ff(a, b, c, d, x, s, t) {
return this.md5cmn((b & c) | (~b & d), a, b, x, s, t)
},
md5gg(a, b, c, d, x, s, t) {
return this.md5cmn((b & d) | (c & ~d), a, b, x, s, t)
},
md5hh(a, b, c, d, x, s, t) {
return this.md5cmn(b ^ c ^ d, a, b, x, s, t)
},
md5ii(a, b, c, d, x, s, t) {
return this.md5cmn(c ^ (b | ~d), a, b, x, s, t)
},
binlMD5(x, len) {
x[len >> 5] |= 0x80 << len % 32
x[(((len + 64) >>> 9) << 4) + 14] = len
var i
var olda
var oldb
var oldc
var oldd
var a = 1732584193
var b = -271733879
var c = -1732584194
var d = 271733878
for (i = 0; i < x.length; i += 16) {
olda = a
oldb = b
oldc = c
oldd = d
a = this.md5ff(a, b, c, d, x[i], 7, -680876936)
d = this.md5ff(d, a, b, c, x[i + 1], 12, -389564586)
c = this.md5ff(c, d, a, b, x[i + 2], 17, 606105819)
b = this.md5ff(b, c, d, a, x[i + 3], 22, -1044525330)
a = this.md5ff(a, b, c, d, x[i + 4], 7, -176418897)
d = this.md5ff(d, a, b, c, x[i + 5], 12, 1200080426)
c = this.md5ff(c, d, a, b, x[i + 6], 17, -1473231341)
b = this.md5ff(b, c, d, a, x[i + 7], 22, -45705983)
a = this.md5ff(a, b, c, d, x[i + 8], 7, 1770035416)
d = this.md5ff(d, a, b, c, x[i + 9], 12, -1958414417)
c = this.md5ff(c, d, a, b, x[i + 10], 17, -42063)
b = this.md5ff(b, c, d, a, x[i + 11], 22, -1990404162)
a = this.md5ff(a, b, c, d, x[i + 12], 7, 1804603682)
d = this.md5ff(d, a, b, c, x[i + 13], 12, -40341101)
c = this.md5ff(c, d, a, b, x[i + 14], 17, -1502002290)
b = this.md5ff(b, c, d, a, x[i + 15], 22, 1236535329)
a = this.md5gg(a, b, c, d, x[i + 1], 5, -165796510)
d = this.md5gg(d, a, b, c, x[i + 6], 9, -1069501632)
c = this.md5gg(c, d, a, b, x[i + 11], 14, 643717713)
b = this.md5gg(b, c, d, a, x[i], 20, -373897302)
a = this.md5gg(a, b, c, d, x[i + 5], 5, -701558691)
d = this.md5gg(d, a, b, c, x[i + 10], 9, 38016083)
c = this.md5gg(c, d, a, b, x[i + 15], 14, -660478335)
b = this.md5gg(b, c, d, a, x[i + 4], 20, -405537848)
a = this.md5gg(a, b, c, d, x[i + 9], 5, 568446438)
d = this.md5gg(d, a, b, c, x[i + 14], 9, -1019803690)
c = this.md5gg(c, d, a, b, x[i + 3], 14, -187363961)
b = this.md5gg(b, c, d, a, x[i + 8], 20, 1163531501)
a = this.md5gg(a, b, c, d, x[i + 13], 5, -1444681467)
d = this.md5gg(d, a, b, c, x[i + 2], 9, -51403784)
c = this.md5gg(c, d, a, b, x[i + 7], 14, 1735328473)
b = this.md5gg(b, c, d, a, x[i + 12], 20, -1926607734)
a = this.md5hh(a, b, c, d, x[i + 5], 4, -378558)
d = this.md5hh(d, a, b, c, x[i + 8], 11, -2022574463)
c = this.md5hh(c, d, a, b, x[i + 11], 16, 1839030562)
b = this.md5hh(b, c, d, a, x[i + 14], 23, -35309556)
a = this.md5hh(a, b, c, d, x[i + 1], 4, -1530992060)
d = this.md5hh(d, a, b, c, x[i + 4], 11, 1272893353)
c = this.md5hh(c, d, a, b, x[i + 7], 16, -155497632)
b = this.md5hh(b, c, d, a, x[i + 10], 23, -1094730640)
a = this.md5hh(a, b, c, d, x[i + 13], 4, 681279174)
d = this.md5hh(d, a, b, c, x[i], 11, -358537222)
c = this.md5hh(c, d, a, b, x[i + 3], 16, -722521979)
b = this.md5hh(b, c, d, a, x[i + 6], 23, 76029189)
a = this.md5hh(a, b, c, d, x[i + 9], 4, -640364487)
d = this.md5hh(d, a, b, c, x[i + 12], 11, -421815835)
c = this.md5hh(c, d, a, b, x[i + 15], 16, 530742520)
b = this.md5hh(b, c, d, a, x[i + 2], 23, -995338651)
a = this.md5ii(a, b, c, d, x[i], 6, -198630844)
d = this.md5ii(d, a, b, c, x[i + 7], 10, 1126891415)
c = this.md5ii(c, d, a, b, x[i + 14], 15, -1416354905)
b = this.md5ii(b, c, d, a, x[i + 5], 21, -57434055)
a = this.md5ii(a, b, c, d, x[i + 12], 6, 1700485571)
d = this.md5ii(d, a, b, c, x[i + 3], 10, -1894986606)
c = this.md5ii(c, d, a, b, x[i + 10], 15, -1051523)
b = this.md5ii(b, c, d, a, x[i + 1], 21, -2054922799)
a = this.md5ii(a, b, c, d, x[i + 8], 6, 1873313359)
d = this.md5ii(d, a, b, c, x[i + 15], 10, -30611744)
c = this.md5ii(c, d, a, b, x[i + 6], 15, -1560198380)
b = this.md5ii(b, c, d, a, x[i + 13], 21, 1309151649)
a = this.md5ii(a, b, c, d, x[i + 4], 6, -145523070)
d = this.md5ii(d, a, b, c, x[i + 11], 10, -1120210379)
c = this.md5ii(c, d, a, b, x[i + 2], 15, 718787259)
b = this.md5ii(b, c, d, a, x[i + 9], 21, -343485551)
a = this.safeAdd(a, olda)
b = this.safeAdd(b, oldb)
c = this.safeAdd(c, oldc)
d = this.safeAdd(d, oldd)
}
return [a, b, c, d]
},
binl2rstr(input) {
var i
var output = ''
var length32 = input.length * 32
for (i = 0; i < length32; i += 8) {
output += String.fromCharCode((input[i >> 5] >>> i % 32) & 0xff)
}
return output
},
rstr2binl(input) {
var i
var output = []
output[(input.length >> 2) - 1] = undefined
for (i = 0; i < output.length; i += 1) {
output[i] = 0
}
var length8 = input.length * 8
for (i = 0; i < length8; i += 8) {
output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << i % 32
}
return output
},
rstrMD5(s) {
return this.binl2rstr(this.binlMD5(this.rstr2binl(s), s.length * 8))
},
rstrHMACMD5(key, data) {
var i
var bkey = this.rstr2binl(key)
var ipad = []
var opad = []
var hash
ipad[15] = opad[15] = undefined
if (bkey.length > 16) {
bkey = this.binlMD5(bkey, key.length * 8)
}
for (i = 0; i < 16; i += 1) {
ipad[i] = bkey[i] ^ 0x36363636
opad[i] = bkey[i] ^ 0x5c5c5c5c
}
hash = this.binlMD5(ipad.concat(this.rstr2binl(data)), 512 + data.length * 8)
return this.binl2rstr(this.binlMD5(opad.concat(hash), 512 + 128))
},
rstr2hex(input) {
var hexTab = '0123456789abcdef'
var output = ''
var x
var i
for (i = 0; i < input.length; i += 1) {
x = input.charCodeAt(i)
output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f)
}
return output
},
str2rstrUTF8(input) {
return unescape(encodeURIComponent(input))
},
rawMD5(s) {
return this.rstrMD5(this.str2rstrUTF8(s))
},
hexMD5(s) {
return this.rstr2hex(this.rawMD5(s))
},
rawHMACMD5(k, d) {
return this.rstrHMACMD5(this.str2rstrUTF8(k), str2rstrUTF8(d))
},
hexHMACMD5(k, d) {
return this.rstr2hex(this.rawHMACMD5(k, d))
},
md5(string, key, raw) {
if (!key) {
if (!raw) {
return this.hexMD5(string)
}
return this.rawMD5(string)
}
if (!raw) {
return this.hexHMACMD5(key, string)
}
return this.rawHMACMD5(key, string)
},
getSig(requestParam, sk, feature, mode) {
var sig = null
var requestArr = []
Object.keys(requestParam)
.sort()
.forEach(function (key) {
requestArr.push(key + '=' + requestParam[key])
})
if (feature == 'search') {
sig = '/ws/place/v1/search?' + requestArr.join('&') + sk
}
if (feature == 'suggest') {
sig = '/ws/place/v1/suggestion?' + requestArr.join('&') + sk
}
if (feature == 'reverseGeocoder') {
sig = '/ws/geocoder/v1/?' + requestArr.join('&') + sk
}
if (feature == 'geocoder') {
sig = '/ws/geocoder/v1/?' + requestArr.join('&') + sk
}
if (feature == 'getCityList') {
sig = '/ws/district/v1/list?' + requestArr.join('&') + sk
}
if (feature == 'getDistrictByCityId') {
sig = '/ws/district/v1/getchildren?' + requestArr.join('&') + sk
}
if (feature == 'calculateDistance') {
sig = '/ws/distance/v1/?' + requestArr.join('&') + sk
}
if (feature == 'direction') {
sig = '/ws/direction/v1/' + mode + '?' + requestArr.join('&') + sk
}
sig = this.md5(sig)
return sig
},
location2query(data) {
if (typeof data == 'string') {
return data
}
var query = ''
for (var i = 0; i < data.length; i++) {
var d = data[i]
if (query) {
query += ';'
}
if (d.location) {
query = query + d.location.lat + ',' + d.location.lng
}
if (d.latitude && d.longitude) {
query = query + d.latitude + ',' + d.longitude
}
}
return query
},
rad(d) {
return (d * Math.PI) / 180.0
},
getEndLocation(location) {
var to = location.split(';')
var endLocation = []
for (var i = 0; i < to.length; i++) {
endLocation.push({
lat: parseFloat(to[i].split(',')[0]),
lng: parseFloat(to[i].split(',')[1]),
})
}
return endLocation
},
getDistance(latFrom, lngFrom, latTo, lngTo) {
var radLatFrom = this.rad(latFrom)
var radLatTo = this.rad(latTo)
var a = radLatFrom - radLatTo
var b = this.rad(lngFrom) - this.rad(lngTo)
var distance =
2 *
Math.asin(
Math.sqrt(
Math.pow(Math.sin(a / 2), 2) +
Math.cos(radLatFrom) * Math.cos(radLatTo) * Math.pow(Math.sin(b / 2), 2),
),
)
distance = distance * EARTH_RADIUS
distance = Math.round(distance * 10000) / 10000
return parseFloat(distance.toFixed(0))
},
getWXLocation(success, fail, complete) {
wx.getLocation({ type: 'gcj02', success: success, fail: fail, complete: complete })
},
getLocationParam(location) {
if (typeof location == 'string') {
var locationArr = location.split(',')
if (locationArr.length === 2) {
location = { latitude: location.split(',')[0], longitude: location.split(',')[1] }
} else {
location = {}
}
}
return location
},
polyfillParam(param) {
param.success = param.success || function () {}
param.fail = param.fail || function () {}
param.complete = param.complete || function () {}
},
checkParamKeyEmpty(param, key) {
if (!param[key]) {
var errconf = this.buildErrorConfig(
ERROR_CONF.PARAM_ERR,
ERROR_CONF.PARAM_ERR_MSG + key + '参数格式有误',
)
param.fail(errconf)
param.complete(errconf)
return true
}
return false
},
checkKeyword(param) {
return !this.checkParamKeyEmpty(param, 'keyword')
},
checkLocation(param) {
var location = this.getLocationParam(param.location)
if (!location || !location.latitude || !location.longitude) {
var errconf = this.buildErrorConfig(
ERROR_CONF.PARAM_ERR,
ERROR_CONF.PARAM_ERR_MSG + ' location参数格式有误',
)
param.fail(errconf)
param.complete(errconf)
return false
}
return true
},
buildErrorConfig(errCode, errMsg) {
return { status: errCode, message: errMsg }
},
handleData(param, data, feature) {
if (feature == 'search') {
var searchResult = data.data
var searchSimplify = []
for (var i = 0; i < searchResult.length; i++) {
searchSimplify.push({
id: searchResult[i].id || null,
title: searchResult[i].title || null,
latitude: (searchResult[i].location && searchResult[i].location.lat) || null,
longitude: (searchResult[i].location && searchResult[i].location.lng) || null,
address: searchResult[i].address || null,
category: searchResult[i].category || null,
tel: searchResult[i].tel || null,
adcode: (searchResult[i].ad_info && searchResult[i].ad_info.adcode) || null,
city: (searchResult[i].ad_info && searchResult[i].ad_info.city) || null,
district: (searchResult[i].ad_info && searchResult[i].ad_info.district) || null,
province: (searchResult[i].ad_info && searchResult[i].ad_info.province) || null,
})
}
param.success(data, { searchResult: searchResult, searchSimplify: searchSimplify })
} else if (feature == 'suggest') {
var suggestResult = data.data
var suggestSimplify = []
for (var i = 0; i < suggestResult.length; i++) {
suggestSimplify.push({
adcode: suggestResult[i].adcode || null,
address: suggestResult[i].address || null,
category: suggestResult[i].category || null,
city: suggestResult[i].city || null,
district: suggestResult[i].district || null,
id: suggestResult[i].id || null,
latitude: (suggestResult[i].location && suggestResult[i].location.lat) || null,
longitude: (suggestResult[i].location && suggestResult[i].location.lng) || null,
province: suggestResult[i].province || null,
title: suggestResult[i].title || null,
type: suggestResult[i].type || null,
})
}
param.success(data, { suggestResult: suggestResult, suggestSimplify: suggestSimplify })
} else if (feature == 'reverseGeocoder') {
var reverseGeocoderResult = data.result
var reverseGeocoderSimplify = {
address: reverseGeocoderResult.address || null,
latitude: (reverseGeocoderResult.location && reverseGeocoderResult.location.lat) || null,
longitude: (reverseGeocoderResult.location && reverseGeocoderResult.location.lng) || null,
adcode: (reverseGeocoderResult.ad_info && reverseGeocoderResult.ad_info.adcode) || null,
city:
(reverseGeocoderResult.address_component &&
reverseGeocoderResult.address_component.city) ||
null,
district:
(reverseGeocoderResult.address_component &&
reverseGeocoderResult.address_component.district) ||
null,
nation:
(reverseGeocoderResult.address_component &&
reverseGeocoderResult.address_component.nation) ||
null,
province:
(reverseGeocoderResult.address_component &&
reverseGeocoderResult.address_component.province) ||
null,
street:
(reverseGeocoderResult.address_component &&
reverseGeocoderResult.address_component.street) ||
null,
street_number:
(reverseGeocoderResult.address_component &&
reverseGeocoderResult.address_component.street_number) ||
null,
recommend:
(reverseGeocoderResult.formatted_addresses &&
reverseGeocoderResult.formatted_addresses.recommend) ||
null,
rough:
(reverseGeocoderResult.formatted_addresses &&
reverseGeocoderResult.formatted_addresses.rough) ||
null,
}
if (reverseGeocoderResult.pois) {
var pois = reverseGeocoderResult.pois
var poisSimplify = []
for (var i = 0; i < pois.length; i++) {
poisSimplify.push({
id: pois[i].id || null,
title: pois[i].title || null,
latitude: (pois[i].location && pois[i].location.lat) || null,
longitude: (pois[i].location && pois[i].location.lng) || null,
address: pois[i].address || null,
category: pois[i].category || null,
adcode: (pois[i].ad_info && pois[i].ad_info.adcode) || null,
city: (pois[i].ad_info && pois[i].ad_info.city) || null,
district: (pois[i].ad_info && pois[i].ad_info.district) || null,
province: (pois[i].ad_info && pois[i].ad_info.province) || null,
})
}
param.success(data, {
reverseGeocoderResult: reverseGeocoderResult,
reverseGeocoderSimplify: reverseGeocoderSimplify,
pois: pois,
poisSimplify: poisSimplify,
})
} else {
param.success(data, {
reverseGeocoderResult: reverseGeocoderResult,
reverseGeocoderSimplify: reverseGeocoderSimplify,
})
}
} else if (feature == 'geocoder') {
var geocoderResult = data.result
var geocoderSimplify = {
title: geocoderResult.title || null,
latitude: (geocoderResult.location && geocoderResult.location.lat) || null,
longitude: (geocoderResult.location && geocoderResult.location.lng) || null,
adcode: (geocoderResult.ad_info && geocoderResult.ad_info.adcode) || null,
province:
(geocoderResult.address_components && geocoderResult.address_components.province) || null,
city: (geocoderResult.address_components && geocoderResult.address_components.city) || null,
district:
(geocoderResult.address_components && geocoderResult.address_components.district) || null,
street:
(geocoderResult.address_components && geocoderResult.address_components.street) || null,
street_number:
(geocoderResult.address_components && geocoderResult.address_components.street_number) ||
null,
level: geocoderResult.level || null,
}
param.success(data, { geocoderResult: geocoderResult, geocoderSimplify: geocoderSimplify })
} else if (feature == 'getCityList') {
var provinceResult = data.result[0]
var cityResult = data.result[1]
var districtResult = data.result[2]
param.success(data, {
provinceResult: provinceResult,
cityResult: cityResult,
districtResult: districtResult,
})
} else if (feature == 'getDistrictByCityId') {
var districtByCity = data.result[0]
param.success(data, districtByCity)
} else if (feature == 'calculateDistance') {
var calculateDistanceResult = data.result.elements
var distance = []
for (var i = 0; i < calculateDistanceResult.length; i++) {
distance.push(calculateDistanceResult[i].distance)
}
param.success(data, { calculateDistanceResult: calculateDistanceResult, distance: distance })
} else if (feature == 'direction') {
var direction = data.result.routes
param.success(data, direction)
} else {
param.success(data)
}
},
buildWxRequestConfig(param, options, feature) {
var that = this
options.header = { 'content-type': 'application/json' }
options.method = 'GET'
options.success = function (res) {
var data = res.data
if (data.status === 0) {
that.handleData(param, data, feature)
} else {
param.fail(data)
}
}
options.fail = function (res) {
res.statusCode = ERROR_CONF.WX_ERR_CODE
param.fail(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg))
}
options.complete = function (res) {
var statusCode = +res.statusCode
switch (statusCode) {
case ERROR_CONF.WX_ERR_CODE: {
param.complete(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg))
break
}
case ERROR_CONF.WX_OK_CODE: {
var data = res.data
if (data.status === 0) {
param.complete(data)
} else {
param.complete(that.buildErrorConfig(data.status, data.message))
}
break
}
default: {
param.complete(that.buildErrorConfig(ERROR_CONF.SYSTEM_ERR, ERROR_CONF.SYSTEM_ERR_MSG))
}
}
}
return options
},
locationProcess(param, locationsuccess, locationfail, locationcomplete) {
var that = this
locationfail =
locationfail ||
function (res) {
res.statusCode = ERROR_CONF.WX_ERR_CODE
param.fail(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg))
}
locationcomplete =
locationcomplete ||
function (res) {
if (res.statusCode == ERROR_CONF.WX_ERR_CODE) {
param.complete(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg))
}
}
if (!param.location) {
that.getWXLocation(locationsuccess, locationfail, locationcomplete)
} else if (that.checkLocation(param)) {
var location = Utils.getLocationParam(param.location)
locationsuccess(location)
}
},
}
class QQMapWX {
constructor(options) {
if (!options.key) {
throw Error('key值不能为空')
}
this.key = options.key
}
search(options) {
var that = this
options = options || {}
Utils.polyfillParam(options)
if (!Utils.checkKeyword(options)) {
return
}
var requestParam = {
keyword: options.keyword,
orderby: options.orderby || '_distance',
page_size: options.page_size || 10,
page_index: options.page_index || 1,
output: 'json',
key: that.key,
}
if (options.address_format) {
requestParam.address_format = options.address_format
}
if (options.filter) {
requestParam.filter = options.filter
}
var distance = options.distance || '1000'
var auto_extend = options.auto_extend || 1
var region = null
var rectangle = null
if (options.region) {
region = options.region
}
if (options.rectangle) {
rectangle = options.rectangle
}
var locationsuccess = function (result) {
if (region && !rectangle) {
requestParam.boundary =
'region(' +
region +
',' +
auto_extend +
',' +
result.latitude +
',' +
result.longitude +
')'
if (options.sig) {
requestParam.sig = Utils.getSig(requestParam, options.sig, 'search')
}
} else if (rectangle && !region) {
requestParam.boundary = 'rectangle(' + rectangle + ')'
if (options.sig) {
requestParam.sig = Utils.getSig(requestParam, options.sig, 'search')
}
} else {
requestParam.boundary =
'nearby(' +
result.latitude +
',' +
result.longitude +
',' +
distance +
',' +
auto_extend +
')'
if (options.sig) {
requestParam.sig = Utils.getSig(requestParam, options.sig, 'search')
}
}
wx.request(
Utils.buildWxRequestConfig(options, { url: URL_SEARCH, data: requestParam }, 'search'),
)
}
Utils.locationProcess(options, locationsuccess)
}
getSuggestion(options) {
var that = this
options = options || {}
Utils.polyfillParam(options)
if (!Utils.checkKeyword(options)) {
return
}
var requestParam = {
keyword: options.keyword,
region: options.region || '全国',
region_fix: options.region_fix || 0,
policy: options.policy || 0,
page_size: options.page_size || 10,
page_index: options.page_index || 1,
get_subpois: options.get_subpois || 0,
output: 'json',
key: that.key,
}
if (options.address_format) {
requestParam.address_format = options.address_format
}
if (options.filter) {
requestParam.filter = options.filter
}
if (options.location) {
var locationsuccess = function (result) {
requestParam.location = result.latitude + ',' + result.longitude
if (options.sig) {
requestParam.sig = Utils.getSig(requestParam, options.sig, 'suggest')
}
wx.request(
Utils.buildWxRequestConfig(
options,
{ url: URL_SUGGESTION, data: requestParam },
'suggest',
),
)
}
Utils.locationProcess(options, locationsuccess)
} else {
if (options.sig) {
requestParam.sig = Utils.getSig(requestParam, options.sig, 'suggest')
}
wx.request(
Utils.buildWxRequestConfig(options, { url: URL_SUGGESTION, data: requestParam }, 'suggest'),
)
}
}
reverseGeocoder(options) {
var that = this
options = options || {}
Utils.polyfillParam(options)
var requestParam = {
coord_type: options.coord_type || 5,
get_poi: options.get_poi || 0,
output: 'json',
key: that.key,
}
if (options.poi_options) {
requestParam.poi_options = options.poi_options
}
var locationsuccess = function (result) {
requestParam.location = result.latitude + ',' + result.longitude
if (options.sig) {
requestParam.sig = Utils.getSig(requestParam, options.sig, 'reverseGeocoder')
}
wx.request(
Utils.buildWxRequestConfig(
options,
{ url: URL_GET_GEOCODER, data: requestParam },
'reverseGeocoder',
),
)
}
Utils.locationProcess(options, locationsuccess)
}
geocoder(options) {
var that = this
options = options || {}
Utils.polyfillParam(options)
if (Utils.checkParamKeyEmpty(options, 'address')) {
return
}
var requestParam = { address: options.address, output: 'json', key: that.key }
if (options.region) {
requestParam.region = options.region
}
if (options.sig) {
requestParam.sig = Utils.getSig(requestParam, options.sig, 'geocoder')
}
wx.request(
Utils.buildWxRequestConfig(
options,
{ url: URL_GET_GEOCODER, data: requestParam },
'geocoder',
),
)
}
getCityList(options) {
var that = this
options = options || {}
Utils.polyfillParam(options)
var requestParam = { output: 'json', key: that.key }
if (options.sig) {
requestParam.sig = Utils.getSig(requestParam, options.sig, 'getCityList')
}
wx.request(
Utils.buildWxRequestConfig(
options,
{ url: URL_CITY_LIST, data: requestParam },
'getCityList',
),
)
}
getDistrictByCityId(options) {
var that = this
options = options || {}
Utils.polyfillParam(options)
if (Utils.checkParamKeyEmpty(options, 'id')) {
return
}
var requestParam = { id: options.id || '', output: 'json', key: that.key }
if (options.sig) {
requestParam.sig = Utils.getSig(requestParam, options.sig, 'getDistrictByCityId')
}
wx.request(
Utils.buildWxRequestConfig(
options,
{ url: URL_AREA_LIST, data: requestParam },
'getDistrictByCityId',
),
)
}
calculateDistance(options) {
var that = this
options = options || {}
Utils.polyfillParam(options)
if (Utils.checkParamKeyEmpty(options, 'to')) {
return
}
var requestParam = {
mode: options.mode || 'walking',
to: Utils.location2query(options.to),
output: 'json',
key: that.key,
}
if (options.from) {
options.location = options.from
}
if (requestParam.mode == 'straight') {
var locationsuccess = function (result) {
var locationTo = Utils.getEndLocation(requestParam.to)
var data = { message: 'query ok', result: { elements: [] }, status: 0 }
for (var i = 0; i < locationTo.length; i++) {
data.result.elements.push({
distance: Utils.getDistance(
result.latitude,
result.longitude,
locationTo[i].lat,
locationTo[i].lng,
),
duration: 0,
from: { lat: result.latitude, lng: result.longitude },
to: { lat: locationTo[i].lat, lng: locationTo[i].lng },
})
}
var calculateResult = data.result.elements
var distanceResult = []
for (var i = 0; i < calculateResult.length; i++) {
distanceResult.push(calculateResult[i].distance)
}
return options.success(data, {
calculateResult: calculateResult,
distanceResult: distanceResult,
})
}
Utils.locationProcess(options, locationsuccess)
} else {
var locationsuccess = function (result) {
requestParam.from = result.latitude + ',' + result.longitude
if (options.sig) {
requestParam.sig = Utils.getSig(requestParam, options.sig, 'calculateDistance')
}
wx.request(
Utils.buildWxRequestConfig(
options,
{ url: URL_DISTANCE, data: requestParam },
'calculateDistance',
),
)
}
Utils.locationProcess(options, locationsuccess)
}
}
direction(options) {
var that = this
options = options || {}
Utils.polyfillParam(options)
if (Utils.checkParamKeyEmpty(options, 'to')) {
return
}
var requestParam = { output: 'json', key: that.key }
if (typeof options.to == 'string') {
requestParam.to = options.to
} else {
requestParam.to = options.to.latitude + ',' + options.to.longitude
}
var SET_URL_DIRECTION = null
options.mode = options.mode || MODE.driving
SET_URL_DIRECTION = URL_DIRECTION + options.mode
if (options.from) {
options.location = options.from
}
if (options.mode == MODE.driving) {
if (options.from_poi) {
requestParam.from_poi = options.from_poi
}
if (options.heading) {
requestParam.heading = options.heading
}
if (options.speed) {
requestParam.speed = options.speed
}
if (options.accuracy) {
requestParam.accuracy = options.accuracy
}
if (options.road_type) {
requestParam.road_type = options.road_type
}
if (options.to_poi) {
requestParam.to_poi = options.to_poi
}
if (options.from_track) {
requestParam.from_track = options.from_track
}
if (options.waypoints) {
requestParam.waypoints = options.waypoints
}
if (options.policy) {
requestParam.policy = options.policy
}
if (options.plate_number) {
requestParam.plate_number = options.plate_number
}
}
if (options.mode == MODE.transit) {
if (options.departure_time) {
requestParam.departure_time = options.departure_time
}
if (options.policy) {
requestParam.policy = options.policy
}
}
var locationsuccess = function (result) {
requestParam.from = result.latitude + ',' + result.longitude
if (options.sig) {
requestParam.sig = Utils.getSig(requestParam, options.sig, 'direction', options.mode)
}
wx.request(
Utils.buildWxRequestConfig(
options,
{ url: SET_URL_DIRECTION, data: requestParam },
'direction',
),
)
}
Utils.locationProcess(options, locationsuccess)
}
}
export default QQMapWX

@ -1,19 +0,0 @@
import { createSSRApp } from 'vue'
import App from './App.vue'
// 导入 pinia 实例
import pinia from './stores'
export function createApp() {
// 创建 vue 实例
const app = createSSRApp(App)
// 使用 pinia
app.use(pinia)
return {
app,
}
}

@ -1,131 +0,0 @@
{
"name" : "合力机械小程序",
"appid" : "__UNI__F93316F",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
/* 5+App */
"app-plus" : {
//
"compatible" : {
"ignoreVersion" : true
},
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
/* */
"modules" : {},
/* */
"distribute" : {
/* android */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios */
"ios" : {
"dSYMs" : false
},
/* SDK */
"sdkConfigs" : {
"ad" : {}
},
"icons" : {
"android" : {
"hdpi" : "unpackage/res/icons/72x72.png",
"xhdpi" : "unpackage/res/icons/96x96.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
},
"ios" : {
"appstore" : "unpackage/res/icons/1024x1024.png",
"ipad" : {
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"notification" : "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png"
},
"iphone" : {
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png"
}
}
},
"splashscreen" : {
"androidStyle" : "default"
}
}
},
/* */
"quickapp" : {},
/* */
"h5" : {
"router" : {
// /
"base" : "./"
}
},
/* */
"mp-weixin" : {
"appid" : "wxa29fe397274614b5",
"setting" : {
"minified" : true,
"urlCheck" : true,
"es6" : true,
"postcss" : true
},
//
"lazyCodeLoading" : "requiredComponents",
"usingComponents" : true,
"uniStatistics" : {
"enable" : true
}
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "3",
"fallbackLocale" : "zh-Hans"
}

@ -1,121 +0,0 @@
{
//
"easycom": {
//
"autoscan": true,
//
"custom": {
// uni-ui
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue",
// Xtx components
"^Xtx(.*)": "@/components/Xtx$1.vue"
}
},
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/previewPdf/previewPdf",
"style": {
"navigationBarTitleText": "预览"
}
},
{
"path": "pages/approveOrder/approveOrder-detail",
"style": {
"navigationBarTitleText": "订单详情"
}
},
{
"path": "pages/approveOrder/approveOrder",
"style": {
"navigationBarTitleText": "订单批准"
}
},
{
"path": "pages/unqualifiedNotification/unqualifiedNotification",
"style": {
"navigationBarTitleText": "品质异常通知单"
}
},
{
"path": "pages/productionReport/productionReport-detail",
"style": {
"navigationBarTitleText": "生产报工详情"
}
},
{
"path": "pages/productionReport/productionReport",
"style": {
"navigationBarTitleText": "生产报工"
}
},
{
"path": "pages/assembleReport/assembleReport-detail",
"style": {
"navigationBarTitleText": "装配报工详情"
}
},
{
"path": "pages/assembleReport/assembleReport",
"style": {
"navigationBarTitleText": "装配报工"
}
},
{
"path": "pages/my/my",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "我的"
}
},
{
"path": "pages/login/login",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "登录"
}
},
{
"path": "pages/password/password",
"style": {
"navigationBarTitleText": "修改密码"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "",
"navigationBarBackgroundColor": "#E8EEF5",
"backgroundColor": "#E8EEF5"
},
// TabBar
"tabBar": {
"color": "#333",
"selectedColor": "#356899",
"backgroundColor": "#fff",
"borderStyle": "white",
"list": [{
"text": "工作台",
"pagePath": "pages/index/index",
"iconPath": "static/tabs/home_default.png",
"selectedIconPath": "static/tabs/home_selected.png"
},
{
"text": "我的",
"pagePath": "pages/my/my",
"iconPath": "static/tabs/user_default.png",
"selectedIconPath": "static/tabs/user_selected.png"
}
]
},
//
"preloadRule": {
}
}

@ -1,467 +0,0 @@
<script setup lang="ts">
import { toRaw, ref } from 'vue'
import { formatDate } from '@/utils/index'
import { onLoad } from '@dcloudio/uni-app'
import { useLoginStore } from '@/stores/modules/login'
import {
getApproveOrderDetailAPI,
getDictAPI,
postOperateAPI,
getChildProductAPI,
getFileAPI,
getLogAPI,
} from '@/services/approveOrder'
const popup = ref<UniHelper.UniPopupInstance>()
// porps
const props = defineProps<{
id: string
}>()
//
const queryParams: Required<any> = {
id: props.id,
}
const userStore = useLoginStore()
const dictInfo = userStore.dictInfo
const propertyDictData = dictInfo.filter(e => e.dictType == 'biz_project_property') || []
const lineDictData = dictInfo.filter(e => e.dictType == 'biz_business_line') || []
const fileDictData = dictInfo.filter(e => e.dictType == 'biz_business_file_type') || []
const LogDictData = dictInfo.filter(e => e.dictType == 'system_operate_type') || []
//
const detailInfo = ref({})
let orderTimeStr = ''
let projectStartTimeStr = ''
let projectEndTimeStr = ''
let businessLineStr = ''
let propertyStr = ''
let isLoading = ref(true)
const getData = async () => {
//
// isLoading.value = true
const data = await getApproveOrderDetailAPI(queryParams)
orderTimeStr = formatDate(data.orderTime)
projectStartTimeStr = formatDate(data.projectStartTime)
projectEndTimeStr = formatDate(data.projectEndTime)
const obj = propertyDictData.find((q) => q.value == data.property) || {}
propertyStr = obj?.label
const lineObj = lineDictData.find((q) => q.value == data.businessLine) || {}
businessLineStr = lineObj?.label
detailInfo.value = data || {}
isLoading.value = false
}
//
let childTableData = []
const getChildProductData = async () => {
const params = {
projectOrderId: props.id,
}
const data = await getChildProductAPI(params)
childTableData = data
}
//
let fileTableData = []
const getFileData = async () => {
const params = {
pageNo: 1,
pageSize: 100,
businessType: 'PROJECT_ORDER',
businessId: props.id,
}
const data = await getFileAPI(params)
data.list.forEach((e) => {
const obj = fileDictData.find((q) => q.value == e.businessFileType) || {}
e.businessFileType = obj?.label
e.createTime = formatDate(e.createTime)
})
fileTableData = data.list
}
//
let logTableData = []
const getLogData = async () => {
const params = {
pageNo: 1,
pageSize: 100,
businessType: 'PROJECT_ORDER',
businessId: props.id,
}
const data = await getLogAPI(params)
data.list.forEach((e) => {
const obj = LogDictData.find((q) => q.value == e.type) || {}
e.type = obj?.label
e.startTime = formatDate(e.startTime)
})
logTableData = data.list
}
onLoad(async () => {
await getChildProductData()
await getFileData()
await getLogData()
await getData()
})
const handleCancle = () => {
uni.navigateBack()
isShowPop.value = false
}
//
const handleStop = async () => {
const params = {
...detailInfo.value,
active: 'TERMINATE',
}
const data = await postOperateAPI(params)
const url = `/pages/approveOrder/approveOrder?state=32,64`
uni.navigateTo({
url,
})
// uni.showToast({ icon: 'success', title: '' })
}
//
const handleAgree = async () => {
const params = {
...detailInfo.value,
active: 'APPROVE',
}
const data = await postOperateAPI(params)
const url = `/pages/approveOrder/approveOrder?state=32,64`
uni.navigateTo({
url,
})
// uni.showToast({ icon: 'success', title: '' })
}
const dialogInputConfirm = async (val: any) => {
console.log(val)
const params = {
...detailInfo.value,
active: 'REPULSE',
activeOpinion: val
}
const data = await postOperateAPI(params)
handleCancle()
}
const isShowPop = ref(false)
//
const handleBack = () => {
popup.value?.open()
setTimeout(() => {
isShowPop.value = true
}, 0);
}
//
const openReport = (url: any) => {
uni.showLoading({
title: '加载中',
mask: true,
})
wx.downloadFile({
url: url,
success: function (res) {
console.log(res)
uni.hideLoading()
var filePath = res.tempFilePath
uni.showLoading({
title: '正在打开',
mask: true,
})
wx.openDocument({
filePath: filePath,
fileType: 'pdf',
success: function (res) {
console.log(res)
uni.hideLoading()
console.log('打开文档成功')
},
fail: function (err) {
uni.hideLoading()
console.log('fail:' + JSON.stringify(err))
},
})
},
fail: function (err) {
uni.hideLoading()
console.log('fail:' + JSON.stringify(err))
},
})
}
//
const handleDownload = (pdfUrl: any) => {
if (pdfUrl) {
switch (uni.getSystemInfoSync().platform) {
case 'android':
console.log('安卓')
//
openReport(pdfUrl)
break
case 'ios':
console.log('IOS')
//web-view
uni.navigateTo({
url: '/pages/previewPdf/previewPdf?url=' + pdfUrl,
})
break
default:
openReport(pdfUrl)
break
}
} else {
uni.showToast({
title: '暂未上传合同扫描件',
icon: 'none',
duration: 2000,
})
}
}
</script>
<template>
<view class="data-detail">
<template v-if="!isLoading">
<view class="hd">
<view class="num">项目编号</view>
<view class="statusLabel"> 编号{{ detailInfo.code }} </view>
</view>
<view class="md">
<view class="product-item">项目名称{{ detailInfo.projectName }}</view>
<view class="product-item">客户名称{{ detailInfo.customerName }}</view>
<view class="product-item">订单日期{{ orderTimeStr }}</view>
<view class="product-item">起止日期{{ projectStartTimeStr }} - {{ projectEndTimeStr }}</view>
<view class="product-item">合同号{{ detailInfo.contractNo }}</view>
<view class="product-item">所属业务线{{ businessLineStr }}</view>
<view class="product-item">性质{{ propertyStr }}</view>
<view class="product-item">提出部门{{ detailInfo.businessDeptName }}</view>
<view class="product-item">是否紧急{{ detailInfo.isUrgency ? '是' : '否' }}</view>
<view class="product-item">有无合同{{ detailInfo.hasContract ? '是' : '无' }}</view>
<view class="product-item">有无技术协议{{ detailInfo.hasTechnologyProtocol ? '是' : '无' }}</view>
<view class="product-item">有无图纸数模{{ detailInfo.hasBlueprint ? '是' : '无' }}</view>
<view class="product-item">可引用的原有技术{{ detailInfo.referenceTechnology }}</view>
<view class="product-item">检验要求{{ detailInfo.qualityRequirement }}</view>
<view class="product-item">备注{{ detailInfo.remark }}</view>
</view>
<view class="md foot">
<view class="foot-item price" v-if="detailInfo.hasPrice">{{ detailInfo.price }}</view>
<view class="foot-item">业务员{{ detailInfo.businessManName }}</view>
<view class="foot-item">是否已变更{{ detailInfo.hasAlter ? '是' : '否' }}</view>
</view>
<view class="table">
<view class="table-title"><span class="line"></span>子项目信息</view>
<uni-table ref="table" class="table-cont" :loading="loading" stripe emptyText="暂无更多数据"
@selection-change="selectionChange">
<uni-tr>
<uni-th>序号</uni-th>
<uni-th>子项目名称</uni-th>
<uni-th>设备型号</uni-th>
<uni-th>数量</uni-th>
<uni-th>单位</uni-th>
<uni-th>材质</uni-th>
<uni-th>备注</uni-th>
</uni-tr>
<uni-tr v-for="(item, index) in childTableData" :key="index">
<uni-td>{{ index }}</uni-td>
<uni-td>{{ item.name }}</uni-td>
<uni-td>{{ item.deviceName }}</uni-td>
<uni-td>{{ item.amount }}</uni-td>
<uni-td>{{ item.unit }}</uni-td>
<uni-td>{{ item.compositionName }}</uni-td>
<uni-td>{{ item.remark }}</uni-td>
</uni-tr>
</uni-table>
</view>
<view class="table">
<view class="table-title"><span class="line"></span>附件信息</view>
<uni-table ref="table" class="table-cont" :loading="loading" stripe emptyText="暂无更多数据"
@selection-change="selectionChange">
<uni-tr>
<uni-th>文件名称</uni-th>
<uni-th>文件类型</uni-th>
<uni-th>上传日期</uni-th>
<uni-th>操作</uni-th>
</uni-tr>
<uni-tr v-for="(item, index) in fileTableData" :key="index">
<uni-td>{{ item.name }}</uni-td>
<uni-td>{{ item.businessFileType }}</uni-td>
<uni-td>{{ item.createTime }}</uni-td>
<uni-td>
<view class="button" @click="handleDownload(item.url)" size="mini" type="primary">下载</view>
</uni-td>
</uni-tr>
</uni-table>
</view>
<view class="table">
<view class="table-title"><span class="line"></span>操作日志</view>
<uni-table ref="table" class="table-cont" :loading="loading" stripe emptyText="暂无更多数据"
@selection-change="selectionChange">
<uni-tr>
<uni-th>操作</uni-th>
<uni-th>操作人</uni-th>
<uni-th>操作时间</uni-th>
</uni-tr>
<uni-tr v-for="(item, index) in logTableData" :key="index">
<uni-td>{{ item.type }}</uni-td>
<uni-td>{{ item.name }}</uni-td>
<uni-td>{{ item.startTime }}</uni-td>
</uni-tr>
</uni-table>
</view>
<view class="action">
<view class="action-item cancle" @click="handleCancle"></view>
<template v-if="detailInfo.orderStatus == 16">
<view class="action-item agree" @click="handleAgree"></view>
<view class="action-item back" @click="handleBack"></view>
</template>
<template v-else>
<view class="action-item stop" v-if="detailInfo.orderStatus == 32" @click="handleStop"></view>
</template>
</view>
</template>
<view class="loading-text" v-else>..</view>
<uni-popup ref="popup" type="dialog">
<uni-popup-dialog v-if="isShowPop" ref="inputClose" mode="input" title="打回订单" placeholder="请输入打回原因"
@confirm="dialogInputConfirm"></uni-popup-dialog>
</uni-popup>
</view>
</template>
<style lang="scss">
//
.data-detail {
padding: 20rpx 0;
margin: 20rpx 20rpx;
border-radius: 10rpx;
background-color: #fff;
padding-bottom: 200rpx;
.hd {
padding: 10rpx;
font-size: 28rpx;
display: flex;
border-bottom: 2rpx solid #F2F2F2;
.statusLabel {
font-size: 24rpx;
color: #737D88;
}
}
.md {
padding: 10rpx;
min-height: 100rpx;
font-size: 28rpx;
border-bottom: 2rpx solid #F2F2F2;
.product-item {
margin: 20rpx 0;
display: flex;
align-items: center;
color: #737D88
}
&.foot {
display: flex;
flex-direction: column;
align-items: flex-end;
padding: 20rpx 30rpx;
.foot-item {
text-align: right;
margin: 10rpx 0;
display: flex;
align-items: center;
color: #737D88;
&.price {
font-weight: 600;
color: #1D2129;
}
}
}
}
.table {
padding: 20rpx 20rpx;
margin: 20rpx 0;
box-shadow: 0px 0px 8px 0px rgba(161, 161, 177, 0.12);
.table-title {
color: #0D0D26;
font-size: 36rpx;
margin: 20rpx 0;
font-weight: 500;
padding-bottom: 10rpx;
border-bottom: 2rpx solid #F2F2F2;
.line {
width: 10rpx;
height: 30rpx;
display: inline-block;
background-color: #356899;
margin-right: 10rpx;
}
}
.table-cont {
font-size: 24rpx;
}
.button {
color: #356899;
}
}
.action {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
bottom: 60rpx;
border-radius: 18rpx;
padding: 30rpx 30rpx;
background: #FFFFFF;
margin: 0 auto;
width: 600rpx;
transform: translateX(10%);
box-shadow: 0px -4px 10px 0px rgba(121, 153, 183, 0.2);
.action-item {
width: 180rpx;
height: 60rpx;
display: flex;
justify-content: center;
align-items: center;
margin: 0 20rpx;
border-radius: 60rpx;
border: 1rpx solid #ccc;
font-size: 26rpx;
color: #444;
&.cancle {
color: #356899;
}
&.agree {
color: #fff;
background: linear-gradient(167deg, #2EACE6 -41%, #356899 111%);
}
&.stop {
color: #fff;
background: linear-gradient(168deg, #FFB59C -12%, #FF3636 101%);
}
&.back {
color: #fff;
background: linear-gradient(173deg, #FEA97B -25%, #F75E40 108%);
}
}
}
.loading-text {
text-align: center;
font-size: 28rpx;
color: #666;
padding: 20rpx 0;
}
}
</style>

@ -1,163 +0,0 @@
<script setup lang="ts">
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import dataItem from './components/dataItem.vue'
import noticeItem from './components/noticeItem.vue'
// porps
const props = defineProps<{
state: string
}>()
// tabs
const orderTabs = ref([
{ orderState: '16', title: '待处理', isRender: false },
{ orderState: '32,64', title: '已处理', isRender: false },
])
const defaultState = props.state || '16'
console.log(defaultState)
//
const activeIndex = ref(0)
const handleIndexChange = (index: any) => {
orderTabs.value.forEach((e) => {
e.isRender = false
})
activeIndex.value = index
orderTabs.value[index].isRender = true
}
onLoad(async (options) => {
if (options.state) {
//
orderTabs.value.forEach((e, index) => {
e.isRender = e.orderState == options.state
if (e.isRender) {
activeIndex.value = index
}
})
} else {
orderTabs.value.forEach((e, index) => {
e.isRender = e.orderState == '16'
if (e.isRender) {
activeIndex.value = index
}
})
}
})
</script>
<template>
<view class="viewport">
<view class="tabs">
<text
class="item"
:class="{ active: activeIndex == index }"
v-for="(item, index) in orderTabs"
:key="item.title"
@tap="handleIndexChange(index)"
>
{{ item.title }}
</text>
<!-- 游标 -->
<view class="cursor" :style="{ left: activeIndex ? '65%' : '14%' }"></view>
</view>
<!-- 滑动容器 -->
<swiper
class="swiper"
:current="activeIndex"
@change="handleIndexChange($event.detail.current)"
>
<!-- 滑动项 -->
<swiper-item v-for="item in orderTabs" :key="item.title">
<dataItem v-if="item.isRender" :order-state="item.orderState" />
</swiper-item>
</swiper>
</view>
</template>
<style lang="scss">
page {
height: 100%;
}
.viewport {
height: 100%;
display: flex;
flex-direction: column;
// background-color: #3775F6;
.navbar {
width: 750rpx;
color: #000;
position: fixed;
top: 0;
left: 0;
z-index: 9;
/* background-color: #f8f8f8; */
background-color: #3775f6;
.wrap {
position: relative;
background-color: #3775f6;
.title {
height: 44px;
display: flex;
justify-content: center;
align-items: center;
font-size: 32rpx;
/* color: #000; */
color: #fff;
}
.back {
position: absolute;
left: 0;
height: 44px;
width: 44px;
font-size: 44rpx;
display: flex;
align-items: center;
justify-content: center;
/* color: #000; */
color: #fff;
}
}
}
.tabs {
display: flex;
justify-content: space-around;
line-height: 60rpx;
position: relative;
z-index: 9;
width: 100%;
.item {
flex: 1;
text-align: center;
padding: 20rpx;
font-size: 28rpx;
color: #1D2129;
&.active {
color: #356899;
}
}
.cursor {
position: absolute;
left: 13%;
bottom: 0;
width: 20%;
height: 6rpx;
padding: 0 50rpx;
background-color: #356899;
/* 过渡效果 */
transition: all 0.4s;
}
}
// swiper
.swiper {
background-color: #f7f7f8;
}
}
</style>

@ -1,356 +0,0 @@
<script setup lang="ts">
import { onMounted, computed, ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { getApproveOrderAPI } from '@/services/approveOrder'
import { useLoginStore } from '@/stores/modules/login'
import { formatDate } from '@/utils/index'
const userStore = useLoginStore()
const dictInfo = userStore.dictInfo
const propertyDictData = dictInfo.filter(e => e.dictType == 'biz_project_property') || []
//
const isFinish = ref(false)
//
const isTriggered = ref(false)
// porps
const props = defineProps<{
orderState: string
}>()
const statusText = computed(() => {
const text = props.orderState == '16' ? '处理' : '查看'
return text
})
//
const isLoading = ref(false)
//
const queryParams: Required<any> = {
page: 1,
pageSize: 5,
orderStatusList: props.orderState,
isSnapshot: 0,
}
const dataList = ref([])
const getListData = async () => {
// 退
if (isLoading.value) return
if (isFinish.value === true) {
return uni.showToast({ icon: 'none', title: '没有更多数据~' })
}
isLoading.value = true
//
const data = await getApproveOrderAPI(queryParams)
isLoading.value = false
const biz_business_line = userStore.dictInfo.filter
data.list.forEach((e) => {
const obj = propertyDictData.find((q) => q.value == e.property) || {}
e.property = obj?.label
e.orderTime = formatDate(e.orderTime)
e.projectStartTime = formatDate(e.projectStartTime)
e.projectEndTime = formatDate(e.projectEndTime)
})
//
dataList.value.push(...data.list)
//
if (queryParams.page < data.totalPages) {
//
queryParams.page++
} else {
//
isFinish.value = true
}
}
onMounted(async () => {
await getListData()
})
const handleDetail = (id) => {
const url = `/pages/approveOrder/approveOrder-detail?id=${id}`
uni.navigateTo({ url })
}
//
const onRefresherrefresh = async () => {
//
isTriggered.value = true
//
queryParams.page = 1
dataList.value = []
isFinish.value = false
//
await getListData()
//
isTriggered.value = false
}
// const searchVal = ref('')
// const handleSearch = async () => {
// let dataListDefault = []
// const code = searchVal.value
// if (code) {
// dataListDefault = dataList.value
// dataList.value = dataList.value.filter((e) => {
// return e.code == code
// })
// } else {
// dataList.value = dataListDefault
// }
// }
</script>
<template>
<view class="cont">
<!-- <view class="search" v-if="dataList.length > 5">
<view class="title"></view>
<input class="uni-input" v-model="searchVal" @change="handleSearch" placeholder="根据编号搜索" />
</view> -->
<scroll-view enable-back-to-top scroll-y class="data-list" refresher-enabled :refresher-triggered="isTriggered"
@refresherrefresh="onRefresherrefresh" @scrolltolower="getListData">
<view class="item" v-for="item in dataList" :key="item.id" @click="handleDetail(item.id)">
<view class="hd">
<view class="num">项目编号</view>
<view class="statusLabel"> 编号{{ item.code }} </view>
</view>
<view class="md">
<view class="product-item">项目名称{{ item.projectName }}</view>
<view class="product-item">客户名称{{ item.customerName }}</view>
<view class="product-item">订单日期{{ item.orderTime }}</view>
<view class="product-item">性质{{ item.property }}</view>
<view class="product-item">业务员{{ item.businessManName }}</view>
<view class="product-item">预计生产日期{{ item.projectStartTime }} - {{ item.projectEndTime }}</view>
</view>
<view class="statusText">{{ statusText }}</view>
</view>
<!-- 底部提示文字 -->
<view class="loading-text" :style="{ paddingBottom: safeAreaInsets?.bottom + 'px' }">
{{ isFinish ? '没有更多数据~' : '正在加载...' }}
</view>
</scroll-view>
</view>
</template>
<style lang="scss">
//
.search {
padding: 4rpx;
width: 80%;
margin: 30rpx auto;
.uni-input {
border: 1px solid #D1D6DB;
height: 60rpx;
line-height: 60rpx;
padding: 4rpx 10rpx;
font-size: 32rpx;
border-radius: 6rpx;
}
}
.data-list {
height: 90vh;
.item {
position: relative;
padding: 20rpx 0;
margin: 20rpx 20rpx;
border-radius: 10rpx;
background-color: #fff;
.hd {
padding: 10rpx;
font-size: 28rpx;
display: flex;
.statusLabel {
font-size: 24rpx;
color: #737D88;
}
}
.md {
position: relative;
padding: 10rpx;
min-height: 100rpx;
font-size: 28rpx;
border-top: 2rpx solid #F2F2F2;
.product-item {
margin: 20rpx 0;
display: flex;
align-items: center;
color: #737D88
}
}
.statusText {
position: absolute;
right: 30rpx;
top: 100rpx;
border-radius: 10rpx;
font-size: 24rpx;
padding: 10rpx 20rpx;
border-radius: 10rpx;
font-size: 24rpx;
background: linear-gradient(149deg, #2DACE6 4%, #356899 98%);
color: #fff;
padding: 10rpx 20rpx;
}
&:last-child {
padding-bottom: 40rpx;
}
}
.status {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 28rpx;
color: #999;
margin-bottom: 15rpx;
.date {
color: #666;
flex: 1;
}
.primary {
color: #ff9240;
}
.icon-delete {
line-height: 1;
margin-left: 10rpx;
padding-left: 10rpx;
border-left: 1rpx solid #e3e3e3;
}
}
.goods {
display: flex;
margin-bottom: 20rpx;
.cover {
width: 170rpx;
height: 170rpx;
margin-right: 20rpx;
border-radius: 10rpx;
overflow: hidden;
position: relative;
.image {
width: 170rpx;
height: 170rpx;
}
}
.quantity {
position: absolute;
bottom: 0;
right: 0;
line-height: 1;
padding: 6rpx 4rpx 6rpx 8rpx;
font-size: 24rpx;
color: #fff;
border-radius: 10rpx 0 0 0;
background-color: rgba(0, 0, 0, 0.6);
}
.meta {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.name {
height: 80rpx;
font-size: 26rpx;
color: #444;
}
.type {
line-height: 1.8;
padding: 0 15rpx;
margin-top: 10rpx;
font-size: 24rpx;
align-self: flex-start;
border-radius: 4rpx;
color: #888;
background-color: #f7f7f8;
}
.more {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
font-size: 22rpx;
color: #333;
}
}
.payment {
display: flex;
justify-content: flex-end;
align-items: center;
line-height: 1;
padding: 20rpx 0;
text-align: right;
color: #999;
font-size: 28rpx;
border-bottom: 1rpx solid #eee;
.quantity {
font-size: 24rpx;
margin-right: 16rpx;
}
.amount {
color: #444;
margin-left: 6rpx;
}
.symbol {
font-size: 20rpx;
}
}
.action {
display: flex;
justify-content: flex-end;
align-items: center;
padding-top: 20rpx;
.button {
width: 180rpx;
height: 60rpx;
display: flex;
justify-content: center;
align-items: center;
margin-left: 20rpx;
border-radius: 60rpx;
border: 1rpx solid #ccc;
font-size: 26rpx;
color: #444;
}
.secondary {
color: #3775F6;
border-color: #3775F6;
}
.primary {
color: #fff;
background-color: #3775F6;
border-color: #3775F6;
}
}
.loading-text {
text-align: center;
font-size: 28rpx;
color: #666;
padding: 20rpx 0;
}
}
</style>import type { stringify } from 'querystring';

@ -1,426 +0,0 @@
<script setup lang="ts">
import { toRaw, ref, computed } from 'vue'
import { formatDate } from '@/utils/index'
import { onLoad, onShow } from '@dcloudio/uni-app'
import { useLoginStore } from '@/stores/modules/login'
import { getTaskRepotPageAPI, getTaskDetailAPI, postOperateAPI } from '@/services/productionReport'
const popup = ref<UniHelper.UniPopupInstance>()
const userStore = useLoginStore()
const dictInfo = userStore?.dictInfo || []
const unitDictData = dictInfo.filter(e => e.dictType == 'biz_material_unit') || []
const userId = userStore.userInfo.userId
const isShowStart = computed(() => {
let flag = true
if (historyList.value.length) {
const obj = historyList.value[0]
if (!obj?.endTime) {
flag = false
}
}
//
if (detailInfo.value.amount == detailInfo.value.totalReportAmount) {
flag = false
}
return flag
})
const isShowEnd = computed(() => {
let flag = true
if (historyList.value.length) {
const obj = historyList.value[0]
if (obj?.endTime) {
flag = false
}
} else {
flag = false
}
return flag
})
const isShowFinish = computed(() => {
let flag = false
flag = detailInfo.value.amount == detailInfo.value.totalReportAmount || false
return flag
})
const amount = ref(null)
const workTime = ref(null)
//
const detailInfo = ref({})
let isLoading = ref(false)
const historyList = ref([])
//
const getData = async () => {
//
// isLoading.value = true
const params = {
pageNo: 1,
integerpageSize: 5,
owner: userId,
dispatchDetailId: detailInfo.value.id,
}
const data = await getTaskRepotPageAPI(params)
data.list.forEach((e) => {
e.startTime = e.startTime && formatDate(e.startTime, 'YYYY-MM-DD HH:mm')
e.endTime = e.endTime && formatDate(e.endTime, 'YYYY-MM-DD HH:mm')
})
historyList.value = data.list
isLoading.value = false
}
//
const getDetailData = async (id) => {
//
// isLoading.value = true
const params = {
id,
}
const data = await getTaskDetailAPI(params)
data.startTime = formatDate(data.startTime, 'YYYY-MM-DD')
data.endTime = formatDate(data.endTime, 'YYYY-MM-DD')
//
const lineObj = unitDictData.find((q) => q.value == data.unit) || {}
data.unit = lineObj.label
detailInfo.value = data || {}
isLoading.value = false
}
onLoad(async (options: any) => {
await getDetailData(options.id)
await getData()
const obj = historyList.value[0]
//
if (obj && obj?.workTime == null && obj.endTime) {
popup.value?.open()
}
})
//
const handleComplate = async () => {
const params = {
id: detailInfo.value?.id,
active: 'FINISH',
}
const data = await postOperateAPI(params)
const url = `/pages/productionReport/productionReport-detail?id=${detailInfo.value.id}`
uni.redirectTo({
url,
})
}
//
const handleOk = async (active) => {
const params = {
id: detailInfo.value?.id,
active: 'SUBMIT',
amount: amount.value,
workTime: workTime.value,
}
const data = await postOperateAPI(params)
const url = `/pages/productionReport/productionReport-detail?id=${detailInfo.value.id}`
uni.redirectTo({
url,
})
}
//
const handleStart = async () => {
const params = {
id: detailInfo.value.id,
active: 'START',
}
const data = await postOperateAPI(params)
const url = `/pages/productionReport/productionReport-detail?id=${detailInfo.value.id}`
uni.redirectTo({
url,
})
}
//
const handleStop = async () => {
const params = {
id: detailInfo.value?.id,
active: 'END',
}
const data = await postOperateAPI(params)
const url = `/pages/productionReport/productionReport-detail?id=${detailInfo.value.id}`
uni.redirectTo({
url,
})
popup.value?.open()
}
</script>
<template>
<view class="data-detail">
<template v-if="!isLoading">
<view class="module">
<view class="module-info">
<view class="product-item">项目{{ detailInfo.dispatchCode }} {{ detailInfo.projectName }}</view>
<image src="/static/images/productionReport-page.png" class="product-img" mode="scaleToFill"></image>
<view class="product-status">{{ detailInfo.procedureStatus == 2 ? '已完成' : '未完成' }}</view>
<view class="product-item">子项目{{ detailInfo.projectSubName }}</view>
<view class="product-item">零件名称{{ detailInfo.materialName }}</view>
<view class="product-item">派工工序{{ detailInfo.procedureName }}</view>
<view class="product-item">派工数量{{ detailInfo.amount }}</view>
<view class="product-item">总报工数量{{ detailInfo.totalReportAmount }}</view>
<view class="product-item">预计工时{{ detailInfo.workTime }}</view>
<view class="product-item">总报工工时{{ detailInfo.totalWorkTime }}</view>
<view class="product-item">预计生产日期{{ detailInfo.startTime }} {{ detailInfo.endTime }}</view>
<!-- <view class="finish" v-if="isShowStart" @click="handleComplate"></view> -->
</view>
</view>
<view class="module-list">
<view class="module-title">历史报工明细</view>
<view class="history-list">
<view class="no-data" v-if="!historyList.length">
无数据...
</view>
<template v-else>
<view class="item" v-for="item in historyList" :key="item.id">
<view class="product-item">生产开始时间{{ item.startTime }}</view>
<view class="product-item">生产结束时间{{ item.endTime }}</view>
<view class="product-item">报工工时{{ item.workTime }}</view>
<view class="product-item">报工数量{{ item.amount }}</view>
</view>
</template>
</view>
</view>
<view class="action" v-if="detailInfo.procedureStatus !== 2">
<view class="action-item start" v-if="isShowStart" @click="handleStart"></view>
<view class="action-item stop" v-if="isShowEnd" @click="handleStop"></view>
<view class="action-item finish" v-if="isShowFinish" @click="handleComplate"></view>
</view>
</template>
<view class="loading-text" v-else>..</view>
<uni-popup class="popup" ref="popup" :mask-click="false" type="bottom" background-color="#fff">
<view class="title">
<view class="text">填写信息</view>
<!-- <view class="close" @click="handleClose">X</view> -->
</view>
<view class="cont">
<view class="item">
<view class="label">开始生产时间</view>
<view class="val">{{ detailInfo.startTime }}</view>
</view>
<view class="item">
<view class="label">结束生产时间</view>
<view class="val">{{ detailInfo.endTime }}</view>
</view>
<view class="item">
<view class="label"><span class="star">*</span>本次报工工时</view>
<uni-easyinput class="val" type="number" v-model="amount" placeholder="请输入本次报工工时"></uni-easyinput>
<view class="unit">小时</view>
</view>
<view class="item">
<view class="label"><span class="star">*</span>本次报工数量</view>
<uni-easyinput class="val" type="number" v-model="workTime" placeholder="请输入本次报工数量"></uni-easyinput>
<view class="unit"> {{ detailInfo.unit }}</view>
</view>
</view>
<view class="ok" @click="handleOk"></view>
</uni-popup>
</view>
</template>
<style lang="scss">
//
.data-detail {
border-radius: 10rpx;
padding-bottom: 200rpx;
.module {
background: linear-gradient(178deg, #356899 7%, #356899 57%, #F4F6F9 94%);
padding: 20rpx;
.module-info {
padding: 20rpx 20rpx 60rpx;
border-radius: 10rpx;
min-height: 100rpx;
font-size: 28rpx;
border-bottom: 2rpx solid #F2F2F2;
background: linear-gradient(215deg, #C7D3E5 8%, rgba(222, 228, 236, 0) 13%), linear-gradient(162deg, #FFFFFF 25%, #E4EFFD 106%);
position: relative;
.product-img {
position: absolute;
right: 0rpx;
top: 0;
width: 100rpx;
height: 100rpx;
}
.product-status {
background: #FFF7E8;
color: #FF7D00;
width: 140rpx;
border-raduis: 10rpx;
text-align: center;
padding: 8rpx 12rpx;
}
.product-item {
margin: 20rpx 0;
display: flex;
align-items: center;
color: #737D88
}
}
}
.module-list {
padding: 20rpx 20rpx;
box-shadow: 0px 0px 8px 0px rgba(161, 161, 177, 0.12);
.module-title {
color: #0D0D26;
font-size: 36rpx;
margin: 20rpx 0;
font-weight: 500;
}
.history-list {
display: flex;
flex-direction: column;
align-items: center;
min-height: 200rpx;
justify-content: center;
margin: 20rpx 0;
padding: 20rpx 10rpx;
.item {
margin: 20rpx 0;
background: #EAEEF4;
font-size: 28rpx;
padding: 20rpx;
width: 100%;
border-radius: 10rpx;
color: #737D88;
.product-item {
margin: 10rpx 0;
}
}
.no-data {
font-size: 28rpx;
color: #444;
}
}
.table-cont {
font-size: 24rpx;
}
.button {
color: #356899;
}
}
.action {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
bottom: 60rpx;
border-radius: 18rpx;
padding: 30rpx 30rpx;
background: #FFFFFF;
margin: 0 auto;
width: 100vw;
box-shadow: 0px -4px 10px 0px rgba(121, 153, 183, 0.2);
.action-item {
width: 272rpx;
height: 86rpx;
display: flex;
justify-content: center;
align-items: center;
margin: 0 20rpx;
font-size: 26rpx;
color: #fff;
width: 272rpx;
height: 86rpx;
border-radius: 24rpx;
&.start {
background: linear-gradient(157deg, #2EACE6 -3%, #356899 90%);
}
&.stop {
background: linear-gradient(167deg, #FEA97B -2%, #F75E40 87%);
}
&.finish {
background: linear-gradient(142deg, #FEB34A 14%, #FE9B12 83%);
}
}
}
.loading-text {
text-align: center;
font-size: 28rpx;
color: #666;
padding: 20rpx 0;
}
.popup {
height: 80vh;
.title {
line-height: 1;
padding: 40rpx;
font-size: 32rpx;
font-weight: normal;
border-bottom: 1rpx solid #ddd;
color: #444;
.close {
position: absolute;
right: 24rpx;
top: 40rpx;
height: 60rpx;
width: 60rpx;
text-align: center;
}
}
.cont {
display: flex;
flex-direction: column;
align-items: center;
margin: 40rpx;
.item {
display: flex;
align-items: center;
margin: 10rpx 0;
color: #737D88;
font-size: 24rpx;
width: 94%;
.label {
width: 200rpx;
.star {
color: red
}
}
.val {
flex: 1
}
.unit {
width: 100rpx;
margin-left: 15rpx;
text-align: center;
}
}
}
.ok {
font-size: 28rpx;
margin: 20rpx auto;
text-align: center;
width: 140rpx;
border-radius: 10rpx;
padding: 8rpx 0;
background-color: #3C8AF7;
color: #fff;
}
}
}
</style>

@ -1,151 +0,0 @@
<script setup lang="ts">
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import dataItem from './components/dataItem.vue'
// porps
const props = defineProps<{
state: string
}>()
// tabs
const orderTabs = ref([
{ orderState: '0,1', title: '未完成', isRender: false },
{ orderState: '2', title: '已完成', isRender: false },
])
//
const activeIndex = ref(0)
const handleIndexChange = (index: any) => {
orderTabs.value.forEach((e) => {
e.isRender = false
})
activeIndex.value = index
orderTabs.value[index].isRender = true
}
onLoad(async (options) => {
if (options.state) {
//
orderTabs.value.forEach((e, index) => {
e.isRender = e.orderState == options.state
if (e.isRender) {
activeIndex.value = index
}
})
} else {
orderTabs.value.forEach((e, index) => {
e.isRender = e.orderState == '0,1'
if (e.isRender) {
activeIndex.value = index
}
})
}
})
</script>
<template>
<view class="viewport">
<view class="tabs">
<text class="item" :class="{ active: activeIndex == index }" v-for="(item, index) in orderTabs" :key="item.title"
@tap="handleIndexChange(index)">
{{ item.title }}
</text>
<!-- 游标 -->
<view class="cursor" :style="{ left: activeIndex ? '65%' : '14%' }"></view>
</view>
<!-- 滑动容器 -->
<swiper class="swiper" :current="activeIndex" @change="handleIndexChange($event.detail.current)">
<!-- 滑动项 -->
<swiper-item v-for="item in orderTabs" :key="item.title">
<dataItem v-if="item.isRender" :order-state="item.orderState" />
</swiper-item>
</swiper>
</view>
</template>
<style lang="scss">
page {
height: 100%;
}
.viewport {
height: 100%;
display: flex;
flex-direction: column;
// background-color: #3775F6;
.navbar {
width: 750rpx;
color: #000;
position: fixed;
top: 0;
left: 0;
z-index: 9;
/* background-color: #f8f8f8; */
background-color: #3775f6;
.wrap {
position: relative;
background-color: #3775f6;
.title {
height: 44px;
display: flex;
justify-content: center;
align-items: center;
font-size: 32rpx;
/* color: #000; */
color: #fff;
}
.back {
position: absolute;
left: 0;
height: 44px;
width: 44px;
font-size: 44rpx;
display: flex;
align-items: center;
justify-content: center;
/* color: #000; */
color: #fff;
}
}
}
.tabs {
display: flex;
justify-content: space-around;
line-height: 60rpx;
position: relative;
z-index: 9;
width: 100%;
.item {
flex: 1;
text-align: center;
padding: 20rpx;
font-size: 28rpx;
color: #1D2129;
&.active {
color: #356899;
}
}
.cursor {
position: absolute;
left: 13%;
bottom: 0;
width: 20%;
height: 6rpx;
padding: 0 50rpx;
background-color: #356899;
/* 过渡效果 */
transition: all 0.4s;
}
}
// swiper
.swiper {
background-color: #f7f7f8;
}
}
</style>

@ -1,365 +0,0 @@
<script setup lang="ts">
import { onMounted, computed, ref } from 'vue'
import { onLoad, onShow } from '@dcloudio/uni-app'
import { getListAPI, getDictAPI } from '@/services/productionReport'
import { useLoginStore } from '@/stores/modules/login'
import { formatDate } from '@/utils/index'
const userStore = useLoginStore()
const userId = userStore.userInfo.userId
//
const isFinish = ref(false)
//
const isTriggered = ref(false)
// porps
const props = defineProps<{
orderState: string
}>()
const statusText = computed(() => {
const text = props.orderState == '0,1' ? '处理' : '查看'
return text
})
//
const isLoading = ref(false)
//
const queryParams: Required<any> = {
page: 1,
pageSize: 5,
owner: userId, //
procedureStatusList: props.orderState, //
dispatchType: 'ASSEMBLE', //
isReport: 1, //
}
const dataList = ref([])
const getListData = async () => {
// 退
if (isLoading.value) return
if (isFinish.value === true) {
return uni.showToast({ icon: 'none', title: '没有更多数据~' })
}
isLoading.value = true
//
const data = await getListAPI(queryParams)
isLoading.value = false
data.list.forEach((e) => {
e.orderTime = formatDate(e.orderTime, 'YYYY-MM-DD')
e.startTime = formatDate(e.startTime, 'YYYY-MM-DD')
e.endTime = formatDate(e.endTime, 'YYYY-MM-DD')
})
//
dataList.value.push(...data.list)
//
if (queryParams.page < data.totalPages) {
//
queryParams.page++
} else {
//
isFinish.value = true
}
}
onMounted(async () => {
await getListData()
})
onShow(async () => {
isFinish.value = false
isLoading.value = false
queryParams.pageNo = 1
dataList.value = []
await getListData()
})
const handleDetail = (item) => {
const url = `/pages/productionReport/productionReport-detail?id=${item.id}`
uni.navigateTo({ url })
}
//
const onRefresherrefresh = async () => {
//
isTriggered.value = true
//
queryParams.page = 1
dataList.value = []
isFinish.value = false
//
await getListData()
//
isTriggered.value = false
}
// const searchVal = ref('')
// const dataListDefault = ref([])
// const handleSearch = async () => {
// const code = searchVal.value
// if (code) {
// dataListDefault.value = dataList.value
// dataList.value = dataList.value.filter((e) => {
// return e.code == code
// })
// } else {
// dataList.value = dataListDefault.value
// }
// }
</script>
<template>
<view class="cont">
<!-- <view class="search" v-if="dataList.length > 5">
<view class="title"></view>
<input class="uni-input" v-model="searchVal" @change="handleSearch" placeholder="根据编号搜索" />
</view> -->
<scroll-view enable-back-to-top scroll-y class="data-list" refresher-enabled :refresher-triggered="isTriggered"
@refresherrefresh="onRefresherrefresh" @scrolltolower="getListData">
<view class="item" v-for="item in dataList" :key="item.id" @click="handleDetail(item)">
<view class="hd">
<view class="num">派工单</view>
<view class="statusLabel"> 单号{{ item.dispatchCode }} </view>
</view>
<view class="md">
<view class="product-item">项目名称{{ item.projectCode + ' ' + item.projectName }}</view>
<view class="product-item">子项目{{ item.projectSubCode || '' }} {{' ' + item.projectSubName }}</view>
<view class="product-item">零件名称{{ item.materialName }}</view>
<view class="product-item">派工工序{{ item.procedureName }}</view>
<view class="product-item">派工数量{{ item.amount }}</view>
<view class="product-item">总报工数量{{ item.totalReportAmount }}</view>
<view class="product-item">预计工时{{ item.workTime }}</view>
<view class="product-item">总报工工时{{ item.totalWorkTime }}</view>
<view class="product-item">预计生产日期{{ item.startTime }} {{ item.endTime }}</view>
</view>
<view class="statusText">{{ statusText }}</view>
</view>
<!-- 底部提示文字 -->
<view class="loading-text" :style="{ paddingBottom: safeAreaInsets?.bottom + 'px' }">
{{ isFinish ? '没有更多数据~' : '正在加载...' }}
</view>
</scroll-view>
</view>
</template>
<style lang="scss">
//
.search {
padding: 4rpx;
width: 80%;
margin: 30rpx auto;
.uni-input {
border: 1px solid #D1D6DB;
height: 60rpx;
line-height: 60rpx;
padding: 4rpx 10rpx;
font-size: 32rpx;
border-radius: 6rpx;
}
}
.data-list {
height: 90vh;
.item {
position: relative;
padding: 20rpx 0;
margin: 20rpx 20rpx;
border-radius: 10rpx;
background-color: #fff;
.hd {
padding: 10rpx;
font-size: 28rpx;
display: flex;
.statusLabel {
font-size: 24rpx;
color: #737D88;
}
}
.md {
position: relative;
padding: 10rpx;
min-height: 100rpx;
font-size: 28rpx;
border-top: 2rpx solid #F2F2F2;
.product-item {
margin: 20rpx 0;
display: flex;
align-items: center;
color: #737D88
}
}
.statusText {
position: absolute;
right: 30rpx;
top: 100rpx;
border-radius: 10rpx;
font-size: 24rpx;
padding: 10rpx 20rpx;
border-radius: 10rpx;
font-size: 24rpx;
background: linear-gradient(149deg, #2DACE6 4%, #356899 98%);
color: #fff;
padding: 10rpx 20rpx;
}
&:last-child {
padding-bottom: 40rpx;
}
}
.status {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 28rpx;
color: #999;
margin-bottom: 15rpx;
.date {
color: #666;
flex: 1;
}
.primary {
color: #ff9240;
}
.icon-delete {
line-height: 1;
margin-left: 10rpx;
padding-left: 10rpx;
border-left: 1rpx solid #e3e3e3;
}
}
.goods {
display: flex;
margin-bottom: 20rpx;
.cover {
width: 170rpx;
height: 170rpx;
margin-right: 20rpx;
border-radius: 10rpx;
overflow: hidden;
position: relative;
.image {
width: 170rpx;
height: 170rpx;
}
}
.quantity {
position: absolute;
bottom: 0;
right: 0;
line-height: 1;
padding: 6rpx 4rpx 6rpx 8rpx;
font-size: 24rpx;
color: #fff;
border-radius: 10rpx 0 0 0;
background-color: rgba(0, 0, 0, 0.6);
}
.meta {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.name {
height: 80rpx;
font-size: 26rpx;
color: #444;
}
.type {
line-height: 1.8;
padding: 0 15rpx;
margin-top: 10rpx;
font-size: 24rpx;
align-self: flex-start;
border-radius: 4rpx;
color: #888;
background-color: #f7f7f8;
}
.more {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
font-size: 22rpx;
color: #333;
}
}
.payment {
display: flex;
justify-content: flex-end;
align-items: center;
line-height: 1;
padding: 20rpx 0;
text-align: right;
color: #999;
font-size: 28rpx;
border-bottom: 1rpx solid #eee;
.quantity {
font-size: 24rpx;
margin-right: 16rpx;
}
.amount {
color: #444;
margin-left: 6rpx;
}
.symbol {
font-size: 20rpx;
}
}
.action {
display: flex;
justify-content: flex-end;
align-items: center;
padding-top: 20rpx;
.button {
width: 180rpx;
height: 60rpx;
display: flex;
justify-content: center;
align-items: center;
margin-left: 20rpx;
border-radius: 60rpx;
border: 1rpx solid #ccc;
font-size: 26rpx;
color: #444;
}
.secondary {
color: #3775F6;
border-color: #3775F6;
}
.primary {
color: #fff;
background-color: #3775F6;
border-color: #3775F6;
}
}
.loading-text {
text-align: center;
font-size: 28rpx;
color: #666;
padding: 20rpx 0;
}
}
</style>import type { stringify } from 'querystring';

@ -1,42 +0,0 @@
<!--
* @Author: 王文杰
* @Date: 2024-03-04 14:13:16
* @LastEditors: jevononlie 728254585@qq.com
* @LastEditTime: 2024-04-10 16:41:20
* @FilePath: /app-nx-personal/src/pages/index/components/CategoryPanel.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<script setup lang="ts">
import type { CategoryItem } from '@/types/home'
// props
defineProps<{
list: Object[]
}>()
const handleToBooking = (path: string) => {
const url = `/pages/${path}/${path}`
uni.navigateTo({
url,
})
}
</script>
<template>
<view class="category">
<template v-if="list.length">
<view class="category-item" hover-class="none" v-for="item in list" :key="item.path"
@click="handleToBooking(item.path)">
<image v-if="item.auth" class="icon" :src="item.imgUrl" mode="scaleToFill"></image>
<image v-else class="icon" :src="item.defaultImgUrl" mode="scaleToFill"></image>
</view>
</template>
<view v-else class="empty-data">
<image class="icon" src="/static/images/home-empty.png" mode="aspectFit"></image>
</view>
</view>
</template>
<style lang="scss">
@import '../styles/category.scss';
</style>

@ -1,92 +0,0 @@
<!--
* @Author: 王文杰
* @Date: 2024-03-04 14:13:16
* @LastEditors: 王文杰
* @LastEditTime: 2024-03-18 17:18:55
* @FilePath: /app-nx-personal/src/pages/index/components/CustomNavbar.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<script setup lang="ts">
//
const { safeAreaInsets } = uni.getSystemInfoSync()
</script>
<template>
<view class="navbar" :style="{ paddingTop: safeAreaInsets!.top + 10 + 'px' }">
<!-- logo文字 -->
<view class="logo">
<image class="logo-image" src="/static/images/logo.png" mode="'aspectFit'"></image>
<!-- <view class="logo-text">
<view class="logo-title">杭州合立</view>
<view class="logo-desc">HANGZHOU HRLI</view>
</view> -->
</view>
<!-- 搜索条 -->
<!-- <view class="search">
<text class="icon-search">搜索商品</text>
<text class="icon-scan"></text>
</view> -->
</view>
</template>
<style lang="scss" scoped>
/* 自定义导航条 */
.navbar {
background-size: cover;
background: #E8EEF5;
position: relative;
display: flex;
flex-direction: column;
padding-top: 20px;
.logo {
display: flex;
align-items: center;
height: 64rpx;
padding-left: 30rpx;
.logo-image {
width: 214rpx;
height: 80rpx;
}
.logo-text {
flex: 1;
line-height: 28rpx;
color: #3D3D3D;
margin: 2rpx 0 0 20rpx;
padding-left: 20rpx;
// border-left: 1rpx solid #fff;
font-size: 26rpx;
.logo-title {
font-size: 28rpx;
color: #3D3D3D;
font-weight: 600;
}
.logo-desc {
font-size: 16rpx;
color: #3D3D3D;
margin-top: 4rpx;
}
}
}
.search {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10rpx 0 26rpx;
height: 64rpx;
margin: 16rpx 20rpx;
color: #fff;
font-size: 28rpx;
border-radius: 32rpx;
background-color: rgba(255, 255, 255, 0.5);
}
.icon-search {
&::before {
margin-right: 10rpx;
}
}
.icon-scan {
font-size: 30rpx;
padding: 15rpx;
}
}
</style>

@ -1,51 +0,0 @@
<!--
此文件为开发者工具生成生成时间: 2024/4/8下午6:04:22
使用方法
/Users/wangwenjie/chanko/mes-biz/mes-ui/mini-app/dist/dev/mp-weixin/pages/index/index.wxml 引入模板
```
<import src="index.skeleton.wxml"/>
<template is="skeleton" wx:if="{{loading}}" />
```
/Users/wangwenjie/chanko/mes-biz/mes-ui/mini-app/dist/dev/mp-weixin/pages/index/index.wxss 中引入样式
```
@import "./index.skeleton.wxss";
```
更多详细信息可以参考文档https://developers.weixin.qq.com/miniprogram/dev/devtools/skeleton.html
-->
<template name="skeleton">
<view class="sk-container">
<view class="viewport viewport">
<view is="pages/index/components/CustomNavbar">
<view class="navbar CustomNavbar--navbar data-v-ff0d84a2 CustomNavbar--data-v-ff0d84a2" style="padding-top:57px">
<view class="logo CustomNavbar--logo data-v-ff0d84a2 CustomNavbar--data-v-ff0d84a2">
<image class="logo-image CustomNavbar--logo-image data-v-ff0d84a2 CustomNavbar--data-v-ff0d84a2 sk-image" mode="'aspectFit'"></image>
</view>
</view>
</view>
<view class="cont cont">
<view is="pages/index/components/CategoryPanel">
<view class="category CategoryPanel--category">
<view class="category-item CategoryPanel--category-item" hover-class="none">
<image class="icon CategoryPanel--icon sk-image" mode="aspectFit"></image>
</view>
<view class="category-item CategoryPanel--category-item" hover-class="none">
<image class="icon CategoryPanel--icon sk-image" mode="aspectFit"></image>
</view>
<view class="category-item CategoryPanel--category-item" hover-class="none">
<image class="icon CategoryPanel--icon sk-image" mode="aspectFit"></image>
</view>
<view class="category-item CategoryPanel--category-item" hover-class="none">
<image class="icon CategoryPanel--icon sk-image" mode="aspectFit"></image>
</view>
</view>
</view>
<view is="pages/index/components/footRight">
<view class="copy-right footRight--copy-right sk-transparent sk-text-14-2857-199 sk-text">Copyright ©上海长江云息数字科技有限公司,All Rights Reserved. 专注工业信息化-供应链解决方案</view>
</view>
</view>
</view>
</view>
</template>

@ -1,19 +0,0 @@
<script setup lang="ts">
//
</script>
<template>
<view class="copy-right">Copyright ©上海长江云息数字科技有限公司,All Rights Reserved. 专注工业信息化-供应链解决方案</view>
</template>
<style lang="scss">
.copy-right {
position: absolute;
left: 50%;
bottom: 50rpx;
width: 600rpx;
transform: translate(-50%, -50%);
text-align: center;
color: #B3BEC9;
font-size: 20rpx;
}
</style>

@ -1,111 +0,0 @@
<script setup lang="ts">
import { onLoad } from '@dcloudio/uni-app'
import { useLoginStore } from '@/stores/modules/login'
import { computed, ref, reactive } from 'vue'
import CustomNavbar from './components/CustomNavbar.vue'
import CategoryPanel from './components/CategoryPanel.vue'
import footRight from './components/footRight.vue'
import PageSkeleton from './components/PageSkeleton.vue'
import { getHomeCategoryAPI } from '@/services/home'
//
const categoryList = ref([
{
path: 'approveOrder',
name: '订单批准',
auth: false,
imgUrl: '/static/images/approveOrder.png',
defaultImgUrl: '/static/images/approveOrder-default.png',
},
{
path: 'unqualifiedNotification',
name: '品质异常通知',
auth: false,
imgUrl: '/static/images/unqualifiedNotification.png',
defaultImgUrl: '/static/images/unqualifiedNotification-default.png',
},
{
path: 'productionReport',
name: '生产报工',
auth: false,
imgUrl: '/static/images/productionReport.png',
defaultImgUrl: '/static/images/productionReport-default.png',
},
{
path: 'assembleReport',
name: '装配报工',
auth: false,
imgUrl: '/static/images/assembleReport.png',
defaultImgUrl: '/static/images/assembleReport-default.png',
},
])
const loginStore = useLoginStore()
const isLogin = computed(() => {
const accessToken = loginStore.userInfo?.accessToken
const storage_token = uni.getStorageSync('storage_userInfo')?.accessToken
return !!accessToken || !!storage_token
})
//
const isLoading = ref(false)
//
onLoad(async() => {
if (isLogin.value) {
await getHomeCategory()
} else {
categoryList.value.forEach((e) => {
e.auth = true
})
}
})
const getHomeCategory = async () => {
isLoading.value = true
const params = {}
const data = await getHomeCategoryAPI(params)
const menus = data?.menus.find((e) => e.path == '/applet')?.children || []
if (menus.length) {
const arr = []
categoryList.value.forEach((e) => {
const target = menus.find((q) => q.path == e.path)
e.auth = !!target
})
}
if (loginStore.userInfo.userId) {
const obj = {
...loginStore.userInfo,
nickname: data.user.nickname
}
loginStore.setInfo(obj)
}
isLoading.value = false
}
</script>
<template>
<view class="viewport">
<template v-if="isLoading">
<PageSkeleton />
</template>
<template v-else>
<CustomNavbar />
<view class="cont">
<CategoryPanel :list="categoryList" />
<footRight />
</view>
</template>
</view>
</template>
<style lang="scss">
page {
height: 100%;
overflow: hidden;
}
.viewport {
width: 100vw;
height: 100vh;
margin-bottom: 300rpx;
.cont {
//margin: 100rpx 0;
}
}
</style>

@ -1,30 +0,0 @@
.category {
padding: 32rpx 20rpx;
margin: 16rpx;
border-radius: 4rpx;
display: flex;
flex-wrap: wrap;
.category-item {
flex: 1;
border-radius: 16rpx;
margin: 12rpx 6rpx;
display: flex;
flex-direction: column;
justify-content: space-between; // flex-direction: row;
align-items: center;
box-sizing: border-box;
box-shadow: 0px 3px 12px 0px rgba(63, 112, 157, 0.5);
.icon {
width: 330rpx;
height: 240rpx;
}
}
.empty-data {
position: absolute;
left: 50%;
top: 50%;
width: 480rpx;
height: 528rpx;
transform: translate(-50%, -50%);
}
}

@ -1,33 +0,0 @@
.category {
padding: 32rpx 20rpx;
margin: 16rpx;
border-radius: 4rpx;
display: flex;
flex-wrap: wrap;
}
.category .category-item {
flex: 1;
border-radius: 16rpx;
margin: 12rpx 6rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
box-shadow: 0px 3px 12px 0px rgba(63, 112, 157, 0.5);
}
.category .category-item .icon {
width: 330rpx;
height: 240rpx;
}
.category .empty-data {
position: absolute;
left: 50%;
top: 50%;
width: 480rpx;
height: 528rpx;
transform: translate(-50%, -50%);
}

@ -1,196 +0,0 @@
<script setup lang="ts">
import { postLoginAPI, getDictAPI } from '@/services/login'
import { useLoginStore } from '@/stores/modules/login'
import type { LoginResult } from '@/types/login'
import { ref } from 'vue'
const loginStore = useLoginStore()
const formRef = ref<UniHelper.UniFormsInstance>()
//
const form = ref({
username: '',
password: '',
// username: 'biz000',
// password: '123456',
})
//
const rules: UniHelper.UniFormsRules = {
username: {
rules: [{ required: true, errorMessage: '请输入员工工号' }],
},
password: {
rules: [{ required: true, errorMessage: '请输入密码' }],
},
}
//
const isLoading = ref(false)
//
const onSubmit = async () => {
try {
// 退
if (isLoading.value) return
isLoading.value = true
//
await formRef.value?.validate?.()
//
const params = {
...form.value,
}
const res = await postLoginAPI(params)
isLoading.value = false
loginSuccess(res)
} catch (error) {
isLoading.value = false
console.log(error)
const msg = error?.data?.msg || '请填写完整信息'
uni.showToast({ icon: 'none', title: msg })
}
}
const loginSuccess = async (data: LoginResult) => {
//
loginStore.setInfo(data)
const dictArr = [
'biz_inspection_type,system_operate_type,biz_business_file_type,biz_project_order_status,biz_delivery_status,biz_business_line,biz_currency,biz_project_property, biz_material_unit','biz_unqualified_notification_opinion']
const params = {
dictTypeList: dictArr.join(','),
}
const resDict = await getDictAPI(params)
loginStore.setDict(resDict)
//
uni.showToast({ icon: 'success', title: '登录成功' })
setTimeout(() => {
//
uni.switchTab({ url: '/pages/index/index' })
// uni.navigateBack()
}, 500)
}
const handleForget = () => {
const url = '/pages/forget/forget'
uni.navigateTo({
url,
})
}
</script>
<template>
<view class="viewport">
<image src="/static/images/login-hd.png" class="hd" mode="'aspectFit'"></image>
<view class="md">
<view class="form-title">
<view class="title"> 用户登录 </view>
<view class="desc"> USER LOGIN </view>
</view>
<uni-forms :rules="rules" :model="form" ref="formRef">
<!-- 表单内容 -->
<uni-forms-item name="username" class="form-item">
<text class="label">员工工号</text>
<input class="input" placeholder="请填写员工工号" v-model="form.username" />
</uni-forms-item>
<uni-forms-item name="password" class="form-item">
<text class="label">登录密码</text>
<input
class="input"
placeholder="请填写登录密码"
:maxlength="11"
v-model="form.password"
/>
</uni-forms-item>
<!-- <view class="forget" @tap="handleForget"></view> -->
</uni-forms>
</view>
<view class="foot">
<view class="desc"> 请联系管理员获取工号和密码 </view>
<view class="copy-right">Copyright ©上海长江云息数字科技有限公司,All Rights Reserved. 专注工业信息化-供应链解决方案</view>
<view class="login" @tap="onSubmit"> </view>
</view>
</view>
</template>
<style lang="scss">
page {
height: 100%;
}
.viewport {
display: flex;
flex-direction: column;
height: 100%;
justify-content: space-between;
.hd {
height: 300rpx;
}
.md {
flex: 1;
padding: 80rpx 60rpx;
.form-title {
.title {
font-size: 48rpx;
}
.desc {
font-size: 28rpx;
color: #888888;
}
}
.uni-forms {
color: #888888;
margin: 80rpx 0 20rpx;
.form-item {
margin: 40rpx 0;
}
.label {
font-size: 32rpx;
}
.input {
background: #F5F7FA;
color: #595959;
font-size: 28rpx;
height: 80rpx;
line-height: 80rpx;
display: flex;
align-items: center;
padding: 0 20rpx;
margin-top: 20rpx;
border-radius: 8rpx;
}
.forget {
color: #356899;
font-size: 28rpx;
}
}
}
.foot {
.desc {
color: #888888;
text-align: center;
font-size: 32rpx;
margin: 20rpx 0;
}
.copy-right {
text-align: center;
color: #B3BEC9;
font-size: 20rpx;
margin: 20rpx 40rpx 60rpx;
}
.login {
font-size: 36rpx;
font-weight: 600;
background: #356899;
height: 120rpx;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
}
}
}
</style>

@ -1,231 +0,0 @@
<script setup lang="ts">
import { ref, reactive, computed } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { useLoginStore } from '@/stores/modules/login'
import { getUserInfoAPI } from '@/services/my'
import { postLogoutAPI } from '@/services/login'
import CustomNavbar from '../index/components/CustomNavbar.vue'
//
const { safeAreaInsets } = uni.getSystemInfoSync()
const userStore = useLoginStore()
const isLogin= computed(() => {
const accessToken = userStore.userInfo?.accessToken
const storage_token = uni.getStorageSync('login').userInfo?.accessToken
return accessToken || storage_token
})
const handleEdit = () => {
uni.navigateTo({ url: '/pages/password/password' })
}
const handleLogut = async () => {
const params = {}
const data = await postLogoutAPI(params)
userStore.clearInfo()
uni.clearStorage()
uni.navigateTo({ url: '/pages/login/login' })
}
onShow(async () => {
await getUserInfoData()
})
const isLoading = ref(false)
let userInfo = ref({})
const getUserInfoData = async () => {
isLoading.value = true
const userId = userStore.userInfo.userId
const params = {
id: userId,
}
const data = await getUserInfoAPI(params)
console.log(data)
const str = data.mobile || ''
data.mobile = str.substr(0, 3) + '****' + str.substr(7)
userInfo.value = data
isLoading.value = false
}
</script>
<template>
<view class="viewport">
<!-- 自定义导航栏 -->
<CustomNavbar />
<view class="profile">
<view class="overview" v-if="isLogin">
<navigator url="/pagesMember/profile/profile" hover-class="none">
<image class="avatar" :src="userInfo.avatar" mode="aspectFill"></image>
</navigator>
<view class="meta">
<view class="nickname">
{{ userInfo.nickname }}
</view>
<view class="mobile">
{{ userInfo.mobile }}
</view>
<!-- <navigator class="extra" url="/pagesMember/profile/profile" hover-class="none">
<text class="update">更新头像昵称</text>
</navigator> -->
</view>
</view>
<view class="overview" v-else>
<navigator url="/pages/login/login" hover-class="none">
<image class="avatar gray" mode="aspectFill" src="/static/images/my.avatar.png"></image>
</navigator>
<view class="meta">
<navigator url="/pages/login/login" hover-class="none" class="nickname">
未登录
</navigator>
<view class="extra">
<text class="tips">点击登录账号</text>
</view>
</view>
</view>
</view>
<view class="empty">
<image class="icon" src="/static/images/my-empty.png" mode="aspectFit"></image>
</view>
<view class="action" v-if="isLogin">
<view class="edit" @click="handleEdit"></view>
<view class="logout" @click="handleLogut">退</view>
</view>
<view class="foot">
<view class="copy-right">Copyright ©上海长江云息数字科技有限公司,All Rights Reserved. 专注工业信息化-供应链解决方案</view>
</view>
</view>
</template>
<style lang="scss">
page {
height: 100%;
overflow: hidden;
background: #F8FAFD;
}
.viewport {
position: relative;
height: 100%;
}
/* 用户信息 */
.profile {
position: relative;
padding-top: 50rpx;
.overview {
display: flex;
height: 120rpx;
padding: 0 36rpx;
color: #fff;
}
.avatar {
width: 120rpx;
height: 120rpx;
border-radius: 50%;
background-color: #eee;
}
.gray {
filter: grayscale(100%);
}
.meta {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
line-height: 30rpx;
padding: 16rpx 0;
margin-left: 20rpx;
.nickname,
.mobile {
max-width: 280rpx;
margin-bottom: 16rpx;
font-size: 30rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: #0D0D26;
}
.extra {
display: flex;
font-size: 20rpx;
color: #95969D;
}
}
.tips {
font-size: 22rpx;
}
.update {
padding: 3rpx 10rpx 1rpx;
color: rgba(255, 255, 255, 0.8);
border: 1rpx solid rgba(255, 255, 255, 0.8);
margin-right: 10rpx;
border-radius: 30rpx;
}
.settings {
position: absolute;
bottom: 0;
right: 40rpx;
font-size: 30rpx;
color: #fff;
}
}
.empty {
margin: 40rpx 0;
width: 750rpx;
height: 538rpx;
.icon {}
}
.action {
.edit {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: linear-gradient(157deg, #2EACE6 -3%, #356899 90%);
box-shadow: 0px 3px 12px 0px rgba(63, 112, 157, 0.5);
color: #fff;
padding: 20rpx 40rpx;
border: 2rpx solid #356899;
width: 400rpx;
margin: 0 auto;
border-radius: 10rpx;
font-weight: 600;
}
.logout {
width: 400rpx;
margin: 30rpx auto;
border-radius: 10rpx;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: #356899;
padding: 20rpx 40rpx;
border: 2rpx solid #356899;
font-weight: 600;
box-shadow: 0px 3px 12px 0px rgba(63, 112, 157, 0.5);
}
}
.foot {
margin-top: 120rpx;
.copy-right {
text-align: center;
color: #B3BEC9;
font-size: 20rpx;
margin: 30rpx 40rpx 60rpx;
}
}
</style>

@ -1,172 +0,0 @@
<script setup lang="ts">
import {
putUpdatePasswordAPI
} from '@/services/my'
import { onLoad, onReady } from '@dcloudio/uni-app'
import { ref, reactive } from 'vue'
//
const form = ref({
oldPassword: '',
newPassword: '',
})
onReady(() => {
})
//
const rules: UniHelper.UniFormsRules = {
oldPassword: {
rules: [{ required: true, errorMessage: '请输入原密码' }],
},
newPassword: {
rules: [
{ min: 6, max: 16, errorMessage: '长度在 4 到 16 个字符', trigger: 'blur' },
{ required: true, errorMessage: '请输入新的密码' }
],
},
confirmPassword: {
rules: [
{ required: true, errorMessage: '请输入新的登录密码', trigger: 'blur' },
{ min: 6, max: 16, errorMessage: '长度在 4 到 16 个字符', trigger: 'blur' },
{
validateFunction: (rule, value, data,callback) => {
if (value !== form.value.newPassword) {
callback('两次输入密码不一致!');
} else {
return true
}
}
}
],
}
}
//
const formRef = ref<UniHelper.UniFormsInstance>()
//
const isLoading = ref(false)
//
const onSubmit = async () => {
try {
// 退
if (isLoading.value) return
isLoading.value = true
//
await formRef.value?.validate?.()
//
const params = {
...form.value,
}
const res = await putUpdatePasswordAPI(params)
isLoading.value = false
//
uni.showToast({ icon: 'success', title: '修改成功'})
//
setTimeout(() => {
uni.navigateBack()
}, 400)
} catch (error) {
isLoading.value = false
console.log(error)
// uni.showToast({ icon: 'none', title: '' })
}
}
</script>
<template>
<view class="content">
<uni-forms :rules="rules" :model="form" ref="formRef">
<!-- 表单内容 -->
<uni-forms-item name="oldPassword" class="form-item">
<text class="label">原始密码</text>
<input class="input" placeholder="请填写原始密码" v-model="form.oldPassword" />
</uni-forms-item>
<uni-forms-item name="newPassword" class="form-item">
<text class="label">设置密码</text>
<input class="input" type="password" placeholder="请填写设置密码" :maxlength="11" v-model="form.newPassword" />
</uni-forms-item>
<uni-forms-item name="confirmPassword" class="form-item">
<text class="label">确认密码</text>
<input class="input" type="password" placeholder="请再次输入新的登录密码" :maxlength="11" v-model="form.confirmPassword" />
</uni-forms-item>
</uni-forms>
</view>
<!-- 提交按钮 -->
<button @tap="onSubmit" class="button">确定</button>
</template>
<style lang="scss">
// uni-data-picker
:deep(.selected-area) {
flex: 0 1 auto;
height: auto;
}
page {
background: #F8FAFD;
}
.content {
margin: 20rpx 20rpx 0;
padding: 0 20rpx;
.form-item,
.uni-forms-item {
display: flex;
align-items: center;
min-height: 96rpx;
padding: 25rpx 10rpx;
font-size: 28rpx;;
position: relative;
margin-bottom: 0;
// uni-forms
.uni-forms-item__content {
display: flex;
align-items: center;
padding: 0 10rpx;
}
.uni-forms-item__error {
margin-left: 200rpx;
}
&:last-child {
border: none;
}
.label {
width: 160rpx;
color: #888888;
font-size: 28rpx;
}
.input {
flex: 1;
display: block;
height: 46rpx;
color: #595959;
border: 1rpx solid #ddd;
height: 70rpx;
padding: 0rpx 8rpx;
border-radius: 4rpx;
}
.placeholder {
color: #595959;
}
}
}
.button {
height: 80rpx;
margin: 130rpx 20rpx 0;
color: #fff;
border-radius: 80rpx;
font-size: 30rpx;
background-color: #3775F6;
box-shadow: 0px 3px 12px 0px rgba(63, 112, 157, 0.5);
background: linear-gradient(144deg, #2EACE6 21%, #356899 76%);
}
</style>

@ -1,23 +0,0 @@
<script setup lang="ts">
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
const url = ref('')
onLoad((options) => {
url.value = options.url
})
</script>
<template>
<view class="viewport">
<web-view :src="url"></web-view>
</view>
</template>
<style lang="scss">
page {
height: 100%;
}
.viewport {
height: 100%;
}
</style>

@ -1,366 +0,0 @@
<script setup lang="ts">
import { onMounted, computed, ref } from 'vue'
import { onLoad, onShow } from '@dcloudio/uni-app'
import { getListAPI, getDictAPI } from '@/services/productionReport'
import { useLoginStore } from '@/stores/modules/login'
import { formatDate } from '@/utils/index'
const userStore = useLoginStore()
const userId = userStore.userInfo.userId
//
const isFinish = ref(false)
//
const isTriggered = ref(false)
// porps
const props = defineProps<{
orderState: string
}>()
const statusText = computed(() => {
const text = props.orderState == '0,1' ? '处理' : '查看'
return text
})
//
const isLoading = ref(false)
//
const queryParams: Required<any> = {
page: 1,
pageSize: 5,
owner: userId, //
procedureStatusList: props.orderState, //
dispatchType: 'PRODUCTION', //
isReport: 1, //
}
const dataList = ref([])
const getListData = async () => {
// 退
if (isLoading.value) return
if (isFinish.value === true) {
return uni.showToast({ icon: 'none', title: '没有更多数据~' })
}
isLoading.value = true
//
const data = await getListAPI(queryParams)
isLoading.value = false
data.list.forEach((e) => {
e.orderTime = formatDate(e.orderTime, 'YYYY-MM-DD')
e.startTime = formatDate(e.startTime, 'YYYY-MM-DD')
e.endTime = formatDate(e.endTime, 'YYYY-MM-DD')
})
//
dataList.value.push(...data.list)
//
if (queryParams.page < data.totalPages) {
//
queryParams.page++
} else {
//
isFinish.value = true
}
}
onMounted(async () => {
await getListData()
})
onShow(async () => {
isFinish.value = false
isLoading.value = false
queryParams.pageNo = 1
dataList.value = []
await getListData()
})
const handleDetail = (item) => {
const url = `/pages/productionReport/productionReport-detail?id=${item.id}`
uni.navigateTo({ url })
}
//
const onRefresherrefresh = async () => {
//
isTriggered.value = true
//
queryParams.page = 1
dataList.value = []
isFinish.value = false
//
await getListData()
//
isTriggered.value = false
}
// const searchVal = ref('')
// const dataListDefault = ref([])
// const handleSearch = async () => {
// const code = searchVal.value
// if (code) {
// dataListDefault.value = dataList.value
// dataList.value = dataList.value.filter((e) => {
// return e.code == code
// })
// } else {
// dataList.value = dataListDefault.value
// }
// }
</script>
<template>
<view class="cont">
<!-- <view class="search" v-if="dataList.length > 5">
<view class="title"></view>
<input class="uni-input" v-model="searchVal" @change="handleSearch" placeholder="根据编号搜索" />
</view> -->
<scroll-view enable-back-to-top scroll-y class="data-list" refresher-enabled :refresher-triggered="isTriggered"
@refresherrefresh="onRefresherrefresh" @scrolltolower="getListData">
<view class="item" v-for="item in dataList" :key="item.id" @click="handleDetail(item)">
<view class="hd">
<view class="num">派工单</view>
<view class="statusLabel"> 单号{{ item.dispatchCode }} </view>
</view>
<view class="md">
<view class="product-item">项目名称{{ item.projectCode + ' ' + item.projectName }}</view>
<view class="product-item">子项目{{ item.projectSubCode || '' }} {{' ' + item.projectSubName }}</view>
<view class="product-item">零件名称{{ item.materialName }}</view>
<view class="product-item">派工工序{{ item.procedureName }}</view>
<view class="product-item">派工数量{{ item.amount }}</view>
<view class="product-item">总报工数量{{ item.totalReportAmount }}</view>
<view class="product-item">预计工时{{ item.workTime }}</view>
<view class="product-item">总报工工时{{ item.totalWorkTime }}</view>
<view class="product-item">预计生产日期{{ item.startTime }} {{ item.endTime }}</view>
</view>
<view class="statusText">{{ statusText }}</view>
</view>
<!-- 底部提示文字 -->
<view class="loading-text" :style="{ paddingBottom: safeAreaInsets?.bottom + 'px' }">
{{ isFinish ? '没有更多数据~' : '正在加载...' }}
</view>
</scroll-view>
</view>
</template>
<style lang="scss">
//
.search {
padding: 4rpx;
width: 80%;
margin: 30rpx auto;
.uni-input {
border: 1px solid #D1D6DB;
height: 60rpx;
line-height: 60rpx;
padding: 4rpx 10rpx;
font-size: 32rpx;
border-radius: 6rpx;
}
}
.data-list {
height: 90vh;
.item {
position: relative;
padding: 20rpx 0;
margin: 20rpx 20rpx;
border-radius: 10rpx;
background-color: #fff;
.hd {
padding: 10rpx;
font-size: 28rpx;
display: flex;
.statusLabel {
font-size: 24rpx;
color: #737D88;
}
}
.md {
position: relative;
padding: 10rpx;
min-height: 100rpx;
font-size: 28rpx;
border-top: 2rpx solid #F2F2F2;
border-bottom: 2rpx solid #F2F2F2;
.product-item {
margin: 20rpx 0;
display: flex;
align-items: center;
color: #737D88
}
}
.statusText {
position: absolute;
right: 30rpx;
top: 100rpx;
border-radius: 10rpx;
font-size: 24rpx;
padding: 10rpx 20rpx;
border-radius: 10rpx;
font-size: 24rpx;
background: linear-gradient(149deg, #2DACE6 4%, #356899 98%);
color: #fff;
padding: 10rpx 20rpx;
}
&:last-child {
padding-bottom: 40rpx;
}
}
.status {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 28rpx;
color: #999;
margin-bottom: 15rpx;
.date {
color: #666;
flex: 1;
}
.primary {
color: #ff9240;
}
.icon-delete {
line-height: 1;
margin-left: 10rpx;
padding-left: 10rpx;
border-left: 1rpx solid #e3e3e3;
}
}
.goods {
display: flex;
margin-bottom: 20rpx;
.cover {
width: 170rpx;
height: 170rpx;
margin-right: 20rpx;
border-radius: 10rpx;
overflow: hidden;
position: relative;
.image {
width: 170rpx;
height: 170rpx;
}
}
.quantity {
position: absolute;
bottom: 0;
right: 0;
line-height: 1;
padding: 6rpx 4rpx 6rpx 8rpx;
font-size: 24rpx;
color: #fff;
border-radius: 10rpx 0 0 0;
background-color: rgba(0, 0, 0, 0.6);
}
.meta {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.name {
height: 80rpx;
font-size: 26rpx;
color: #444;
}
.type {
line-height: 1.8;
padding: 0 15rpx;
margin-top: 10rpx;
font-size: 24rpx;
align-self: flex-start;
border-radius: 4rpx;
color: #888;
background-color: #f7f7f8;
}
.more {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
font-size: 22rpx;
color: #333;
}
}
.payment {
display: flex;
justify-content: flex-end;
align-items: center;
line-height: 1;
padding: 20rpx 0;
text-align: right;
color: #999;
font-size: 28rpx;
border-bottom: 1rpx solid #eee;
.quantity {
font-size: 24rpx;
margin-right: 16rpx;
}
.amount {
color: #444;
margin-left: 6rpx;
}
.symbol {
font-size: 20rpx;
}
}
.action {
display: flex;
justify-content: flex-end;
align-items: center;
padding-top: 20rpx;
.button {
width: 180rpx;
height: 60rpx;
display: flex;
justify-content: center;
align-items: center;
margin-left: 20rpx;
border-radius: 60rpx;
border: 1rpx solid #ccc;
font-size: 26rpx;
color: #444;
}
.secondary {
color: #3775F6;
border-color: #3775F6;
}
.primary {
color: #fff;
background-color: #3775F6;
border-color: #3775F6;
}
}
.loading-text {
text-align: center;
font-size: 28rpx;
color: #666;
padding: 20rpx 0;
}
}
</style>import type { stringify } from 'querystring';

@ -1,425 +0,0 @@
<script setup lang="ts">
import { toRaw, ref, computed } from 'vue'
import { formatDate } from '@/utils/index'
import { onLoad, onShow } from '@dcloudio/uni-app'
import { useLoginStore } from '@/stores/modules/login'
import { getTaskRepotPageAPI, getTaskDetailAPI, postOperateAPI } from '@/services/productionReport'
const popup = ref<UniHelper.UniPopupInstance>()
const userStore = useLoginStore()
const dictInfo = userStore?.dictInfo || []
const unitDictData = dictInfo.filter(e => e.dictType == 'biz_material_unit') || []
const userId = userStore.userInfo.userId
const isShowStart = computed(() => {
let flag = true
if (historyList.value.length) {
const obj = historyList.value[0]
if (!obj?.endTime) {
flag = false
}
}
//
if (detailInfo.value.amount == detailInfo.value.totalReportAmount) {
flag = false
}
return flag
})
const isShowEnd = computed(() => {
let flag = true
if (historyList.value.length) {
const obj = historyList.value[0]
if (obj?.endTime) {
flag = false
}
} else {
flag = false
}
return flag
})
const isShowFinish = computed(() => {
let flag = false
flag = detailInfo.value.amount == detailInfo.value.totalReportAmount || false
return flag
})
const amount = ref(null)
const workTime = ref(null)
//
const detailInfo = ref({})
let isLoading = ref(false)
const historyList = ref([])
//
const getData = async () => {
//
// isLoading.value = true
const params = {
pageNo: 1,
integerpageSize: 5,
owner: userId,
dispatchDetailId: detailInfo.value.id,
}
const data = await getTaskRepotPageAPI(params)
data.list.forEach((e) => {
e.startTime = e.startTime && formatDate(e.startTime, 'YYYY-MM-DD HH:mm')
e.endTime = e.endTime && formatDate(e.endTime, 'YYYY-MM-DD HH:mm')
})
historyList.value = data.list
isLoading.value = false
}
//
const getDetailData = async (id) => {
//
// isLoading.value = true
const params = {
id,
}
const data = await getTaskDetailAPI(params)
data.startTime = formatDate(data.startTime, 'YYYY-MM-DD')
data.endTime = formatDate(data.endTime, 'YYYY-MM-DD')
//
const lineObj = unitDictData.find((q) => q.value == data.unit) || {}
data.unit = lineObj.label
detailInfo.value = data || {}
isLoading.value = false
}
onLoad(async (options: any) => {
await getDetailData(options.id)
await getData()
const obj = historyList.value[0]
//
if (obj && obj?.workTime == null && obj.endTime) {
popup.value?.open()
}
})
//
const handleComplate = async () => {
const params = {
id: detailInfo.value?.id,
active: 'FINISH',
}
const data = await postOperateAPI(params)
const url = `/pages/productionReport/productionReport-detail?id=${detailInfo.value.id}`
uni.redirectTo({
url,
})
}
//
const handleOk = async (active) => {
const params = {
id: detailInfo.value?.id,
active: 'SUBMIT',
amount: amount.value,
workTime: workTime.value,
}
const data = await postOperateAPI(params)
const url = `/pages/productionReport/productionReport-detail?id=${detailInfo.value.id}`
uni.redirectTo({
url,
})
}
//
const handleStart = async () => {
const params = {
id: detailInfo.value.id,
active: 'START',
}
const data = await postOperateAPI(params)
const url = `/pages/productionReport/productionReport-detail?id=${detailInfo.value.id}`
uni.redirectTo({
url,
})
}
//
const handleStop = async () => {
const params = {
id: detailInfo.value?.id,
active: 'END',
}
const data = await postOperateAPI(params)
const url = `/pages/productionReport/productionReport-detail?id=${detailInfo.value.id}`
uni.redirectTo({
url,
})
popup.value?.open()
}
</script>
<template>
<view class="data-detail">
<template v-if="!isLoading">
<view class="module">
<view class="module-info">
<view class="product-item">项目{{ detailInfo.dispatchCode }} {{ detailInfo.projectName }}</view>
<image src="/static/images/productionReport-page.png" class="product-img" mode="scaleToFill"></image>
<view class="product-status">{{ detailInfo.procedureStatus == 2 ? '已完成' : '未完成' }}</view>
<view class="product-item">子项目{{ detailInfo.projectSubName }}</view>
<view class="product-item">零件名称{{ detailInfo.materialName }}</view>
<view class="product-item">派工工序{{ detailInfo.procedureName }}</view>
<view class="product-item">派工数量{{ detailInfo.amount }}</view>
<view class="product-item">总报工数量{{ detailInfo.totalReportAmount }}</view>
<view class="product-item">预计工时{{ detailInfo.workTime }}</view>
<view class="product-item">总报工工时{{ detailInfo.totalWorkTime }}</view>
<view class="product-item">预计生产日期{{ detailInfo.startTime }} {{ detailInfo.endTime }}</view>
<!-- <view class="finish" v-if="isShowStart" @click="handleComplate"></view> -->
</view>
</view>
<view class="module-list">
<view class="module-title">历史报工明细</view>
<view class="history-list">
<view class="no-data" v-if="!historyList.length">
无数据...
</view>
<template v-else>
<view class="item" v-for="item in historyList" :key="item.id">
<view class="product-item">生产开始时间{{ item.startTime }}</view>
<view class="product-item">生产结束时间{{ item.endTime }}</view>
<view class="product-item">报工工时{{ item.workTime }}</view>
<view class="product-item">报工数量{{ item.amount }}</view>
</view>
</template>
</view>
</view>
<view class="action" v-if="detailInfo.procedureStatus !== 2">
<view class="action-item start" v-if="isShowStart" @click="handleStart"></view>
<view class="action-item stop" v-if="isShowEnd" @click="handleStop"></view>
<view class="action-item finish" v-if="isShowFinish" @click="handleComplate"></view>
</view>
</template>
<view class="loading-text" v-else>..</view>
<uni-popup class="popup" ref="popup" :mask-click="false" type="bottom" background-color="#fff">
<view class="title">
<view class="text">填写信息</view>
<!-- <view class="close" @click="handleClose">X</view> -->
</view>
<view class="cont">
<view class="item">
<view class="label">开始生产时间</view>
<view class="val">{{ detailInfo.startTime }}</view>
</view>
<view class="item">
<view class="label">结束生产时间</view>
<view class="val">{{ detailInfo.endTime }}</view>
</view>
<view class="item">
<view class="label"><span class="star">*</span>本次报工工时</view>
<uni-easyinput class="val" type="number" v-model="amount" placeholder="请输入本次报工工时"></uni-easyinput>
<view class="unit">小时</view>
</view>
<view class="item">
<view class="label"><span class="star">*</span>本次报工数量</view>
<uni-easyinput class="val" type="number" v-model="workTime" placeholder="请输入本次报工数量"></uni-easyinput>
<view class="unit"> {{ detailInfo.unit }}</view>
</view>
</view>
<view class="ok" @click="handleOk"></view>
</uni-popup>
</view>
</template>
<style lang="scss">
//
.data-detail {
border-radius: 10rpx;
padding-bottom: 200rpx;
.module {
background: linear-gradient(178deg, #356899 7%, #356899 57%, #F4F6F9 94%);
padding: 20rpx;
.module-info {
padding: 20rpx 20rpx 60rpx;
border-radius: 10rpx;
min-height: 100rpx;
font-size: 28rpx;
border-bottom: 2rpx solid #F2F2F2;
background: linear-gradient(215deg, #C7D3E5 8%, rgba(222, 228, 236, 0) 13%), linear-gradient(162deg, #FFFFFF 25%, #E4EFFD 106%);
position: relative;
.product-img {
position: absolute;
right: 0rpx;
top: 0;
width: 100rpx;
height: 100rpx;
}
.product-status {
background: #FFF7E8;
color: #FF7D00;
width: 140rpx;
border-raduis: 10rpx;
text-align: center;
padding: 8rpx 12rpx;
}
.product-item {
margin: 20rpx 0;
display: flex;
align-items: center;
color: #737D88
}
}
}
.module-list {
padding: 20rpx 20rpx;
box-shadow: 0px 0px 8px 0px rgba(161, 161, 177, 0.12);
.module-title {
color: #0D0D26;
font-size: 36rpx;
margin: 20rpx 0;
font-weight: 500;
}
.history-list {
display: flex;
flex-direction: column;
align-items: center;
min-height: 200rpx;
justify-content: center;
margin: 20rpx 0;
padding: 20rpx 10rpx;
.item {
margin: 20rpx 0;
background: #EAEEF4;
font-size: 28rpx;
padding: 20rpx;
width: 100%;
border-radius: 10rpx;
color: #737D88;
.product-item {
margin: 10rpx 0;
}
}
.no-data {
font-size: 28rpx;
color: #444;
}
}
.table-cont {
font-size: 24rpx;
}
.button {
color: #356899;
}
}
.action {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
bottom: 60rpx;
border-radius: 18rpx;
padding: 30rpx 30rpx;
background: #FFFFFF;
margin: 0 auto;
width: 100vw;
box-shadow: 0px -4px 10px 0px rgba(121, 153, 183, 0.2);
.action-item {
width: 272rpx;
height: 86rpx;
display: flex;
justify-content: center;
align-items: center;
margin: 0 20rpx;
font-size: 26rpx;
color: #fff;
width: 272rpx;
height: 86rpx;
border-radius: 24rpx;
&.start {
background: linear-gradient(157deg, #2EACE6 -3%, #356899 90%);
}
&.stop {
background: linear-gradient(167deg, #FEA97B -2%, #F75E40 87%);
}
&.finish {
background: linear-gradient(142deg, #FEB34A 14%, #FE9B12 83%);
}
}
}
.loading-text {
text-align: center;
font-size: 28rpx;
color: #666;
padding: 20rpx 0;
}
.popup {
height: 80vh;
.title {
line-height: 1;
padding: 40rpx;
font-size: 32rpx;
font-weight: normal;
border-bottom: 1rpx solid #ddd;
color: #444;
.close {
position: absolute;
right: 24rpx;
top: 40rpx;
height: 60rpx;
width: 60rpx;
text-align: center;
}
}
.cont {
display: flex;
flex-direction: column;
align-items: center;
margin: 40rpx;
.item {
display: flex;
align-items: center;
margin: 10rpx 0;
color: #737D88;
font-size: 24rpx;
width: 94%;
.label {
width: 200rpx;
.star {
color: red
}
}
.val {
flex: 1
}
.unit {
width: 100rpx;
margin-left: 15rpx;
text-align: center;
}
}
}
.ok {
font-size: 28rpx;
margin: 20rpx auto;
text-align: center;
width: 140rpx;
border-radius: 10rpx;
padding: 8rpx 0;
background-color: #3C8AF7;
color: #fff;
}
}
}
</style>

@ -1,151 +0,0 @@
<script setup lang="ts">
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import dataItem from './components/dataItem.vue'
// porps
const props = defineProps<{
state: string
}>()
// tabs
const orderTabs = ref([
{ orderState: '0,1', title: '未完成', isRender: false },
{ orderState: '2', title: '已完成', isRender: false },
])
//
const activeIndex = ref(0)
const handleIndexChange = (index: any) => {
orderTabs.value.forEach((e) => {
e.isRender = false
})
activeIndex.value = index
orderTabs.value[index].isRender = true
}
onLoad(async (options) => {
if (options.state) {
//
orderTabs.value.forEach((e, index) => {
e.isRender = e.orderState == options.state
if (e.isRender) {
activeIndex.value = index
}
})
} else {
orderTabs.value.forEach((e, index) => {
e.isRender = e.orderState == '0,1'
if (e.isRender) {
activeIndex.value = index
}
})
}
})
</script>
<template>
<view class="viewport">
<view class="tabs">
<text class="item" :class="{ active: activeIndex == index }" v-for="(item, index) in orderTabs" :key="item.title"
@tap="handleIndexChange(index)">
{{ item.title }}
</text>
<!-- 游标 -->
<view class="cursor" :style="{ left: activeIndex ? '65%' : '14%' }"></view>
</view>
<!-- 滑动容器 -->
<swiper class="swiper" :current="activeIndex" @change="handleIndexChange($event.detail.current)">
<!-- 滑动项 -->
<swiper-item v-for="item in orderTabs" :key="item.title">
<dataItem v-if="item.isRender" :order-state="item.orderState" />
</swiper-item>
</swiper>
</view>
</template>
<style lang="scss">
page {
height: 100%;
}
.viewport {
height: 100%;
display: flex;
flex-direction: column;
// background-color: #3775F6;
.navbar {
width: 750rpx;
color: #000;
position: fixed;
top: 0;
left: 0;
z-index: 9;
/* background-color: #f8f8f8; */
background-color: #3775f6;
.wrap {
position: relative;
background-color: #3775f6;
.title {
height: 44px;
display: flex;
justify-content: center;
align-items: center;
font-size: 32rpx;
/* color: #000; */
color: #fff;
}
.back {
position: absolute;
left: 0;
height: 44px;
width: 44px;
font-size: 44rpx;
display: flex;
align-items: center;
justify-content: center;
/* color: #000; */
color: #fff;
}
}
}
.tabs {
display: flex;
justify-content: space-around;
line-height: 60rpx;
position: relative;
z-index: 9;
width: 100%;
.item {
flex: 1;
text-align: center;
padding: 20rpx;
font-size: 28rpx;
color: #1D2129;
&.active {
color: #356899;
}
}
.cursor {
position: absolute;
left: 13%;
bottom: 0;
width: 20%;
height: 6rpx;
padding: 0 50rpx;
background-color: #356899;
/* 过渡效果 */
transition: all 0.4s;
}
}
// swiper
.swiper {
background-color: #f7f7f8;
}
}
</style>

@ -1,220 +0,0 @@
<script setup lang="ts">
import { onMounted, computed, ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { getNotificationPageAPI, postAddAPI } from '@/services/unqualifiedNotification'
import { useLoginStore } from '@/stores/modules/login'
import { formatDate } from '@/utils/index'
const userStore = useLoginStore()
const userId = userStore.userInfo.userId
const dictInfo = userStore?.dictInfo || []
const notificationOpinionDictData = dictInfo.filter(e => e.dictType == 'biz_unqualified_notification_opinion') || []
//
const isFinish = ref(false)
//
const isTriggered = ref(false)
// porps
const props = defineProps<{
orderState: string
}>()
//
const isLoading = ref(false)
//
const queryParams: Required<any> = {
page: 1,
pageSize: 5,
owner: userId,
minCreateTime: '',
maxCreateTime: ''
}
const dataList = ref([])
const getListData = async () => {
// 退
if (isLoading.value) return
if (isFinish.value === true) {
return uni.showToast({ icon: 'none', title: '没有更多数据~' })
}
isLoading.value = true
//
const data = await getNotificationPageAPI(queryParams)
isLoading.value = false
data.list.forEach((e) => {
const obj = userStore.dictInfo.find((q) => q.value == e.property) || {}
e.property = obj?.label
e.createTime = formatDate(e.createTime, 'YYYY-MM-DD')
const obj2 = notificationOpinionDictData.find(q => q.value == e.auditOpinion)
e.auditOpinion = obj2?.label
})
//
dataList.value.push(...data.list)
//
if (queryParams.page < data.totalPages) {
//
queryParams.page++
} else {
//
isFinish.value = true
}
}
onMounted(async () => {
const today = new Date() //
const timeVal = today.setMonth(today.getMonth()-3)//
if (props.orderState == '0') {
queryParams.minCreateTime = formatDate(timeVal)
delete queryParams.maxCreateTime
} else {
delete queryParams.minCreateTime
queryParams.maxCreateTime = formatDate(timeVal)
}
dataList.value = []
await getListData()
})
//
const onRefresherrefresh = async () => {
//
isTriggered.value = true
//
queryParams.page = 1
dataList.value = []
isFinish.value = false
//
await getListData()
//
isTriggered.value = false
}
defineExpose({ getListData })
</script>
<template>
<view class="cont">
<scroll-view enable-back-to-top scroll-y class="data-list" refresher-enabled :refresher-triggered="isTriggered"
@refresherrefresh="onRefresherrefresh" @scrolltolower="getListData">
<view class="item" v-for="item in dataList" :key="item.id">
<view class="hd">
<view class="num">异常通知单</view>
<view class="statusLabel">单号{{ item.code }}</view>
</view>
<view class="md">
<view class="product-item">创建人<text class="blue">{{ item.creatorName }}</text></view>
<view class="product-item">项目名称<text class="blue">{{ item.projectCode + ' ' + item.projectName }}</text></view>
<view class="product-item">子项目名称<text class="blue">{{ item.projectSubCode || '' }} {{' ' + item.projectSubName }}</text></view>
<view class="product-item">客户名称<text class="blue">{{ item.customerName }}</text></view>
<view class="product-item">通知日期<text class="blue">{{ item.createTime }}</text></view>
<view class="product-item">零件名称<text class="blue">{{ item.bomDetailId }}</text></view>
<view class="product-item">图号<text class="blue">{{ item.blueprintNo }}</text></view>
<view class="product-item">材质<text class="blue">{{ item.compositionName }}</text></view>
<view class="product-item">责任工序<text class="blue">{{ item.procedureName }}</text></view>
<view class="product-item">异常数量<text class="blue">{{ item.amount }}</text></view>
<view class="product-item">责任人<text class="blue">{{ item.ownerName }}</text></view>
<view class="product-item">异常情况描述及原因分析<text class="blue">{{ item.remark }}</text></view>
<view class="product-item">审核人{{ item.auditorName }}</view>
<view class="product-item">审核意见<text class="auditOpinion">{{ item.auditOpinion }}</text></view>
</view>
</view>
<!-- 底部提示文字 -->
<view class="loading-text" :style="{ paddingBottom: safeAreaInsets?.bottom + 'px' }">
{{ isFinish ? '没有更多数据~' : '正在加载...' }}
</view>
</scroll-view>
</view>
</template>
<style lang="scss">
//
.cont {
height: 100vh;
overflow: auto;
position: reactive;
}
.data-list {
.item {
position: relative;
padding: 20rpx 0;
margin: 20rpx 20rpx;
border-radius: 10rpx;
background-color: #fff;
.hd {
padding: 10rpx;
font-size: 32rpx;
display: flex;
.statusLabel {
font-size: 28rpx;
color: #737D88;
}
}
.md {
position: relative;
padding: 10rpx;
min-height: 100rpx;
font-size: 28rpx;
border-top: 2rpx solid #F2F2F2;
.product-item {
margin: 20rpx 0;
display: flex;
align-items: center;
color: #737D88;
.auditOpinion {
color: #FF7D00;
}
.blue {
color: #409EFF;
}
}
}
&:last-child {
padding-bottom: 40rpx;
}
}
.action {
display: flex;
justify-content: flex-end;
align-items: center;
padding-top: 20rpx;
.button {
width: 180rpx;
height: 60rpx;
display: flex;
justify-content: center;
align-items: center;
margin-left: 20rpx;
border-radius: 60rpx;
border: 1rpx solid #ccc;
font-size: 26rpx;
color: #444;
}
.secondary {
color: #3775F6;
border-color: #3775F6;
}
.primary {
color: #fff;
background-color: #3775F6;
border-color: #3775F6;
}
}
.loading-text {
text-align: center;
font-size: 28rpx;
color: #666;
padding: 20rpx 0;
}
}
</style>

@ -1,337 +0,0 @@
<script setup lang="ts">
import { toRaw, ref } from 'vue'
import { formatDate } from '@/utils/index'
import { getApproveOrderAPI, getChildProductAPI } from '@/services/approveOrder'
import { getBomPageAPI, getProcedurePageAPI, getUserPageAPI, postAddAPI } from '@/services/unqualifiedNotification'
import { onShow } from '@dcloudio/uni-app'
import { useLoginStore } from '@/stores/modules/login'
//
const emit = defineEmits<{
(event: 'close'): void
}>()
const userStore = useLoginStore()
const dictData = userStore.dictInfo
const userId = userStore.userInfo.userId
const userName = userStore.userInfo.nickname
//
const detailInfo = ref({})
let isLoading = ref(false)
//
let typeDictData = []
const getTypeDictData = () => {
const arr = dictData.filter(e => e.dictType == 'biz_inspection_type') || []
arr.forEach(e => {
const obj = {
value: e.value,
text: e.label
}
typeDictData.push(obj)
})
}
//
let projectData = []
const getProjectData = async () => {
const params = {
pageNo: 1,
pageSize: 99,
orderStatusList: '32',
isSnapshot: 0,
deliveryStatusList: '1,2' // 1|2|3
}
const data = await getApproveOrderAPI(params)
const arr = []
data.list.forEach(e => {
const obj = {
text: e.projectName,
value: e.id
}
arr.push(obj)
})
projectData = arr
}
const projectChildData = ref([])
const getProjectChildData = async (projectOrderId) => {
const params = {
projectOrderId,
}
const data = await getChildProductAPI(params)
const arr = []
data.forEach(e => {
const obj = {
text: e.name,
value: e.id
}
arr.push(obj)
})
projectChildData.value = arr
}
//
const bomData = ref([])
const getBomData = async (projectOrderId) => {
const params = {
pageNo: 1,
pageSize: 99,
projectId: valiFormData.value.projectId,
projectSubId: valiFormData.value.projectSubId
}
const data = await getBomPageAPI(params)
const arr = []
data.list.forEach(e => {
const obj = {
text: e.materialName,
value: e.bomDetailId
}
arr.push(obj)
})
bomData.value = arr
}
//
const procedureData = ref([])
const getProcedurePage = async (projectOrderId) => {
const params = {
pageNo: 1,
pageSize: 99,
}
const data = await getProcedurePageAPI(params)
const arr = []
data.list.forEach(e => {
const obj = {
text: e.name,
value: e.id
}
arr.push(obj)
})
procedureData.value = arr
}
//
const ownerData = ref([])
const getOwnerDataData = async (projectOrderId) => {
const params = {
pageNo: 1,
pageSize: 99,
}
const data = await getUserPageAPI(params)
const arr = []
data.list.forEach(e => {
const obj = {
text: e.nickname,
value: e.id
}
arr.push(obj)
})
ownerData.value = arr
}
onShow(async () => {
isLoading.value = false
await getTypeDictData()
await getProjectData()
await getBomData()
await getProcedurePage()
await getOwnerDataData()
// await getFileData()
// await getLogData()
// await getData()
isLoading.value = false
})
//
const formRef = ref<UniHelper.UniFormsInstance>()
const valiFormData = ref({
type: '', //
projectId: '', // id
projectSubId: '', // id
bomDetailId: '', //
procedureId: '', //id
amount: 0,
owner: '',
remark: '',
status: 1, // ,12,(1)
notificationStatus: 2, // || 1|2|32
active: 'SUBMIT'
})
//
const rules: UniHelper.UniFormsRules = {
type: {
rules: [{ required: true, errorMessage: '请选择质检类型' }],
},
projectId: {
rules: [{ required: true, errorMessage: '请选择项目名称' }],
},
projectSubId: {
rules: [{ required: true, errorMessage: '请选择子项目名称' }],
},
procedureId: {
rules: [{ required: true, errorMessage: '请选择子责任工序' }],
},
// bomDetailId: {
// rules: [{ required: true, errorMessage: '' }],
// },
amount: {
rules: [{ required: true, errorMessage: '请输入异常常量' }],
},
owner: {
rules: [{ required: true, errorMessage: '请选择责任人' }],
},
remark: {
rules: [{ required: true, errorMessage: '请输入情况描述' }],
},
}
const handleChangeType = (val) => {
valiFormData.value.type = val
//
if (val == 1) {
valiFormData.value.owner = userId
}
}
//
const handleChangeProject = (val) => {
valiFormData.value.projectId = val
valiFormData.value.projectSubId = ''
projectChildData.value = []
valiFormData.value.bomDetailId = ''
bomData.value = []
if (val || val == 0) {
getProjectChildData(val)
}
}
//
const handleChangeProjectChild = (val) => {
valiFormData.value.projectSubId = val
valiFormData.value.bomDetailId = ''
bomData.value = []
getBomData(val)
}
//
const handleCancl = () => {
emit('close', false)
}
//
const handleSubmit = async () => {
await formRef.value?.validate?.()
const params = {
...valiFormData.value
}
const data = await postAddAPI(params)
valiFormData.value.type = ''
valiFormData.value.projectId = ''
valiFormData.value.projectSubId = ''
valiFormData.value.bomDetailId = ''
valiFormData.value.procedureId = ''
valiFormData.value.amount = undefined
valiFormData.value.owner = ''
valiFormData.value.remark = ''
emit('close', true)
}
</script>
<template>
<view class="data-detail">
<template v-if="!isLoading">
<!-- 基础表单校验 -->
<uni-forms ref="formRef" :rules="rules" :modelValue="valiFormData" label-width="120">
<uni-forms-item label="质检类型" required name="type">
<uni-data-select
v-model="valiFormData.type"
:localdata="typeDictData"
@change="handleChangeType"
></uni-data-select>
</uni-forms-item>
<uni-forms-item label="项目名称" required name="projectId">
<uni-data-select
v-model="valiFormData.projectId"
:localdata="projectData"
@change="handleChangeProject"
></uni-data-select>
</uni-forms-item>
<uni-forms-item label="子项目名称" required name="projectSubId">
<uni-data-select
v-model="valiFormData.projectSubId"
:localdata="projectChildData"
@change="handleChangeProjectChild"
></uni-data-select>
</uni-forms-item>
<uni-forms-item label="零件名称" name="bomDetailId">
<uni-data-select
v-model="valiFormData.bomDetailId"
:localdata="bomData"
></uni-data-select>
</uni-forms-item>
<uni-forms-item label="责任工序" required name="procedureId">
<uni-data-select
v-model="valiFormData.procedureId"
:localdata="procedureData"
></uni-data-select>
</uni-forms-item>
<uni-forms-item label="异常数量" required name="amount">
<uni-easyinput type="number" v-model="valiFormData.amount" placeholder="请输入异常数量" />
</uni-forms-item>
<uni-forms-item label="责任人" required name="owner">
<template v-if="valiFormData.type == 1">
<uni-easyinput type="text" disabled :value="userName" />
</template>
<template v-else>
<uni-data-select
v-model="valiFormData.owner"
:localdata="ownerData"
></uni-data-select>
</template>
</uni-forms-item>
<uni-forms-item label="情况描述" required name="remark">
<uni-easyinput type="textarea" v-model="valiFormData.remark" placeholder="请输入情况描述" />
</uni-forms-item>
</uni-forms>
<view class="action">
<button class="cancle" @click="handleCancl()"></button>
<button class="submit" @click="handleSubmit()"></button>
</view>
</template>
<view class="loading-text" v-else>..</view>
</view>
</template>
<style lang="scss" scoped>
//
.data-detail {
height: 80vh;
z-index: 9999;
padding: 20rpx 0;
margin: 20rpx 20rpx;
border-radius: 10rpx;
background-color: #fff;
padding-bottom: 200rpx;
.loading-text {
text-align: center;
font-size: 28rpx;
color: #666;
padding: 20rpx 0;
}
.uni-section {
display: flex!important;
align-items: center!important;
}
.action {
display: flex;
justify-content: space-between;
align-items: center;
.cancle {
color: #356899;
background-color: #F9FCFF;
padding: 0rpx 100rpx;
margin-right: 20rpx;
}
.submit {
// background-color: #F9FCFF;
padding: 0rpx 100rpx;
color: #fff;
background: linear-gradient(170deg, #2DACE6 -128%, #356899 141%);
}
}
}
</style>

@ -1,180 +0,0 @@
<script setup lang="ts">
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import dataItem from './components/dataItem.vue'
import detailPanel from './components/detailPanel.vue'
const childRef = ref(null);
// tabs
const orderTabs = ref([
{ orderState: '0', title: '近三个月', isRender: false },
{ orderState: '1', title: '三个月前', isRender: false },
])
//
const activeIndex = ref(0)
const handleIndexChange = (index: any) => {
orderTabs.value.forEach((e) => {
e.isRender = false
})
activeIndex.value = index
orderTabs.value[index].isRender = true
}
onLoad(async (options) => {
if (options.state) {
//
orderTabs.value.forEach((e, index) => {
e.isRender = e.orderState == options.state
if (e.isRender) {
activeIndex.value = index
}
})
} else {
orderTabs.value.forEach((e, index) => {
e.isRender = e.orderState == '0'
if (e.isRender) {
activeIndex.value = index
}
})
}
})
const btnTop = ref(80)
const btnLeft = ref(20)
const startX = ref(0)
const startY = ref(0)
//
const handleAdd = (e) => {
popup.value?.open()
}
// uni-ui ref
const popup = ref<{
open: (type?: UniHelper.UniPopupType) => void
close: () => void
}>()
const handlePopClose = (flag) => {
popup.value?.close()
flag && childRef.value[0].getListData()
}
</script>
<template>
<view class="viewport">
<view class="tabs">
<text class="item" :class="{ active: activeIndex == index }" v-for="(item, index) in orderTabs" :key="item.title"
@tap="handleIndexChange(index)">
{{ item.title }}
</text>
<!-- 游标 -->
<view class="cursor" :style="{ left: activeIndex ? '65%' : '14%' }"></view>
</view>
<!-- 滑动容器 -->
<swiper class="swiper" :current="activeIndex" @change="handleIndexChange($event.detail.current)">
<!-- 滑动项 -->
<swiper-item v-for="item in orderTabs" :key="item.title">
<dataItem ref="childRef" v-if="item.isRender" :order-state="item.orderState" />
</swiper-item>
</swiper>
<view class="float-btn" :style="{bottom: btnTop + 'px', right: btnLeft + 'px'}" @click="handleAdd">
<uni-icons type="plus-filled" size="60" color="#FF3E18"></uni-icons>
</view>
<!-- uni-ui 弹出层 -->
<uni-popup ref="popup" :mask-click="false" type="bottom" background-color="#fff">
<detailPanel @close="handlePopClose" />
</uni-popup>
</view>
</template>
<style lang="scss">
page {
height: 100%;
}
.viewport {
height: 100%;
display: flex;
flex-direction: column;
position: reactive;
// background-color: #3775F6;
.navbar {
width: 750rpx;
color: #000;
position: fixed;
top: 0;
left: 0;
z-index: 9;
/* background-color: #f8f8f8; */
background-color: #3775f6;
.wrap {
position: relative;
background-color: #3775f6;
.title {
height: 44px;
display: flex;
justify-content: center;
align-items: center;
font-size: 32rpx;
/* color: #000; */
color: #fff;
}
.back {
position: absolute;
left: 0;
height: 44px;
width: 44px;
font-size: 44rpx;
display: flex;
align-items: center;
justify-content: center;
/* color: #000; */
color: #fff;
}
}
}
.tabs {
display: flex;
justify-content: space-around;
line-height: 60rpx;
position: relative;
z-index: 9;
width: 100%;
.item {
flex: 1;
text-align: center;
padding: 20rpx;
font-size: 28rpx;
color: #1D2129;
&.active {
color: #356899;
}
}
.cursor {
position: absolute;
left: 13%;
bottom: 0;
width: 20%;
height: 6rpx;
padding: 0 50rpx;
background-color: #356899;
/* 过渡效果 */
transition: all 0.4s;
}
}
// swiper
.swiper {
background-color: #f7f7f8;
}
.float-btn {
position: absolute;
color: #fff;
text-align: center;
}
}
</style>

@ -1,73 +0,0 @@
/*
* @Author:
* @Date: 2024-01-04 12:54:56
* @LastEditors:
* @LastEditTime: 2024-03-25 11:17:12
* @FilePath: /app-nx-personal/src/services/home.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { http } from '@/utils/http'
export const getApproveOrderAPI = (data: Object) => {
return http<any[]>({
method: 'GET',
url: '/biz/project-order/page',
data,
})
}
export const getApproveOrderDetailAPI = (data: Object) => {
return http<any[]>({
method: 'GET',
url: '/biz/project-order/get',
data,
})
}
/**
* //
*/
export const postOperateAPI = (data: Object) => {
return http<any[]>({
method: 'POST',
url: '/biz/project-order/operate',
data,
})
}
/**
*
*/
export const getChildProductAPI = (data: Object) => {
return http<any[]>({
method: 'GET',
url: '/biz/project-order/project-order-sub/list-by-project-order-id',
data,
})
}
/**
*
*/
export const getFileAPI = (data: Object) => {
return http<any[]>({
method: 'GET',
url: '/infra/file/page',
data,
})
}
/**
*
*/
export const getLogAPI = (data: Object) => {
return http<any[]>({
method: 'GET',
url: '/system/operate-log/page',
data,
})
}
export const getDictAPI = (data: Object) => {
return http<any[]>({
method: 'GET',
url: '/system/dict-data/page',
data,
})
}

@ -1,11 +0,0 @@
/*
* @Author:
* @Date: 2024-01-04 12:54:56
* @LastEditors:
* @LastEditTime: 2024-03-26 14:38:12
* @FilePath: /hl-app/src/services/constants.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
// export const serviceDomain = 'https://nxhs.cjyx.cc'
export const serviceDomain = 'http://222.71.165.187:9010'

@ -1,19 +0,0 @@
/*
* @Author:
* @Date: 2024-01-04 12:54:56
* @LastEditors:
* @LastEditTime: 2024-03-19 17:27:47
* @FilePath: /app-nx-personal/src/services/home.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import type { PageParams, PageResult } from '@/types/global'
import type { BannerItem, CategoryItem, GuessItem, HotItem } from '@/types/home'
import { http } from '@/utils/http'
export const getHomeCategoryAPI = () => {
return http<CategoryItem[]>({
method: 'GET',
url: '/system/auth/get-permission-info',
})
}

@ -1,72 +0,0 @@
/*
* @Author:
* @Date: 2024-03-04 14:13:16
* @LastEditors:
* @LastEditTime: 2024-03-26 09:35:18
* @FilePath: /hl-app/src/services/login.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import type { LoginResult } from '@/types/login'
import { http } from '@/utils/http'
type LoginWxMinParams = {
code: string
encryptedData?: string
iv?: string
}
/**
*
* @param data
*/
export const postLoginWxMinAPI = (data: LoginWxMinParams) => {
return http<LoginResult>({
method: 'POST',
url: '/common/shlogin',
data,
})
}
type LoginParams = {
username: string
password: string
}
/**
* -+
* @param data
*/
export const postLoginAPI = (data: LoginParams) => {
return http<LoginResult>({
method: 'POST',
url: '/system/auth/login',
data,
})
}
// 获得全部字典数据列表
export const getDictAPI = (data: any) => {
return http<LoginResult>({
method: 'GET',
url: '/system/dict-data/simple-list',
data,
})
}
/**
* 退
*/
export const postLogoutAPI = (data: Object) => {
return http<any>({
method: 'POST',
url: '/system/auth/logout',
data,
})
}
export const getAuthAPI = () => {
return http<any>({
method: 'GET',
url: '/system/auth/get-permission-info',
})
}

@ -1,23 +0,0 @@
/*
* @Author:
* @Date: 2024-03-20 13:30:51
* @LastEditors:
* @LastEditTime: 2024-03-20 17:58:26
* @FilePath: /hl-app/src/services/my.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { http } from '@/utils/http'
export const getUserInfoAPI = (data: any) => {
return http<any[]>({
method: 'GET',
url: '/system/user/get',
data,
})
}
export const putUpdatePasswordAPI = (data: any) => {
return http<any[]>({
method: 'PUT',
url: '/system/user/profile/update-password',
data,
})
}

@ -1,44 +0,0 @@
/*
* @Author:
* @Date: 2024-01-04 12:54:56
* @LastEditors:
* @LastEditTime: 2024-03-29 15:44:53
* @FilePath: /app-nx-personal/src/services/home.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { http } from '@/utils/http'
// 获取工序分页
export const getListAPI = (data: Object) => {
return http<any[]>({
method: 'GET',
url: '/biz/task-dispatch/task-dispatch-detail/page',
data,
})
}
// 报工记录分页查询
export const getTaskRepotPageAPI = (data: Object) => {
return http<any[]>({
method: 'GET',
url: '/biz/task-report/page',
data,
})
}
// 派工任务详情
export const getTaskDetailAPI = (data: Object) => {
return http<any[]>({
method: 'GET',
url: '/biz/task-dispatch/task-dispatch-detail/get',
data,
})
}
/**
* ///
*/
export const postOperateAPI = (data: Object) => {
return http<any[]>({
method: 'POST',
url: '/biz/task-dispatch/task-dispatch-detail/operate',
data,
})
}

@ -1,32 +0,0 @@
/*
* @Author:
* @Date: 2024-01-04 12:54:56
* @LastEditors:
* @LastEditTime: 2024-03-07 15:49:32
* @FilePath: /app-nx-personal/src/services/profile.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import type { ProfileDetail, ProfileParams } from '@/types/member'
import { http } from '@/utils/http'
/**
*
*/
export const getMemberProfileAPI = () => {
return http<ProfileDetail>({
method: 'GET',
url: '/client/info',
})
}
/**
*
* @param data
*/
export const postMemberProfileAPI = (data: ProfileParams) => {
return http<ProfileDetail>({
method: 'POST',
url: '/client/update',
data,
})
}

@ -1,54 +0,0 @@
/*
* @Author:
* @Date: 2024-01-04 12:54:56
* @LastEditors: jevononlie 728254585@qq.com
* @LastEditTime: 2024-04-02 10:04:35
* @FilePath: /app-nx-personal/src/services/home.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { http } from '@/utils/http'
// 异常通知单分页查询
export const getNotificationPageAPI = (data: Object) => {
return http<any[]>({
method: 'GET',
url: '/biz/unqualified-notification/page',
data,
})
}
// 获取零件分页
export const getBomPageAPI = (data: Object) => {
return http<any[]>({
method: 'GET',
url: '/biz/plan-task-bom/page',
data,
})
}
// 获取工序分页
export const getProcedurePageAPI = (data: Object) => {
return http<any[]>({
method: 'GET',
url: '/biz/procedure/page',
data,
})
}
// 获取用户分页
export const getUserPageAPI = (data: Object) => {
return http<any[]>({
method: 'GET',
url: '/system/user/page',
data,
})
}
// 创建品质异常通知单审核
export const postAddAPI = (data: Object) => {
return http<any[]>({
method: 'POST',
url: '/biz/unqualified-notification/create',
data,
})
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

@ -1,18 +0,0 @@
/*
* @Author:
* @Date: 2024-03-04 14:13:16
* @LastEditors:
* @LastEditTime: 2024-03-26 14:35:40
* @FilePath: /hl-app/src/stores/index.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import { createPinia } from 'pinia'
import persist from 'pinia-plugin-persistedstate'
// 创建 pinia 实例
const pinia = createPinia()
// 使用持久化存储插件
pinia.use(persist)
// 默认导出,给 main.ts 使用
export default pinia

@ -1,56 +0,0 @@
/*
* @Author:
* @Date: 2024-01-04 12:54:56
* @LastEditors: jevononlie 728254585@qq.com
* @LastEditTime: 2024-04-09 18:09:07
* @FilePath: /app-nx-recycle/src/stores/modules/member.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import type { LoginResult } from '@/types/login'
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
// 定义 Store
export const useLoginStore = defineStore('login', () => {
// 会员信息
const userInfo = ref({})
const dictInfo = ref([])
// 保存会员信息,登录时使用
const setInfo = (val: Object) => {
userInfo.value = val
}
// 清理会员信息,退出时使用
const clearInfo = () => {
userInfo.value = undefined
}
// 保存枚举
const setDict = (val: any) => {
dictInfo.value = val
}
// 清理枚举
const clearDict = () => {
dictInfo.value = []
}
return {
userInfo,
dictInfo,
setInfo,
clearInfo,
setDict,
clearDict,
}
},{
persist: {
storage: {
getItem(key) {
return uni.getStorageSync(key)
},
setItem(key, value) {
uni.setStorageSync(key, value)
},
}
}
})

@ -1,32 +0,0 @@
view,
navigator,
input,
scroll-view {
box-sizing: border-box;
}
button::after {
border: none;
}
swiper,
scroll-view {
flex: 1;
height: 100%;
overflow: auto;
}
image {
width: 100%;
height: 100%;
vertical-align: middle;
}
//
.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}

@ -1,31 +0,0 @@
view,
navigator,
input,
scroll-view {
box-sizing: border-box;
}
button::after {
border: none;
}
swiper,
scroll-view {
flex: 1;
height: 100%;
overflow: auto;
}
image {
width: 100%;
height: 100%;
vertical-align: middle;
}
.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}

@ -1,147 +0,0 @@
@font-face {
font-family: 'erabbit';
src: url('https://at.alicdn.com/t/c/font_4009193_lnbhmo3yos.woff?t=1681201348304') format('woff'),
url('https://at.alicdn.com/t/c/font_4009193_lnbhmo3yos.ttf?t=1681201348304') format('truetype'),
url('https://at.alicdn.com/t/c/font_4009193_lnbhmo3yos.svg?t=1681201348304#erabbit')
format('svg');
}
[class^='icon-'],
[class*=' icon-'] {
font-family: 'erabbit' !important;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-mail:before {
content: '\e644';
}
.icon-weixin:before {
content: '\e620';
}
.icon-phone:before {
content: '\e618';
}
.icon-camera-plus:before {
content: '\e636';
}
.icon-close:before {
content: '\e6e1';
}
.icon-help:before {
content: '\e617';
}
.icon-cart:before {
content: '\e6d1';
}
.icon-settings:before {
content: '\e6cf';
}
.icon-clock:before {
content: '\e609';
}
.icon-delete:before {
content: '\e6ce';
}
.icon-checked:before {
content: '\e6cc';
}
.icon-ring:before {
content: '\e6cd';
}
.icon-locate:before {
content: '\e6cb';
}
.icon-mark:before {
content: '\e6ca';
}
.icon-check:before {
content: '\e6c9';
}
.icon-handset:before {
content: '\e6c8';
}
.icon-gift:before {
content: '\e6c7';
}
.icon-currency:before {
content: '\e6c6';
}
.icon-comment:before {
content: '\e6c5';
}
.icon-caret:before {
content: '\e6c3';
}
.icon-right:before {
content: '\e6c2';
}
.icon-left:before {
content: '\e6c1';
}
.icon-down:before {
content: '\e6c0';
}
.icon-up:before {
content: '\e6bf';
}
.icon-sort:before {
content: '\e616';
}
.icon-clear:before {
content: '\e6be';
}
.icon-user:before {
content: '\e6bb';
}
.icon-scan:before {
content: '\e6bc';
}
.icon-search:before {
content: '\e632';
}
.icon-preview:before {
content: '\e61d';
}
.icon-heart:before {
content: '\e647';
}
.icon-filter:before {
content: '\e629';
}
.icon-home:before {
content: '\e8b9';
}

@ -1,144 +0,0 @@
@font-face {
font-family: 'erabbit';
src: url("https://at.alicdn.com/t/c/font_4009193_lnbhmo3yos.woff?t=1681201348304") format("woff"), url("https://at.alicdn.com/t/c/font_4009193_lnbhmo3yos.ttf?t=1681201348304") format("truetype"), url("https://at.alicdn.com/t/c/font_4009193_lnbhmo3yos.svg?t=1681201348304#erabbit") format("svg");
}
[class^='icon-'],
[class*=' icon-'] {
font-family: 'erabbit' !important;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-mail:before {
content: '\e644';
}
.icon-weixin:before {
content: '\e620';
}
.icon-phone:before {
content: '\e618';
}
.icon-camera-plus:before {
content: '\e636';
}
.icon-close:before {
content: '\e6e1';
}
.icon-help:before {
content: '\e617';
}
.icon-cart:before {
content: '\e6d1';
}
.icon-settings:before {
content: '\e6cf';
}
.icon-clock:before {
content: '\e609';
}
.icon-delete:before {
content: '\e6ce';
}
.icon-checked:before {
content: '\e6cc';
}
.icon-ring:before {
content: '\e6cd';
}
.icon-locate:before {
content: '\e6cb';
}
.icon-mark:before {
content: '\e6ca';
}
.icon-check:before {
content: '\e6c9';
}
.icon-handset:before {
content: '\e6c8';
}
.icon-gift:before {
content: '\e6c7';
}
.icon-currency:before {
content: '\e6c6';
}
.icon-comment:before {
content: '\e6c5';
}
.icon-caret:before {
content: '\e6c3';
}
.icon-right:before {
content: '\e6c2';
}
.icon-left:before {
content: '\e6c1';
}
.icon-down:before {
content: '\e6c0';
}
.icon-up:before {
content: '\e6bf';
}
.icon-sort:before {
content: '\e616';
}
.icon-clear:before {
content: '\e6be';
}
.icon-user:before {
content: '\e6bb';
}
.icon-scan:before {
content: '\e6bc';
}
.icon-search:before {
content: '\e632';
}
.icon-preview:before {
content: '\e61d';
}
.icon-heart:before {
content: '\e647';
}
.icon-filter:before {
content: '\e629';
}
.icon-home:before {
content: '\e8b9';
}

@ -1,27 +0,0 @@
import type { GoodsItem } from './global'
/** 一级分类项 */
export type CategoryTopItem = {
/** 二级分类集合[ 二级分类项 ] */
children: CategoryChildItem[]
/** 一级分类id */
id: string
/** 一级分类图片集[ 一级分类图片项 ] */
imageBanners: string[]
/** 一级分类名称 */
name: string
/** 一级分类图片 */
picture: string
}
/** 二级分类项 */
export type CategoryChildItem = {
/** 商品集合[ 商品项 ] */
goods: GoodsItem[]
/** 二级分类id */
id: string
/** 二级分类名称 */
name: string
/** 二级分类图片 */
picture: string
}

@ -1,13 +0,0 @@
import XtxSwiper from '@/components/XtxSwiper.vue'
import XtxGuess from '@/components/XtxGuess.vue'
declare module 'vue' {
export interface GlobalComponents {
XtxSwiper: typeof XtxSwiper
XtxGuess: typeof XtxGuess
}
}
// 组件实例类型
export type XtxGuessInstance = InstanceType<typeof XtxGuess>
export type XtxSwiperInstance = InstanceType<typeof XtxSwiper>

@ -1,40 +0,0 @@
/*
* @Author:
* @Date: 2024-01-04 12:54:56
* @LastEditors:
* @LastEditTime: 2024-02-22 17:00:35
* @FilePath: /app-nx-recycle/src/types/global.d.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/** 通用分页结果类型 */
export type PageResult<T> = {
/** 列表数据 */
list: T[]
pages: string,
}
/** 通用分页参数类型 */
export type PageParams = {
/** 页码:默认值为 1 */
pageNo?: number
/** 页大小:默认值为 10 */
pageSize?: number,
}
/** 通用商品类型 */
export type GoodsItem = {
/** 商品描述 */
desc: string
/** 商品折扣 */
discount: number
/** id */
id: string
/** 商品名称 */
name: string
/** 商品已下单数量 */
orderNum: number
/** 商品图片 */
picture: string
/** 商品价格 */
price: number
}

@ -1,90 +0,0 @@
import type { AddressItem } from './address'
import type { GoodsItem } from './global'
/** 商品信息 */
export type GoodsResult = {
/** id */
id: string
/** 商品名称 */
name: string
/** 商品描述 */
desc: string
/** 当前价格 */
price: number
/** 原价 */
oldPrice: number
/** 商品详情: 包含详情属性 + 详情图片 */
details: Details
/** 主图图片集合[ 主图图片链接 ] */
mainPictures: string[]
/** 同类商品[ 商品信息 ] */
similarProducts: GoodsItem[]
/** sku集合[ sku信息 ] */
skus: SkuItem[]
/** 可选规格集合备注[ 可选规格信息 ] */
specs: SpecItem[]
/** 用户地址列表[ 地址信息 ] */
userAddresses: AddressItem[]
}
/** 商品详情: 包含详情属性 + 详情图片 */
export type Details = {
/** 商品属性集合[ 属性信息 ] */
properties: DetailsPropertyItem[]
/** 商品详情图片集合[ 图片链接 ] */
pictures: string[]
}
/** 属性信息 */
export type DetailsPropertyItem = {
/** 属性名称 */
name: string
/** 属性值 */
value: string
}
/** sku信息 */
export type SkuItem = {
/** sku id */
id: string
/** sku 库存 */
inventory: number
/** sku 原价 */
oldPrice: number
/** sku 图片 */
picture: string
/** sku 当前价 */
price: number
/** sku 编码 */
skuCode: string
/** 规格集合[ 规格信息 ] */
specs: SkuSpecItem[]
}
/** 规格信息 */
export type SkuSpecItem = {
/** 规格名称 */
name: string
/** 可选值名称 */
valueName: string
}
/** 可选规格信息 */
export type SpecItem = {
/** 规格名称 */
name: string
/** 可选值集合[ 可选值信息 ] */
values: SpecValueItem[]
}
/** 可选值信息 */
export type SpecValueItem = {
/** 是否可售 */
available: boolean
/** 可选值备注 */
desc: string
/** 可选值名称 */
name: string
/** 可选值图片链接 */
picture: string
}

@ -1,42 +0,0 @@
import type { GoodsItem } from './global'
/** 首页-广告区域数据类型 */
export type BannerItem = {
/** 跳转链接 */
hrefUrl: string
/** id */
id: string
/** 图片链接 */
imgUrl: string
/** 跳转类型 */
type: number
}
/** 首页-前台类目数据类型 */
export type CategoryItem = {
/** 图标路径 */
icon: string
/** id */
id: string
/** 分类名称 */
name: string
}
/** 首页-热门推荐数据类型 */
export type HotItem = {
/** 说明 */
alt: string
/** id */
id: string
/** 图片集合[ 图片路径 ] */
pictures: string[]
/** 跳转地址 */
target: string
/** 标题 */
title: string
/** 推荐类型 */
type: string
}
/** 猜你喜欢-商品类型 */
export type GuessItem = GoodsItem

@ -1,23 +0,0 @@
import type { PageResult, GoodsItem } from './global'
/** 热门推荐-子类选项 */
export type SubTypeItem = {
/** 子类id */
id: string
/** 子类标题 */
title: string
/** 子类对应的商品集合 */
goodsItems: PageResult<GoodsItem>
}
/** 热门推荐 */
export type HotResult = {
/** id信息 */
id: string
/** 活动图片 */
bannerPicture: string
/** 活动标题 */
title: string
/** 子类选项 */
subTypes: SubTypeItem[]
}

@ -1,21 +0,0 @@
/*
* @Author:
* @Date: 2024-03-19 16:49:52
* @LastEditors:
* @LastEditTime: 2024-03-19 17:14:46
* @FilePath: /hl-app/src/types/login.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/** 登录信息 */
export type LoginResult = {
/** 用户ID */
// code: number
// data: Object
// /** 昵称 */
// msg?: string
accessToken: string
expiresTime: number
refreshToken: string
userId: number
}

@ -1,50 +0,0 @@
/** 通用的用户信息 */
type BaseProfile = {
/** 用户ID */
id: number
/** 头像 */
avatar: string
/** 账户名 */
account: string
/** 昵称 */
nickname?: string
}
/** 小程序登录 登录用户信息 */
export type LoginResult = {
id: string
openid: string
phone: string
/** 登录凭证 */
token: string
userType: Object
username: string
}
/** 个人信息 用户详情信息 */
export type ProfileDetail = BaseProfile & {
/** 性别 */
gender?: Gender
/** 生日 */
birthday?: string
/** 省市区 */
fullLocation?: string
/** 职业 */
profession?: string
}
/** 性别 */
export type Gender = '女' | '男'
/** 个人信息 修改请求体参数 */
export type ProfileParams = Pick<
ProfileDetail,
'nickname' | 'gender' | 'birthday' | 'profession'
> & {
/** 省份编码 */
provinceCode?: string
/** 城市编码 */
cityCode?: string
/** 区/县编码 */
countyCode?: string
}

@ -1,165 +0,0 @@
import type { OrderState } from '@/services/constants'
import type { AddressItem } from './address'
import type { PageParams } from '@/types/global'
/** 获取预付订单 返回信息 */
export type OrderPreResult = {
/** 商品集合 [ 商品信息 ] */
goods: OrderPreGoods[]
/** 结算信息 */
summary: {
/** 商品总价 */
totalPrice: number
/** 邮费 */
postFee: number
/** 应付金额 */
totalPayPrice: number
}
/** 用户地址列表 [ 地址信息 ] */
userAddresses: AddressItem[]
}
/** 商品信息 */
export type OrderPreGoods = {
/** 属性文字,例如“颜色:瓷白色 尺寸8寸” */
attrsText: string
/** 数量 */
count: number
/** id */
id: string
/** 商品名称 */
name: string
/** 实付单价 */
payPrice: string
/** 图片 */
picture: string
/** 原单价 */
price: string
/** SKUID */
skuId: string
/** 实付价格小计 */
totalPayPrice: string
/** 小计总价 */
totalPrice: string
}
/** 提交订单 请求参数 */
export type OrderCreateParams = {
/** 所选地址Id */
addressId: string
/** 配送时间类型1为不限2为工作日3为双休或假日 */
deliveryTimeType: number
/** 订单备注 */
buyerMessage: string
/** 商品集合[ 商品信息 ] */
goods: {
/** 数量 */
count: number
/** skuId */
skuId: string
}[]
/** 支付渠道支付渠道1支付宝、2微信--支付方式为在线支付时,传值,为货到付款时,不传值 */
payChannel: 1 | 2
/** 支付方式1为在线支付2为货到付款 */
payType: 1 | 2
}
/** 提交订单 返回信息 */
export type OrderCreateResult = {
/** 订单Id */
id: string
}
/** 订单详情 返回信息 */
export type OrderResult = {
/** 订单编号 */
id: string
/** 订单状态1为待付款、2为待发货、3为待收货、4为待评价、5为已完成、6为已取消 */
orderState: OrderState
/** 倒计时--剩余的秒数 -1 表示已经超时,正数表示倒计时未结束 */
countdown: number
/** 商品集合 [ 商品信息 ] */
skus: OrderSkuItem[]
/** 收货人 */
receiverContact: string
/** 收货人手机 */
receiverMobile: string
/** 收货人地址 */
receiverAddress: string
/** 下单时间 */
createTime: string
/** 商品总价 */
totalMoney: number
/** 运费 */
postFee: number
/** 应付金额 */
payMoney: number
}
/** 商品信息 */
export type OrderSkuItem = {
/** sku id */
id: string
/** 商品 id */
spuId: string
/** 商品名称 */
name: string
/** 商品属性文字 */
attrsText: string
/** 数量 */
quantity: number
/** 购买时单价 */
curPrice: number
/** 图片地址 */
image: string
}
/** 物流信息 返回值类型 */
export type OrderLogisticResult = {
/** 快递公司 */
company: {
/** 公司名称 */
name: string
/** 快递编号 */
number: string
/** 联系电话 */
tel: string
}
/** 商品件数 */
count: number
/** 物流日志 */
list: LogisticItem[]
}
/** 物流日志 */
export type LogisticItem = {
/** 信息ID */
id: string
/** 信息文字 */
text: string
/** 时间 */
time: string
}
/** 订单列表参数 */
export type OrderListParams = PageParams
/** 订单列表 */
export type OrderListResult = {
/** 总记录数 */
counts: number
/** 数据集合 [ 订单信息 ] */
items: OrderItem[]
/** 当前页码 */
page: number
/** 总页数 */
pages: number
/** 页尺寸 */
pageSize: number
}
/** 订单列表项 */
export type OrderItem = OrderResult & {
/** 总件数 */
totalNum: number
}

@ -1,76 +0,0 @@
/**
* uni-app
*
* uni-app https://ext.dcloud.net.cn使
* 使scss使 import 便App
*
*/
/**
* App使
*
* 使scss scss 使 import
*/
/* 颜色变量 */
/* 行为相关颜色 */
$uni-color-primary: #007aff;
$uni-color-success: #4cd964;
$uni-color-warning: #f0ad4e;
$uni-color-error: #dd524d;
/* 文字基本颜色 */
$uni-text-color: #333; //
$uni-text-color-inverse: #fff; //
$uni-text-color-grey: #999; //
$uni-text-color-placeholder: #808080;
$uni-text-color-disable: #c0c0c0;
/* 背景颜色 */
$uni-bg-color: #fff;
$uni-bg-color-grey: #f8f8f8;
$uni-bg-color-hover: #f1f1f1; //
$uni-bg-color-mask: rgba(0, 0, 0, 0.4); //
/* 边框颜色 */
$uni-border-color: #c8c7cc;
/* 尺寸变量 */
/* 文字尺寸 */
$uni-font-size-sm: 12px;
$uni-font-size-base: 14px;
$uni-font-size-lg: 16;
/* 图片尺寸 */
$uni-img-size-sm: 20px;
$uni-img-size-base: 26px;
$uni-img-size-lg: 40px;
/* Border Radius */
$uni-border-radius-sm: 2px;
$uni-border-radius-base: 3px;
$uni-border-radius-lg: 6px;
$uni-border-radius-circle: 50%;
/* 水平间距 */
$uni-spacing-row-sm: 5px;
$uni-spacing-row-base: 10px;
$uni-spacing-row-lg: 15px;
/* 垂直间距 */
$uni-spacing-col-sm: 4px;
$uni-spacing-col-base: 8px;
$uni-spacing-col-lg: 12px;
/* 透明度 */
$uni-opacity-disabled: 0.3; //
/* 文章场景相关 */
$uni-color-title: #2c405a; //
$uni-font-size-title: 20px;
$uni-color-subtitle: #555; //
$uni-font-size-subtitle: 18px;
$uni-color-paragraph: #3f536e; //
$uni-font-size-paragraph: 15px;

@ -1,128 +0,0 @@
/**
* :
* request
* uploadFile
*
* TODO:
* 1. http
* 2.
* 3.
* 4. token
*/
import { useLoginStore } from '@/stores/modules/login'
import { serviceDomain } from '@/services/constants'
const baseURL = serviceDomain + '/admin-api'
const loginStore = useLoginStore()
// 添加拦截器
const httpInterceptor = {
// 拦截前触发
invoke(options: UniApp.RequestOptions) {
// 1. 非 http 开头需拼接地址
if (!options.url.startsWith('http')) {
options.url = baseURL + options.url
}
// 2. 请求超时, 默认 60s
options.timeout = 10000
// 3. 添加小程序端请求头标识
options.header = {
...options.header,
'tenant-id': loginStore.userInfo?.userId || 2,
}
// 4. 添加 token 请求头标识
const storage_token = uni.getStorageSync('storage_loginInfo')?.accessToken
const token = loginStore.userInfo?.accessToken || storage_token
if (token) {
options.header.Authorization = token
}
},
}
uni.addInterceptor('request', httpInterceptor)
uni.addInterceptor('uploadFile', httpInterceptor)
/**
*
* @param UniApp.RequestOptions
* @returns Promise
* 1. Promise
* 2.
* 2.1 res.data
* 2.2
* 3.
* 3.1 401 ->
* 3.2 ->
* 3.3 ->
*/
type Data<T> = {
code: string
msg: string
result: T
}
function ajaxError(data) {
uni.showToast({
title: data.msg || '请求出错,请重试',
duration: 3000,
icon: 'none',
complete() {
if (data.code === 600 || data.code === 601 || data.code === 602) {
const memberStore = useMemberStore()
memberStore.clearProfile()
uni.reLaunch({
url: '/pages/login/login'
})
}
}
})
}
// 2.2 添加类型,支持泛型
export const http = <T>(options: UniApp.RequestOptions) => {
// 1. 返回 Promise 对象
return new Promise<Data<T>>((resolve, reject) => {
uni.request({
...options,
// 响应成功
success(res) {
console.log(res)
// 状态码 2xx axios 就是这样设计的
if (res.statusCode >= 200 && res.statusCode < 300) {
if (res.data?.code == 0) {
resolve(res.data.data as Data<T>)
} else if (res.data?.code === 401) {
// 401错误 -> 清理用户信息,跳转到登录页
loginStore.clearInfo()
uni.navigateTo({ url: '/pages/login/login' })
reject(res)
} else {
const msg = (res.data as Data<T>).msg
uni.showToast({
icon: 'none',
duration: 3000,
title: msg || '请求错误',
})
reject(res)
}
} else {
// 其他错误 -> 根据后端错误信息轻提示
uni.showToast({
icon: 'none',
duration: 3000,
title: (res.data as Data<T>).msg || '请求错误',
})
reject(res)
}
},
// 响应失败
fail(err) {
uni.showToast({
icon: 'none',
duration: 3000,
title: '网络错误,换个网络试试',
})
reject(err)
},
})
})
}

@ -1,69 +0,0 @@
/*
* @Author:
* @Date: 2024-01-04 12:54:56
* @LastEditors: jevononlie 728254585@qq.com
* @LastEditTime: 2024-04-07 09:36:33
* @FilePath: /app-nx-personal/src/utils/index.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/**
*
* @param date
* @param format YYYY-MM-DD HH:mm:ss
*/
export const formatDate = (datePramas: Date, format = 'YYYY-MM-DD HH:mm:ss') => {
// 获取年月日时分秒,通过 padStart 补 0
const date = new Date(datePramas)
const year = String(date.getFullYear())
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
// 返回格式化后的结果
return format
.replace('YYYY', year)
.replace('MM', month)
.replace('DD', day)
.replace('HH', hours)
.replace('mm', minutes)
.replace('ss', seconds)
}
/**
*
*
* @return {[type]} [return description]
*/
export const updateManager = () => {
const updateManager = uni.getUpdateManager() // 小程序版本更新管理器
updateManager.onCheckForUpdate((res) => {
// 检测新版本后的回调
if (res.hasUpdate) {
// 如果有新版本提醒并进行强制升级
uni.showModal({
content: '新版本已经准备好,是否重启应用?',
showCancel: false,
confirmText: '确定',
success: (res) => {
if (res.confirm) {
updateManager.onUpdateReady((res) => {
// 新版本下载完成的回调
updateManager.applyUpdate() // 强制当前小程序应用上新版本并重启
})
updateManager.onUpdateFailed((res) => {
// 新版本下载失败的回调
// 新版本下载失败,提示用户删除后通过冷启动重新打开
uni.showModal({
content: '下载失败,请删除当前小程序后重新打开',
showCancel: false,
confirmText: '知道了',
})
})
}
},
})
}
})
}

@ -1,24 +0,0 @@
{
"extends": "@vue/tsconfig/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"sourceMap": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
},
"lib": ["esnext", "dom"],
"types": [
"@dcloudio/types",
"miniprogram-api-typings",
"@uni-helper/uni-app-types",
"@uni-helper/uni-ui-types"
]
},
// uni-app
"vueCompilerOptions": {
// experimentalRuntimeMode nativeTags Volar
"nativeTags": ["block", "component", "template", "slot"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save