修改生产页面的显示逻辑,增加可选
编写自定义组件的说明书
4
.env.development
Normal file
@ -0,0 +1,4 @@
|
||||
# 开发环境
|
||||
# 请求接口地址
|
||||
VITE_REQUEST_BASE_URL = https://36.112.48.190
|
||||
#VITE_REQUEST_BASE_URL = http://10.75.166.6:8080
|
||||
3
.env.production
Normal file
@ -0,0 +1,3 @@
|
||||
# 生产环境
|
||||
# 请求接口地址
|
||||
VITE_REQUEST_BASE_URL = https://36.112.48.190
|
||||
65
.gitignore
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
/unpackage/
|
||||
/unpackage/cache/apk/__UNI__9F097F0_cm.apk
|
||||
/unpackage/cache/apk/apkurl
|
||||
/unpackage/cache/apk/cmManifestCache.json
|
||||
/unpackage/cache/certdata
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/app-config-service.js
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/app-service.js
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/app.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/manifest.json
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/checkin/index.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/document/detail.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/document/index.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/leave/application.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/login/login.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/meeting/detail.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/meeting/index.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/product/index.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/safe/detail.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/safe/manage.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/tab/index.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/tab/my.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/tab/office.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/talk/conversation.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/talk/message_list.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/talk/system.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/task/handle.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/task/index.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/task/self.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/task/todotask.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/useredit/add_address.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/useredit/address.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/useredit/addressbook.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/useredit/useredit.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/userlist/index.css
|
||||
/unpackage/cache/wgt/__UNI__9F097F0/pages/views/zhongheguanli/zhiban/index.css
|
||||
/unpackage/dist/build/app-plus/__uniappautomator.js
|
||||
/unpackage/dist/build/app-plus/__uniappchooselocation.js
|
||||
/unpackage/dist/build/app-plus/app-config-service.js
|
||||
/unpackage/dist/build/app-plus/app-service.js
|
||||
/unpackage/dist/build/app-plus/app.css
|
||||
/unpackage/dist/build/app-plus/manifest.json
|
||||
/unpackage/dist/build/app-plus/pages/document/detail.css
|
||||
/unpackage/dist/build/app-plus/pages/leave/application.css
|
||||
/unpackage/dist/build/app-plus/pages/login/login.css
|
||||
/unpackage/dist/build/app-plus/pages/tab/index.css
|
||||
/unpackage/dist/build/app-plus/pages/tab/my.css
|
||||
/unpackage/dist/build/app-plus/pages/useredit/useredit.css
|
||||
/unpackage/dist/build/app-plus/uni-app-view.umd.js
|
||||
/unpackage/dist/dev/app-plus/__uniappautomator.js
|
||||
/unpackage/dist/dev/app-plus/__uniappchooselocation.js
|
||||
/unpackage/dist/dev/app-plus/app-config-service.js
|
||||
/unpackage/dist/dev/app-plus/app-service.js
|
||||
/unpackage/dist/dev/app-plus/app.css
|
||||
/unpackage/dist/dev/app-plus/manifest.json
|
||||
/unpackage/dist/dev/app-plus/uni-app-view.umd.js
|
||||
/node_modules/.vite/deps/_metadata.json
|
||||
/node_modules/.vite/deps/base-64.js
|
||||
/node_modules/.vite/deps/base-64.js.map
|
||||
/node_modules/.vite/deps/chunk-RSJERJUL.js
|
||||
/node_modules/.vite/deps/chunk-RSJERJUL.js.map
|
||||
/node_modules/.vite/deps/dayjs.js
|
||||
/node_modules/.vite/deps/dayjs.js.map
|
||||
/node_modules/.vite/deps/package.json
|
||||
/uni_modules
|
||||
/node_modules
|
||||
26
.hbuilderx/launch.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
// launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
|
||||
// launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
|
||||
"version" : "0.0",
|
||||
"configurations" : [
|
||||
{
|
||||
"app-plus" :
|
||||
{
|
||||
"launchtype" : "local"
|
||||
},
|
||||
"default" :
|
||||
{
|
||||
"launchtype" : "local"
|
||||
},
|
||||
"mp-weixin" :
|
||||
{
|
||||
"launchtype" : "local"
|
||||
},
|
||||
"type" : "uniCloud"
|
||||
},
|
||||
{
|
||||
"playground" : "standard",
|
||||
"type" : "uni-app:app-android"
|
||||
}
|
||||
]
|
||||
}
|
||||
13
.vite/deps/_metadata.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"hash": "5610b5a1",
|
||||
"browserHash": "3deef0d9",
|
||||
"optimized": {
|
||||
"base-64": {
|
||||
"src": "../../node_modules/base-64/base64.js",
|
||||
"file": "base-64.js",
|
||||
"fileHash": "768aae23",
|
||||
"needsInterop": true
|
||||
}
|
||||
},
|
||||
"chunks": {}
|
||||
}
|
||||
117
.vite/deps/base-64.js
Normal file
@ -0,0 +1,117 @@
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __commonJS = (cb, mod) => function __require() {
|
||||
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
||||
};
|
||||
|
||||
// ../../../../Documents/HBuilderProjects/B404219-tianranqi/node_modules/base-64/base64.js
|
||||
var require_base64 = __commonJS({
|
||||
"../../../../Documents/HBuilderProjects/B404219-tianranqi/node_modules/base-64/base64.js"(exports, module) {
|
||||
(function(root) {
|
||||
var freeExports = typeof exports == "object" && exports;
|
||||
var freeModule = typeof module == "object" && module && module.exports == freeExports && module;
|
||||
var freeGlobal = typeof global == "object" && global;
|
||||
if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
|
||||
root = freeGlobal;
|
||||
}
|
||||
var InvalidCharacterError = function(message) {
|
||||
this.message = message;
|
||||
};
|
||||
InvalidCharacterError.prototype = new Error();
|
||||
InvalidCharacterError.prototype.name = "InvalidCharacterError";
|
||||
var error = function(message) {
|
||||
throw new InvalidCharacterError(message);
|
||||
};
|
||||
var TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
var REGEX_SPACE_CHARACTERS = /[\t\n\f\r ]/g;
|
||||
var decode = function(input) {
|
||||
input = String(input).replace(REGEX_SPACE_CHARACTERS, "");
|
||||
var length = input.length;
|
||||
if (length % 4 == 0) {
|
||||
input = input.replace(/==?$/, "");
|
||||
length = input.length;
|
||||
}
|
||||
if (length % 4 == 1 || // http://whatwg.org/C#alphanumeric-ascii-characters
|
||||
/[^+a-zA-Z0-9/]/.test(input)) {
|
||||
error(
|
||||
"Invalid character: the string to be decoded is not correctly encoded."
|
||||
);
|
||||
}
|
||||
var bitCounter = 0;
|
||||
var bitStorage;
|
||||
var buffer;
|
||||
var output = "";
|
||||
var position = -1;
|
||||
while (++position < length) {
|
||||
buffer = TABLE.indexOf(input.charAt(position));
|
||||
bitStorage = bitCounter % 4 ? bitStorage * 64 + buffer : buffer;
|
||||
if (bitCounter++ % 4) {
|
||||
output += String.fromCharCode(
|
||||
255 & bitStorage >> (-2 * bitCounter & 6)
|
||||
);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
};
|
||||
var encode = function(input) {
|
||||
input = String(input);
|
||||
if (/[^\0-\xFF]/.test(input)) {
|
||||
error(
|
||||
"The string to be encoded contains characters outside of the Latin1 range."
|
||||
);
|
||||
}
|
||||
var padding = input.length % 3;
|
||||
var output = "";
|
||||
var position = -1;
|
||||
var a;
|
||||
var b;
|
||||
var c;
|
||||
var buffer;
|
||||
var length = input.length - padding;
|
||||
while (++position < length) {
|
||||
a = input.charCodeAt(position) << 16;
|
||||
b = input.charCodeAt(++position) << 8;
|
||||
c = input.charCodeAt(++position);
|
||||
buffer = a + b + c;
|
||||
output += TABLE.charAt(buffer >> 18 & 63) + TABLE.charAt(buffer >> 12 & 63) + TABLE.charAt(buffer >> 6 & 63) + TABLE.charAt(buffer & 63);
|
||||
}
|
||||
if (padding == 2) {
|
||||
a = input.charCodeAt(position) << 8;
|
||||
b = input.charCodeAt(++position);
|
||||
buffer = a + b;
|
||||
output += TABLE.charAt(buffer >> 10) + TABLE.charAt(buffer >> 4 & 63) + TABLE.charAt(buffer << 2 & 63) + "=";
|
||||
} else if (padding == 1) {
|
||||
buffer = input.charCodeAt(position);
|
||||
output += TABLE.charAt(buffer >> 2) + TABLE.charAt(buffer << 4 & 63) + "==";
|
||||
}
|
||||
return output;
|
||||
};
|
||||
var base64 = {
|
||||
"encode": encode,
|
||||
"decode": decode,
|
||||
"version": "1.0.0"
|
||||
};
|
||||
if (typeof define == "function" && typeof define.amd == "object" && define.amd) {
|
||||
define(function() {
|
||||
return base64;
|
||||
});
|
||||
} else if (freeExports && !freeExports.nodeType) {
|
||||
if (freeModule) {
|
||||
freeModule.exports = base64;
|
||||
} else {
|
||||
for (var key in base64) {
|
||||
base64.hasOwnProperty(key) && (freeExports[key] = base64[key]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
root.base64 = base64;
|
||||
}
|
||||
})(exports);
|
||||
}
|
||||
});
|
||||
export default require_base64();
|
||||
/*! Bundled license information:
|
||||
|
||||
base-64/base64.js:
|
||||
(*! https://mths.be/base64 v1.0.0 by @mathias | MIT license *)
|
||||
*/
|
||||
//# sourceMappingURL=base-64.js.map
|
||||
7
.vite/deps/base-64.js.map
Normal file
3
.vite/deps/package.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
80
App.vue
Normal file
@ -0,0 +1,80 @@
|
||||
<script setup>
|
||||
import {
|
||||
useUpdateApp
|
||||
} from '@/store/update.js';
|
||||
import {
|
||||
cxcJurisdictionApi
|
||||
} from '@/api/api.js';
|
||||
import {
|
||||
onLaunch,
|
||||
onShow
|
||||
} from "@dcloudio/uni-app";
|
||||
import {
|
||||
getLocation,
|
||||
getWeather,
|
||||
} from './utils/index.js';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
import {
|
||||
ref
|
||||
} from 'vue';
|
||||
onLaunch(() => {
|
||||
// 检查更新
|
||||
useUpdateApp().checkAppUpdate()
|
||||
// 定位
|
||||
getLocation()
|
||||
})
|
||||
onShow(() => {
|
||||
//是否灰化
|
||||
ifGray()
|
||||
})
|
||||
|
||||
const ifGray = () => {
|
||||
cxcJurisdictionApi({
|
||||
id: "1827997127165677570"
|
||||
}).then((res) => {
|
||||
// console.log(res)
|
||||
// 1为灰化
|
||||
if (res.success) {
|
||||
const store = useStore()
|
||||
uni.setStorageSync('isgray', res.result.value)
|
||||
store.setIsgray(res.result.value)
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/*每个页面公共css */
|
||||
|
||||
.gray {
|
||||
filter: grayscale(1);
|
||||
}
|
||||
|
||||
.f-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.f-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.jca {
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.jce {
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.jcb {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.aic {
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
20
README.md
Normal file
@ -0,0 +1,20 @@
|
||||
数智产销APP正式版
|
||||
|
||||
|
||||
发布需要在pages/login/login.vue中
|
||||
将
|
||||
```javascript
|
||||
localLoginApi({
|
||||
username: username.value,
|
||||
password: password.value,
|
||||
captcha: 'app'
|
||||
```
|
||||
改成
|
||||
|
||||
```javascript
|
||||
loginApi({
|
||||
username: un,
|
||||
password: pw,
|
||||
ip: getDeviceIp()
|
||||
```
|
||||
|
||||
271
api/api.js
Normal file
@ -0,0 +1,271 @@
|
||||
import {
|
||||
https
|
||||
} from '@/utils/http.js';
|
||||
export function taskListApi(config) { // 我的任务列表
|
||||
return https({
|
||||
url: '/act/task/list',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function taskHistoryListApi(config) { // 我的历史任务列表
|
||||
return https({
|
||||
url: '/act/task/taskHistoryList',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function myApplyProcessListApi(config) { // 本人发起列表
|
||||
return https({
|
||||
url: '/act/task/myApplyProcessList',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
|
||||
export function taskEntrustApi(config) { // 任务委托操作
|
||||
return https({
|
||||
url: '/act/task/taskEntrust',
|
||||
method: 'put',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function getProcessNodeInfoApi(config) { // 办理任务节点信息获取
|
||||
return https({
|
||||
url: '/process/extActProcessNode/getProcessNodeInfo',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function getHisProcessNodeInfoApi(config) { // 历史任务详情
|
||||
return https({
|
||||
url: '/process/extActProcessNode/getHisProcessNodeInfo',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function queryMyDeptTreeListApi(config) { // 部门
|
||||
return https({
|
||||
url: '/sys/sysDepart/queryTreeList',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function userListApi(config) { // 所有人员列表
|
||||
return https({
|
||||
url: '/sys/user/userList',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function queryUserByDepIdApi(config) { // 根据部门id查询该部门下的人员列表
|
||||
return https({
|
||||
url: '/sys/user/queryUserByDepId',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function indexChartScdtDataApi(config) { // 首页
|
||||
return https({
|
||||
url: '/scdt.cxcscdtjldrb/cxcScdtJldRb/indexChartScdtData',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function gongwenlistApi(config) { // 公文
|
||||
return https({
|
||||
url: '/cxcoagwfb/cxcOaGwfb/bpmlist',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function gonggaolistApi(config) { // 公告
|
||||
return https({
|
||||
url: '/cxctz/cxcTz/list',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function zhibanQueryApi(config) { // 值班按月查看
|
||||
return https({
|
||||
url: '/zhgl_zbgl/zhglZbglZbb/list',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function zhibanApi(config) { // 首页值班
|
||||
return https({
|
||||
url: '/zhgl_zbgl/zhglZbglZbb/homepageList',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function faguiApi(config) { // 法规
|
||||
return https({
|
||||
url: '/cxcoaflgf/cxcOaFlgf/zslist',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function cjzhiduApi(config) { // 上级制度
|
||||
return https({
|
||||
url: '/cxcjyglsjzdgl/cxcJyglSjzdgl/zslist',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function zhiduApi(config) { // 厂级制度
|
||||
return https({
|
||||
url: '/cxczd/cxcZdgl/list',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function huiyilistApi(config) { // 会议
|
||||
return https({
|
||||
url: '/appConnet/app/list',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function huiyiDetailApi(config) { // 会议详情
|
||||
return https({
|
||||
url: '/zhgl_hygl/zhglHyglHyyc/listbymainid',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function userProfileApi(config) { // 用户信息
|
||||
return https({
|
||||
url: '/sys/user/userList',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function userEditApi(config) { // 用户编辑
|
||||
return https({
|
||||
url: '/sys/user/editApp',
|
||||
method: 'PUT',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function extActFlowDataApi(config) { // 获取审批流程所需参数
|
||||
return https({
|
||||
url: '/process/extActFlowData/getProcessInfo',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
|
||||
export function processHistoryListApi(config) { // 审批流程
|
||||
return https({
|
||||
url: '/act/task/processHistoryList',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function startMutilProcessApi(config) { // 发起流程
|
||||
return https({
|
||||
url: '/process/extActProcess/startMutilProcess',
|
||||
method: 'post',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function processCompleteApi(config) { // 流程办理
|
||||
return https({
|
||||
url: '/act/task/processComplete',
|
||||
method: 'post',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function claimApi(config) { // 流程签收
|
||||
return https({
|
||||
url: '/act/task/claim',
|
||||
method: 'put',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function callBackProcessApi(config) { // 流程取回
|
||||
return https({
|
||||
url: '/act/task/callBackProcess',
|
||||
method: 'put',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function invalidProcessApi(config) { // 流程作废
|
||||
return https({
|
||||
url: '/act/task/invalidProcess',
|
||||
method: 'put',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function getDictItemsApi(dictCode) { // 字典标签专用
|
||||
return https({
|
||||
url: `/sys/dict/getDictItems/${dictCode}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function getCategoryItemsApi(pid) { // 分类字典专用
|
||||
return https({
|
||||
url: '/sys/category/findtree',
|
||||
method: 'get',
|
||||
data: {
|
||||
pid
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function getProcessTaskTransInfoApi(config) { //
|
||||
return https({
|
||||
url: '/act/task/getProcessTaskTransInfo',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function upDateAppApi(config) { // 更新
|
||||
return https({
|
||||
url: '/sys/common/upDateApp',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function cxcDapingApi(config) { // 首页图片
|
||||
return https({
|
||||
url: '/CxcDaping/cxcDaping/list',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function dbSxxqQueryByIdApi(config) { // 督办事项详情
|
||||
return https({
|
||||
url: '/cxcdbxt/dbSxxq/queryById',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function dbJbxxQueryByIdApi(config) { // 督办基本信息
|
||||
return https({
|
||||
url: '/cxcdbxt/dbJbxx/queryById',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
|
||||
export function cxcJurisdictionApi(config) { // 是否灰化
|
||||
return https({
|
||||
url: '/CxcJurisdiction/cxcJurisdiction/queryById',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
16
api/common.js
Normal file
@ -0,0 +1,16 @@
|
||||
import {
|
||||
https
|
||||
} from '@/utils/http.js';
|
||||
/*
|
||||
这是后端系统通用的系统类的基础性的api路径,后续的大家分类建js存放
|
||||
*/
|
||||
|
||||
|
||||
|
||||
export function initDictOption(dictCode) { // 获取部门所有人员信息
|
||||
return https({
|
||||
url: ' /sys/dict/getDictItems',
|
||||
method: 'get',
|
||||
data: dictCode
|
||||
})
|
||||
}
|
||||
23
api/depart.js
Normal file
@ -0,0 +1,23 @@
|
||||
import {
|
||||
https
|
||||
} from '@/utils/http.js';
|
||||
|
||||
export function queryDepByCode(code) { // 获取部门数据
|
||||
return https({
|
||||
url: '/sys/sysDepart/queryDepNameByDepCode',
|
||||
method: 'get',
|
||||
data: {
|
||||
code
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function queryZbDepByLdhth(ldhth) { // 获取人员主表中人员部门
|
||||
return https({
|
||||
url: '/sys/sysDepart/queryZbDepByLdhth',
|
||||
method: 'get',
|
||||
data: {
|
||||
ldhth
|
||||
}
|
||||
})
|
||||
}
|
||||
56
api/leaveApi.js
Normal file
@ -0,0 +1,56 @@
|
||||
import {
|
||||
https
|
||||
} from '@/utils/http.js';
|
||||
|
||||
export function qjAddApi(config) { // 发起请假流程申请
|
||||
return https({
|
||||
url: '/CxcQxj/cxcQxj/add',
|
||||
method: 'post',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function queryZwmcAndExaApi(username) { // 根据username获取职位名称和审批领导列表
|
||||
return https({
|
||||
url: '/CxcQxj/cxcQxj/queryZwmcByUsername',
|
||||
method: 'get',
|
||||
data: {
|
||||
username
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function qjQueryByIdApi(config) { // 通过id查询请假数据 流程用
|
||||
return https({
|
||||
url: '/CxcQxj/cxcQxj/queryById',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
|
||||
export function queryHisDateApi(username) { // 根据username获取最新请假结束日期
|
||||
return https({
|
||||
url: '/CxcQxj/cxcQxj/queryHisDate',
|
||||
method: 'get',
|
||||
data: {
|
||||
username
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function queryLeaveListApi(params) { // 获取所有请假信息
|
||||
return https({
|
||||
url: '/CxcQxj/cxcQxj/list',
|
||||
method: 'get',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
export function countByOrgApi(params) { // 获取所有请假信息
|
||||
return https({
|
||||
url: '/CxcQxj/cxcQxj/countByOrg',
|
||||
method: 'get',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
29
api/login.js
Normal file
@ -0,0 +1,29 @@
|
||||
import { https } from '@/utils/http.js';
|
||||
export function loginApi(config) { // 登录
|
||||
return https({
|
||||
url: '/sys/sinopecLogin',
|
||||
method: 'post',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function localLoginApi(config) { // 本地登录
|
||||
return https({
|
||||
url: '/sys/login',
|
||||
method: 'post',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function queryRoleApi(config) { // 获取角色职位
|
||||
return https({
|
||||
url: '/appConnet/app/queryRoleByRoleIds',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
export function getUserPermissionApi(config) { // 获取权限
|
||||
return https({
|
||||
url: '/sys/permission/getUserPermissionByToken',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
39
api/pages.js
Normal file
@ -0,0 +1,39 @@
|
||||
import {
|
||||
https
|
||||
} from '@/utils/http.js';
|
||||
|
||||
export function qjAddApi(config) { // 发起请假流程申请
|
||||
return https({
|
||||
url: '/CxcQxj/cxcQxj/add',
|
||||
method: 'post',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
|
||||
export function queryZwmcAndExaApi(username) { // 根据username获取职位名称和审批领导列表
|
||||
return https({
|
||||
url: '/CxcQxj/cxcQxj/queryZwmcByUsername',
|
||||
method: 'get',
|
||||
data: {
|
||||
username
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function qjQueryByIdApi(config) { // 通过id查询请假数据 流程用
|
||||
return https({
|
||||
url: '/CxcQxj/cxcQxj/queryById',
|
||||
method: 'get',
|
||||
data: config
|
||||
})
|
||||
}
|
||||
|
||||
export function queryHisDateApi(username) { // 根据username获取最新请假结束日期
|
||||
return https({
|
||||
url: '/CxcQxj/cxcQxj/queryHisDate',
|
||||
method: 'get',
|
||||
data: {
|
||||
username
|
||||
}
|
||||
})
|
||||
}
|
||||
107
api/renyuan.js
Normal file
@ -0,0 +1,107 @@
|
||||
import {
|
||||
https
|
||||
} from '@/utils/http.js';
|
||||
|
||||
export function queryRenyuanByDepartID(orgCode) { // 获取部门所有人员信息
|
||||
return https({
|
||||
url: '/cxc_rlzy.zb/cxcRlzyZb/list',
|
||||
method: 'get',
|
||||
data: orgCode
|
||||
})
|
||||
}
|
||||
|
||||
export function queryGzjlByRyLdhth(ldhth) { // 获取人员工作经历信息
|
||||
return https({
|
||||
url: '/cxc_rlzy.zb/cxcRlzyZb/queryLl',
|
||||
method: 'get',
|
||||
data: ldhth
|
||||
})
|
||||
}
|
||||
|
||||
export function queryQzqkByRyLdhth(ldhth) { // 获取人员证件台账
|
||||
return https({
|
||||
url: '/cxc_rlzy.zb/cxcRlzyZb/queryZjtz',
|
||||
method: 'get',
|
||||
data: ldhth
|
||||
})
|
||||
}
|
||||
|
||||
export function queryJtzycyByRyLdhth(ldhth) { // 获取人员家庭主要成员
|
||||
return https({
|
||||
url: '/cxchrygxxtj/cxcHrYgxxtj/queryJtzycy',
|
||||
method: 'get',
|
||||
data: ldhth
|
||||
})
|
||||
}
|
||||
export function queryXlxxByRyLdhth(ldhth) { // 获取人员学历信息
|
||||
return https({
|
||||
url: '/cxchrygxxtj/cxcHrYgxxtj/listCxcXlxwxxFbByMainId',
|
||||
method: 'get',
|
||||
data: ldhth
|
||||
})
|
||||
}
|
||||
|
||||
export function queryGbxxByRyLdhth(ldhth) { // 获取人员干部信息 专业技术等级信息
|
||||
return https({
|
||||
url: '/cxc_rlzy.gbxx/cxcRlzyGbxx/queryGbxx',
|
||||
method: 'get',
|
||||
data: ldhth
|
||||
})
|
||||
}
|
||||
|
||||
export function queryZyzgdjByRyLdhth(ldhth) { // 获取人员职业资格等级
|
||||
return https({
|
||||
url: '/cxc_rlzy.zb/cxcRlzyZb/queryZyzgdj',
|
||||
method: 'get',
|
||||
data: ldhth
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function queryJxkhByRyLdhth(ldhth) { // 绩效考核信息
|
||||
return https({
|
||||
url: '/cxc_rlzy.zb/cxcRlzyZb/listCxcRlzyJxkhByMainId',
|
||||
method: 'get',
|
||||
data: ldhth
|
||||
})
|
||||
}
|
||||
|
||||
export function cxcHrYgxxtj(parm) { // 获取员工信息统计
|
||||
return https({
|
||||
url: '/cxchrygxxtj/cxcHrYgxxtj/list',
|
||||
method: 'get',
|
||||
data: parm
|
||||
})
|
||||
}
|
||||
|
||||
export function cxcRyDataTongji(url, parm) { // 员工信息统计
|
||||
return https({
|
||||
url: url,
|
||||
method: 'get',
|
||||
data: parm
|
||||
})
|
||||
}
|
||||
|
||||
export function cxcRyDatAstatistics(parm) { // 员工分组统计
|
||||
return https({
|
||||
url: '/cxc_rlzy.zb/cxcRlzyZb/statistics',
|
||||
method: 'get',
|
||||
data: parm
|
||||
})
|
||||
}
|
||||
|
||||
export function cxcRyDatAstatisticsCertificate(parm) { // 员工按证件分组统计
|
||||
return https({
|
||||
url: '/cxc_rlzy.zb/cxcRlzyZb/getStatisticsCertificate',
|
||||
method: 'get',
|
||||
data: parm
|
||||
})
|
||||
}
|
||||
|
||||
export function cxcRyDatAstatisticsDetails(parm) { // 员工信息统计
|
||||
return https({
|
||||
url: '/cxc_rlzy.zb/cxcRlzyZb/details',
|
||||
method: 'get',
|
||||
data: parm
|
||||
})
|
||||
}
|
||||
37
api/shengchan.js
Normal file
@ -0,0 +1,37 @@
|
||||
import {
|
||||
https
|
||||
} from '@/utils/http.js';
|
||||
|
||||
export function queryJinriShengchansj(params) { // 获取今日天然气生产数据
|
||||
return https({
|
||||
url: '/scdt.CxcScdtChart/cxcScdtChart/list',
|
||||
method: 'get',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
export function queryJinriTrqShengchansj(params) { // 获取当前日期、今年以来天然气的生产数据 day gas unit
|
||||
return https({
|
||||
url: '/scdt.CxcScdtChart/cxcScdtChart/getStatisticsData',
|
||||
method: 'get',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function queryYearShengchansj(params) { // 获取今年以来天然气的生产数据
|
||||
return https({
|
||||
url: '/scdt.CxcScdtChart/cxcScdtChart/getYearStatis',
|
||||
method: 'get',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
|
||||
export function queryJinriYuanyouShengchansj(params) { // 获取今日原油 污油产量
|
||||
return https({
|
||||
url: '/scdt.cxcscdtwyrb/cxcScdtWyRb/list',
|
||||
method: 'get',
|
||||
data: params
|
||||
})
|
||||
}
|
||||
36
bpm/customNav.vue
Normal file
@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<view class="">
|
||||
<view class="nav ">
|
||||
<slot></slot>
|
||||
</view>
|
||||
<view class="place">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const res = wx.getSystemInfoSync();
|
||||
const statusHeight = res.statusBarHeight; //状态栏高度
|
||||
const cusnavbarheight = (statusHeight + 44) + "px";
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.nav {
|
||||
width: calc(100% - 60rpx);
|
||||
padding: 0 30rpx;
|
||||
height: v-bind(cusnavbarheight);
|
||||
background: linear-gradient(270deg, #256FBC 0%, #044D87 100%);
|
||||
|
||||
font-size: 24rpx;
|
||||
color: #FFFFFF;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.place {
|
||||
height: v-bind(cusnavbarheight);
|
||||
}
|
||||
</style>
|
||||
143
bpm/dataCom.vue
Normal file
@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<view class="">
|
||||
<view class="info">
|
||||
<view class="item_box">
|
||||
<view class="item">
|
||||
<view class="title_box f-row aic jcb">
|
||||
<view class="title">
|
||||
{{title}}
|
||||
</view>
|
||||
<view class="f-row aic more" v-if="list.length>6" @click="open=!open">
|
||||
<text>{{!open?'展开':'收起'}}</text>
|
||||
<uni-icons type="down" color="#999999" v-if="!open"></uni-icons>
|
||||
<uni-icons type="up" color="#999999" v-else></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view :class="['data_wrapper',{'close':list.length>6&&open}]">
|
||||
<view class="data_box f-row aic ">
|
||||
<view class="data f-col aic" v-for="item,i in list">
|
||||
<view class="">
|
||||
{{item?.dailyVolume}}
|
||||
</view>
|
||||
<text>{{item.gas}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
computed,
|
||||
watch,
|
||||
nextTick
|
||||
} from 'vue';
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default: function() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
})
|
||||
const open = ref(false)
|
||||
const moreHeight = ref(null)
|
||||
|
||||
watch(() => props.list, () => {
|
||||
nextTick(() => {
|
||||
uni.createSelectorQuery().select('.data_box').boundingClientRect(data => {
|
||||
moreHeight.value = (data?.height || 0) + 'px'
|
||||
}).exec()
|
||||
})
|
||||
|
||||
}, {
|
||||
immediate: true
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page {
|
||||
background-color: #F8F8F8;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.data_wrapper {
|
||||
height: 288rpx;
|
||||
transition: all .3s;
|
||||
overflow: hidden;
|
||||
}
|
||||
.close {
|
||||
height: v-bind(moreHeight);
|
||||
}
|
||||
|
||||
.info {
|
||||
.item_box {
|
||||
|
||||
.item {
|
||||
width: 690rpx;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx 0;
|
||||
margin-top: 24rpx;
|
||||
|
||||
.title_box {
|
||||
padding: 0 30rpx;
|
||||
margin-bottom: -20rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
background-image: url('../../static/index/line.png');
|
||||
background-size: 44rpx 13rpx;
|
||||
background-repeat: no-repeat;
|
||||
background-position: left bottom;
|
||||
|
||||
}
|
||||
|
||||
.more {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
|
||||
text {
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.data_box {
|
||||
|
||||
flex-wrap: wrap;
|
||||
.data {
|
||||
width: 33.33%;
|
||||
margin-top: 60rpx;
|
||||
height: 80rpx;
|
||||
|
||||
view {
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
margin-bottom: 8rpx;
|
||||
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 24rpx;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
203
bpm/extendCom.vue
Normal file
@ -0,0 +1,203 @@
|
||||
<template>
|
||||
<view class="content">
|
||||
<view class="todo f-col aic">
|
||||
<view class="f-col aic">
|
||||
<view class="title_box f-row aic jcb" @click="tolist('')">
|
||||
<view class="title f-row aic">
|
||||
<image :src="`/static/my/${img}.png`" mode=""></image>
|
||||
{{title}}
|
||||
</view>
|
||||
<view class="num">
|
||||
{{total}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="list" v-if="list.length">
|
||||
<view :class="['box',{'close':list.length>5&&open}]">
|
||||
<view class="item_box">
|
||||
<view @click="tolist(item.title)" class="item f-row aic" v-for="item,i in list" :key="i">
|
||||
<view class="">
|
||||
{{item.title}}
|
||||
</view>
|
||||
<text>{{item.num}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="more" v-show="list.length>5" @click="open = !open">
|
||||
{{!open?'显示更多':'收起'}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
onMounted,
|
||||
nextTick,
|
||||
computed,
|
||||
watch,
|
||||
getCurrentInstance
|
||||
} from 'vue';
|
||||
import {
|
||||
beforeJump
|
||||
} from '@/utils/index.js';
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
img: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default: function() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
total: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
type:{
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
const open = ref(false)
|
||||
const moreHeight = ref(null)
|
||||
const CurrentInstance = getCurrentInstance()
|
||||
watch(() => props.list, () => {
|
||||
nextTick(() => {
|
||||
uni.createSelectorQuery().in(CurrentInstance.proxy).select('.item_box')
|
||||
.boundingClientRect(data => {
|
||||
moreHeight.value = data?.height + 'px'
|
||||
}).exec()
|
||||
})
|
||||
|
||||
}, {
|
||||
immediate: true
|
||||
})
|
||||
const tolist = (title) => {
|
||||
let id = null
|
||||
beforeJump('/pages/task/index', () => {
|
||||
|
||||
if (props.type == '0') {
|
||||
id = 0
|
||||
}
|
||||
if (props.type == '1') {
|
||||
id = 1
|
||||
}
|
||||
if (props.type == '2') {
|
||||
return uni.navigateTo({
|
||||
url: `/pages/task/self?title=${title}`
|
||||
})
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: `/pages/task/index?id=${id}&title=${title}`
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page {
|
||||
background-color: #F8F8F8;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
padding-top: 30rpx;
|
||||
}
|
||||
|
||||
.todo {
|
||||
.title_box {
|
||||
width: 630rpx;
|
||||
height: 108rpx;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 6rpx 0rpx rgba(0, 0, 0, 0.16);
|
||||
border-radius: 16rpx;
|
||||
padding: 0 30rpx;
|
||||
|
||||
.title {
|
||||
image {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
|
||||
font-weight: 500;
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.num {
|
||||
width: 54rpx;
|
||||
height: 54rpx;
|
||||
background: url('../../static/my/num.png') no-repeat;
|
||||
background-size: 54rpx 54rpx;
|
||||
font-size: 24rpx;
|
||||
color: #FFFFFF;
|
||||
text-align: center;
|
||||
line-height: 54rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.list {
|
||||
width: 570rpx;
|
||||
padding: 20rpx 30rpx 30rpx 30rpx;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 6rpx 0rpx rgba(0, 0, 0, 0.16);
|
||||
border-radius: 0rpx 0rpx 16rpx 16rpx;
|
||||
|
||||
.box {
|
||||
|
||||
max-height: 120rpx;
|
||||
transition: all .3s;
|
||||
overflow: hidden;
|
||||
|
||||
.item_box {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.item {
|
||||
font-size: 28rpx;
|
||||
height: 60rpx;
|
||||
width: 50%;
|
||||
|
||||
view {
|
||||
color: #666666;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
-o-text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
text {
|
||||
color: #ED361D;
|
||||
margin: 0 10rpx;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.close {
|
||||
// height: 300rpx;
|
||||
max-height: v-bind(moreHeight);
|
||||
}
|
||||
|
||||
.more {
|
||||
font-size: 28rpx;
|
||||
color: #008DFF;
|
||||
text-decoration: underline;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
335
bpm/leaveApplication/index.vue
Normal file
@ -0,0 +1,335 @@
|
||||
<template>
|
||||
<view class="f-col aic">
|
||||
<view class="info_box">
|
||||
<view class="title">
|
||||
申请信息
|
||||
<b style="text-align: right;color: blue;" @click="goToHis">历史查询</b>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
请假职工:
|
||||
</view>
|
||||
<text>{{info.username_dictText}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
所属单位:
|
||||
</view>
|
||||
<text>{{info.sysOrgCode_dictText}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
联系方式:
|
||||
</view>
|
||||
<text>{{info.phone}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
请假类型:
|
||||
</view>
|
||||
<text>{{info.type}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
请假开始时间:
|
||||
</view>
|
||||
<text>{{info.begintime}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
请假结束时间:
|
||||
</view>
|
||||
<text>{{info.endtime}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
请假天数:
|
||||
</view>
|
||||
<text>{{info.days}}天</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
{{examineleader}}:
|
||||
</view>
|
||||
<text>{{info.examineleader_dictText}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
出发地:
|
||||
</view>
|
||||
<text>{{info.departure}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
目的地:
|
||||
</view>
|
||||
<text>{{info.destination}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
请假原因:
|
||||
</view>
|
||||
<text>{{info.reason}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb" v-if="ifShowFj">
|
||||
<view>
|
||||
附件:
|
||||
</view>
|
||||
<uni-file-picker v-model="imageValue" :image-styles="imageStyles" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="f-col aic">
|
||||
<view class="progress">
|
||||
<view class="title">
|
||||
审批流程
|
||||
</view>
|
||||
<view class="progress_box">
|
||||
<view class="box" v-for="(item,index) in step" :key="index">
|
||||
<view class="topic f-row aic">
|
||||
<view>
|
||||
{{item.name}}
|
||||
</view>
|
||||
<view
|
||||
:class="['status',{'complete':item.deleteReason=='已完成'},{'refuse':item.deleteReason=='已拒绝'}]">
|
||||
{{item.deleteReason}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="name_time">
|
||||
{{item.assigneeName}} | {{item.endTime}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
extActFlowDataApi,
|
||||
processHistoryListApi
|
||||
} from '@/api/api.js';
|
||||
import {
|
||||
qjQueryByIdApi
|
||||
} from '@/api/leaveApi.js';
|
||||
import {
|
||||
ref,
|
||||
onMounted
|
||||
} from 'vue'
|
||||
import {
|
||||
imgUrl
|
||||
} from '@/utils/index.js';
|
||||
const props = defineProps({
|
||||
dataId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
})
|
||||
const examineleader = ref('')
|
||||
const imageValue = ref([])
|
||||
const ifShowFj = ref(false)
|
||||
const imageStyles = {
|
||||
width: 64,
|
||||
height: 64,
|
||||
border: {
|
||||
color: "#dce7e1",
|
||||
width: 2,
|
||||
style: 'dashed',
|
||||
radius: '2px'
|
||||
}
|
||||
}
|
||||
const info = ref({})
|
||||
// 申请信息
|
||||
const qjQueryById = () => {
|
||||
qjQueryByIdApi({
|
||||
id: props.dataId
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
if (res.result.records[0].zwmc == '单位专家' || res.result.records[0].zwmc == '基层正职' ||
|
||||
res.result.records[0].zwmc == '高级主管') {
|
||||
examineleader.value = '分管领导';
|
||||
} else {
|
||||
examineleader.value = '审批领导';
|
||||
}
|
||||
info.value = res.result.records[0]
|
||||
// 构造 imageValue 数组
|
||||
if (info.value.path) {
|
||||
ifShowFj.value = true;
|
||||
imageValue.value = info.value.path.split(',').map(path => {
|
||||
const name = path.split('/').pop(); // 获取文件名
|
||||
const extname = name.split('.').pop(); // 获取文件扩展名并转换为大写
|
||||
return {
|
||||
name,
|
||||
extname,
|
||||
url: imgUrl(path)
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**审批步骤*/
|
||||
const extActFlowData = () => {
|
||||
extActFlowDataApi({
|
||||
flowCode: "dev_cxc_qxj",
|
||||
dataId: props.dataId
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
processHistoryList(res.result.processInstanceId)
|
||||
}
|
||||
})
|
||||
}
|
||||
const step = ref([])
|
||||
const processHistoryList = (processInstanceId) => {
|
||||
processHistoryListApi({
|
||||
processInstanceId
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
step.value = res.result.records
|
||||
step.value = step.value.map(item => {
|
||||
if (item.name === 'start') {
|
||||
item.name = '开始';
|
||||
} else if (item.name === 'end') {
|
||||
item.name = '结束';
|
||||
}
|
||||
return item;
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
onMounted(() => {
|
||||
qjQueryById()
|
||||
extActFlowData()
|
||||
})
|
||||
|
||||
const goToHis = () => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/views/renliziyuan/qingjiaxinxi/index?username=${info.value.username}`
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.info_box {
|
||||
padding: 40rpx 30rpx 16rpx 30rpx;
|
||||
width: 630rpx;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
margin-top: 30rpx;
|
||||
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
background-image: url(../../static/index/line.png);
|
||||
background-size: 44rpx 12rpx;
|
||||
background-repeat: no-repeat;
|
||||
background-position: left bottom;
|
||||
margin-bottom: 30rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.info {
|
||||
font-size: 28rpx;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
view {
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
text {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.progress {
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
width: 630rpx;
|
||||
padding: 40rpx 30rpx 16rpx 30rpx;
|
||||
margin-top: 30rpx;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.status {
|
||||
padding: 4rpx 8rpx;
|
||||
display: inline-block;
|
||||
|
||||
color: #FFFFFF;
|
||||
font-size: 20rpx;
|
||||
margin-left: 8rpx;
|
||||
border-radius: 8rpx;
|
||||
|
||||
}
|
||||
|
||||
.complete {
|
||||
background-color: #7AC756;
|
||||
}
|
||||
|
||||
.refuse {
|
||||
background-color: #FE4600;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
background-image: url(../../static/index/line.png);
|
||||
background-size: 44rpx 12rpx;
|
||||
background-repeat: no-repeat;
|
||||
background-position: left bottom;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
}
|
||||
|
||||
// .box:not(:first-child) {
|
||||
// padding-top: 60rpx;
|
||||
// }
|
||||
.box:not(:last-child) {
|
||||
position: relative;
|
||||
padding-bottom: 60rpx;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
content: ' ';
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
background: #efefef;
|
||||
left: -42rpx;
|
||||
top: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.box {
|
||||
margin-left: 50rpx;
|
||||
|
||||
|
||||
.topic {
|
||||
position: relative;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
content: ' ';
|
||||
width: 18rpx;
|
||||
height: 18rpx;
|
||||
background: #01508B;
|
||||
border-radius: 14rpx;
|
||||
left: -50rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.name_time {
|
||||
font-size: 24rpx;
|
||||
color: #888888;
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
62
bpm/processCom.vue
Normal file
@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<view class="f-col aic">
|
||||
<view class="info_box">
|
||||
<view class="title">
|
||||
申请信息
|
||||
</view>
|
||||
<view class="" v-for="item,i in info" :key="i">
|
||||
<view class="info f-row aic jcb">
|
||||
<view class="">
|
||||
{{item.title}}:
|
||||
</view>
|
||||
<rich-text :nodes="item.data" v-if="item.title=='事项内容'"></rich-text>
|
||||
<text v-else>{{item.data}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
info: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.info_box {
|
||||
padding: 40rpx 30rpx 16rpx 30rpx;
|
||||
width: 630rpx;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
margin-top: 30rpx;
|
||||
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
background-image: url(../../static/index/line.png);
|
||||
background-size: 44rpx 12rpx;
|
||||
background-repeat: no-repeat;
|
||||
background-position: left bottom;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.info {
|
||||
font-size: 28rpx;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
view {
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
text {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
54
bpm/safeCom.vue
Normal file
@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<view class="list f-row aic jcb">
|
||||
<view class="item" v-for="item,i in 20" :key="i" @click="jump('/pages/safe/detail')">
|
||||
<view class="">
|
||||
<image src="" mode=""></image>
|
||||
</view>
|
||||
<view class="text">
|
||||
五月天“突然好想你”线上演唱会精彩回放
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
beforeJump
|
||||
} from '@/utils/index.js';
|
||||
const jump = (url) => {
|
||||
beforeJump(url, () => {
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.list {
|
||||
flex-wrap: wrap;
|
||||
|
||||
.item {
|
||||
width: 340rpx;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
margin-top: 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
line-height: 40rpx;
|
||||
|
||||
.text {
|
||||
padding: 16rpx;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 340rpx;
|
||||
height: 200rpx;
|
||||
border-radius: 16rpx 16rpx 0 0;
|
||||
background-color: #efefef;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
331
bpm/supervise.vue
Normal file
@ -0,0 +1,331 @@
|
||||
<template>
|
||||
<view class="">
|
||||
<view class="tab f-row aic">
|
||||
<view :class="{'active':currentTab==item.id}" v-for="item,i in tabArr" :key="i" @click="changeTab(item.id)">
|
||||
{{item.title}}
|
||||
</view>
|
||||
</view>
|
||||
<processCom :info="info"></processCom>
|
||||
<view class="f-col aic">
|
||||
<view class="progress">
|
||||
<view class="title">
|
||||
审批流程
|
||||
</view>
|
||||
<view class="progress_box">
|
||||
<view class="box" v-for="(item,index) in step" :key="index">
|
||||
<view class="topic f-row aic">
|
||||
<view class="">
|
||||
{{item.name}}
|
||||
</view>
|
||||
<view
|
||||
:class="['status',{'complete':item.deleteReason=='已完成'},{'refuse':item.deleteReason=='已拒绝'}]">
|
||||
{{item.deleteReason}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="name_time">
|
||||
{{item.assigneeName}} | {{item.endTime}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
dbSxxqQueryByIdApi,
|
||||
dbJbxxQueryByIdApi,
|
||||
extActFlowDataApi,
|
||||
processHistoryListApi
|
||||
} from '@/api/api.js';
|
||||
import processCom from './processCom.vue';
|
||||
import {
|
||||
ref,
|
||||
onBeforeMount,
|
||||
watch,
|
||||
onMounted
|
||||
} from 'vue';
|
||||
const props = defineProps({
|
||||
dataId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
const tabArr = [{
|
||||
title: '基本信息',
|
||||
id: 1
|
||||
}, {
|
||||
title: '事项详情',
|
||||
id: 2
|
||||
}, {
|
||||
title: '添加下级',
|
||||
id: 3
|
||||
}, {
|
||||
title: '节点顺序',
|
||||
id: 4
|
||||
}, {
|
||||
title: '运行计划',
|
||||
id: 5
|
||||
}]
|
||||
const currentTab = ref(1)
|
||||
const changeTab = (id) => {
|
||||
currentTab.value = id
|
||||
dbSxxqQueryById()
|
||||
|
||||
}
|
||||
const info = ref([])
|
||||
/**事项详情*/
|
||||
const dbSxxqQueryById = () => {
|
||||
dbSxxqQueryByIdApi({
|
||||
id: props.dataId
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
|
||||
if(currentTab.value==1){
|
||||
|
||||
dbJbxxQueryById(res.result.jbxxid)
|
||||
}
|
||||
if(currentTab.value==2){
|
||||
let d = res.result
|
||||
info.value = [{
|
||||
title: '承办部门',
|
||||
data: d.zbdw
|
||||
}, {
|
||||
title: '协办部门',
|
||||
data: d.xbdw
|
||||
}, {
|
||||
title: '部门领导',
|
||||
data: d.fgld
|
||||
}, {
|
||||
title: '办理人员',
|
||||
data: d.dbry
|
||||
}, {
|
||||
title: '要求反馈时间',
|
||||
data: d.yqfksj
|
||||
}, {
|
||||
title: '节点名称',
|
||||
data: ''
|
||||
}, {
|
||||
title: '预计完成时间',
|
||||
data: ''
|
||||
}, {
|
||||
title: '实际反馈时间',
|
||||
data: d.sjfksj
|
||||
}, {
|
||||
title: '自评价',
|
||||
data: d.zpj
|
||||
}, {
|
||||
title: '发起时间',
|
||||
data: d.fqsj
|
||||
}, {
|
||||
title: '序号',
|
||||
data: ''
|
||||
}, {
|
||||
title: '概述',
|
||||
data: ''
|
||||
}, {
|
||||
title: '时间进度',
|
||||
data: ''
|
||||
}, {
|
||||
title: '事项内容',
|
||||
data: d.sxnr
|
||||
}]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
/**基本信息*/
|
||||
const dbJbxxQueryById = (id) => {
|
||||
dbJbxxQueryByIdApi({
|
||||
id
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
let d = res.result
|
||||
info.value = [{
|
||||
title: '督办分类',
|
||||
data: d.fl
|
||||
}, {
|
||||
title: '协办部门',
|
||||
data: d.xbbm
|
||||
}, {
|
||||
title: '督办部门',
|
||||
data: d.cbbm
|
||||
}, {
|
||||
title: '督办人员',
|
||||
data: d.dbry
|
||||
}, {
|
||||
title: '督办部门负责人',
|
||||
data: d.zrr
|
||||
}, {
|
||||
title: '是否涉密',
|
||||
data: d.sfsm
|
||||
}, {
|
||||
title: '计划完成时间',
|
||||
data: d.jhwcsj
|
||||
}, {
|
||||
title: '实际完成时间',
|
||||
data: d.wcsj
|
||||
}, {
|
||||
title: '完成状态',
|
||||
data: d.wczt
|
||||
}, {
|
||||
title: '备注',
|
||||
data: d.bz
|
||||
}, {
|
||||
title: '督办事项',
|
||||
data: d.dbsx
|
||||
}, {
|
||||
title: '时间进度',
|
||||
data: d.sjjd
|
||||
}]
|
||||
}
|
||||
})
|
||||
}
|
||||
const extActFlowData = (dataId) => {
|
||||
extActFlowDataApi({
|
||||
flowCode: "dev_db_sxxq_001",
|
||||
dataId: props.dataId
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
processHistoryList(res.result.processInstanceId)
|
||||
}
|
||||
})
|
||||
}
|
||||
const step = ref([])
|
||||
/**审批步骤*/
|
||||
const processHistoryList = (processInstanceId) => {
|
||||
console.log('000', processInstanceId);
|
||||
processHistoryListApi({
|
||||
processInstanceId
|
||||
}).then((res) => {
|
||||
console.log('0088800', res);
|
||||
if (res.success) {
|
||||
step.value = res.result.records
|
||||
}
|
||||
})
|
||||
}
|
||||
onMounted(() => {
|
||||
dbSxxqQueryById()
|
||||
extActFlowData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.tab {
|
||||
background-color: #fff;
|
||||
overflow-x: auto;
|
||||
|
||||
view {
|
||||
padding: 20rpx 30rpx;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.active {
|
||||
position: relative;
|
||||
color: #1890ff;
|
||||
|
||||
&::after {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
width: 100rpx;
|
||||
height: 6rpx;
|
||||
border-radius: 3rpx;
|
||||
background-color: #1890ff;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.progress {
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
width: 630rpx;
|
||||
padding: 40rpx 30rpx 16rpx 30rpx;
|
||||
margin-top: 30rpx;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.status {
|
||||
padding: 4rpx 8rpx;
|
||||
display: inline-block;
|
||||
|
||||
color: #FFFFFF;
|
||||
font-size: 20rpx;
|
||||
margin-left: 8rpx;
|
||||
border-radius: 8rpx;
|
||||
|
||||
}
|
||||
|
||||
.complete {
|
||||
background-color: #7AC756;
|
||||
}
|
||||
|
||||
.refuse {
|
||||
background-color: #FE4600;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
background-image: url(../../static/index/line.png);
|
||||
background-size: 44rpx 12rpx;
|
||||
background-repeat: no-repeat;
|
||||
background-position: left bottom;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
}
|
||||
|
||||
// .box:not(:first-child) {
|
||||
// padding-top: 60rpx;
|
||||
// }
|
||||
.box:not(:last-child) {
|
||||
position: relative;
|
||||
padding-bottom: 60rpx;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
content: ' ';
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
background: #efefef;
|
||||
left: -42rpx;
|
||||
top: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.box {
|
||||
margin-left: 50rpx;
|
||||
|
||||
|
||||
.topic {
|
||||
position: relative;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
content: ' ';
|
||||
width: 18rpx;
|
||||
height: 18rpx;
|
||||
background: #01508B;
|
||||
border-radius: 14rpx;
|
||||
left: -50rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.name_time {
|
||||
font-size: 24rpx;
|
||||
color: #888888;
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
194
bpm/tasklistCom.vue
Normal file
@ -0,0 +1,194 @@
|
||||
<template>
|
||||
<view class="list_box">
|
||||
<view class="list" v-for="item,i in taskArr" :key="i"
|
||||
@click="tojump(`/pages/task/handle?info=${JSON.stringify(item)}&type=${currentIndex}`)">
|
||||
<view class="title f-row aic jcb">
|
||||
<view>
|
||||
<view>
|
||||
{{item.bpmBizTitle}}
|
||||
</view>
|
||||
</view>
|
||||
<text>{{item.durationStr}}</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view>
|
||||
申请理由:{{item.bpmBizTitle}}
|
||||
</view>
|
||||
<view v-if="currentIndex != 2">
|
||||
当前环节:{{item.taskName}}
|
||||
</view>
|
||||
<view>
|
||||
流程名称:{{item.processDefinitionName}}
|
||||
</view>
|
||||
<view>
|
||||
发起人:{{item.processApplyUserName}}
|
||||
</view>
|
||||
<view>
|
||||
开始时间:{{item.taskBeginTime}}
|
||||
</view>
|
||||
<view v-if="item.taskEndTime">
|
||||
结束时间:{{item.taskEndTime}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn f-row aic jcb" v-if="currentIndex == 0 && item.taskAssigneeName">
|
||||
<view class="entrust" @click.stop="tojump(`/pages/userlist/index?isradio=1&id=${item.id}`)">
|
||||
委托
|
||||
</view>
|
||||
<view class="handle" @click="tojump(`/pages/task/handle?info=${JSON.stringify(item)}&type=${currentIndex}`)">
|
||||
办理
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn f-row aic jcb" v-if="currentIndex == 0 && !item.taskAssigneeName">
|
||||
<view>
|
||||
</view>
|
||||
<view class="handle" @click.stop="handleClaim(item.id)">
|
||||
签收
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn f-row aic jcb" v-if="currentIndex == 2 && !item.endTime">
|
||||
<view class="entrust" @click.stop="invalidProcess(item.processInstanceId)">
|
||||
作废流程
|
||||
</view>
|
||||
<view class="handle" @click.stop="callBackProcess(item.processInstanceId)">
|
||||
取回流程
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
claimApi,
|
||||
callBackProcessApi,
|
||||
invalidProcessApi
|
||||
} from '@/api/api.js';
|
||||
import {
|
||||
getCurrentInstance,
|
||||
} from 'vue';
|
||||
const {
|
||||
proxy
|
||||
} = getCurrentInstance()
|
||||
|
||||
const props = defineProps({
|
||||
taskArr: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
currentIndex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
})
|
||||
const emit = defineEmits(['jump'])
|
||||
const tojump = (url) => {
|
||||
emit('jump', url)
|
||||
}
|
||||
|
||||
/**流程签收*/
|
||||
const handleClaim = (id) => {
|
||||
claimApi({
|
||||
taskId: id
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
uni.redirectTo({
|
||||
url: './index?id=0'
|
||||
});
|
||||
proxy.$toast(res.message)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**流程取回*/
|
||||
const callBackProcess = (id) => {
|
||||
callBackProcessApi({
|
||||
processInstanceId: id
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
uni.redirectTo({
|
||||
url: './self'
|
||||
});
|
||||
proxy.$toast(res.message)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**流程作废*/
|
||||
const invalidProcess = (id) => {
|
||||
invalidProcessApi({
|
||||
processInstanceId: id
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
uni.redirectTo({
|
||||
url: './self'
|
||||
});
|
||||
proxy.$toast(res.message)
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.list_box {
|
||||
padding: 0 30rpx 0 30rpx;
|
||||
margin-top: 24rpx;
|
||||
|
||||
.list {
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.title {
|
||||
border-bottom: 1px solid #efefef;
|
||||
padding-bottom: 24rpx;
|
||||
margin-bottom: 8rpx;
|
||||
|
||||
view {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
|
||||
view {
|
||||
padding-top: 16rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin-top: 30rpx;
|
||||
|
||||
view {
|
||||
width: 300rpx;
|
||||
height: 64rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 28rpx;
|
||||
text-align: center;
|
||||
line-height: 64rpx;
|
||||
}
|
||||
|
||||
.entrust {
|
||||
background: #FFFFFF;
|
||||
border: 2rpx solid #01508B;
|
||||
box-sizing: border-box;
|
||||
color: #01508B;
|
||||
}
|
||||
|
||||
.handle {
|
||||
background: #01508B;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
BIN
certificate/book.keystore
Normal file
9
certificate/证书信息.txt
Normal file
@ -0,0 +1,9 @@
|
||||
证书指纹:
|
||||
MD5: 9A:AD:4D:78:17:EE:17:D3:62:B2:6E:B2:56:0B:18:C3
|
||||
SHA1: B1:1E:CE:4B:70:C7:88:B3:6E:8B:B9:05:98:4B:FD:67:81:C1:3A:8F
|
||||
SHA256: A9:78:BD:BF:BB:DE:35:14:AA:5D:45:E9:6A:D0:E5:17:6D:BE:58:86:7A:1D:66:A2:F3:62:2F:E7:9C:9E:59:F6
|
||||
|
||||
|
||||
别名: __uni__9f097f0
|
||||
证书密码为:uZ6Stufj
|
||||
包名:com.tianranqi.app
|
||||
119
components/departSelect/departSelect.vue
Normal file
@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<view>
|
||||
<view v-if="customReturnValue === 'orgCode'">
|
||||
<uni-data-picker :openSearch="true" placeholder="请选择单位" popup-title="请选择单位" :localdata="dataList"
|
||||
@nodeclick="onNodeClick" @popupclosed="onPopupClosed" v-model="ID"
|
||||
:map="{ text: 'title', value: 'orgCode' }"></uni-data-picker>
|
||||
</view>
|
||||
<view v-else>
|
||||
<uni-data-picker :openSearch="true" placeholder="请选择单位" popup-title="请选择单位" :localdata="dataList"
|
||||
@nodeclick="onNodeClick" @popupclosed="onPopupClosed" v-model="ID"
|
||||
:map="{ text: 'title', value: 'id' }"></uni-data-picker>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
queryDepByCode,
|
||||
queryZbDepByLdhth
|
||||
} from '@/api/depart.js'
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
|
||||
const store = useStore()
|
||||
|
||||
const props = defineProps([{
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
customReturnValue: {
|
||||
require: true,
|
||||
type: String,
|
||||
default: 'orgCode'
|
||||
}
|
||||
}]),
|
||||
|
||||
watch(value,(newValue,oldValue)=>{
|
||||
console.log("新值是"+newValue, "旧址是"+oldValue);
|
||||
this.ID = val;
|
||||
}),
|
||||
watch(value,(newValue,oldValue)=>{
|
||||
console.log("新值是"+newValue, "旧址是"+oldValue);
|
||||
this.ID = val;
|
||||
}),
|
||||
|
||||
|
||||
data() {
|
||||
return {
|
||||
reset: true,
|
||||
url: {
|
||||
list: '/sys/sysDepart/queryTreeList'
|
||||
},
|
||||
pageNo: 1,
|
||||
pageSize: 3000,
|
||||
|
||||
params: {
|
||||
pageNo: this.pageNo,
|
||||
pageSize: this.pageSize
|
||||
},
|
||||
dataList: [],
|
||||
ID: '',
|
||||
bmText: '',
|
||||
tempID: '',
|
||||
field: ''
|
||||
};
|
||||
},
|
||||
onReady() {
|
||||
this.getData();
|
||||
},
|
||||
mounted() {
|
||||
this.getData();
|
||||
},
|
||||
methods: {
|
||||
onNodeClick(e) {
|
||||
console.log(JSON.stringify(e));
|
||||
console.log(e.orgCode, e.title, e.id, this.customReturnValue);
|
||||
this.$nextTick(() => {
|
||||
if (this.customReturnValue == 'orgCode') {
|
||||
this.tempID = e.orgCode;
|
||||
}
|
||||
if (this.customReturnValue == 'id') {
|
||||
this.tempID = e.id;
|
||||
}
|
||||
|
||||
this.bmText = e.title;
|
||||
})
|
||||
},
|
||||
onPopupClosed() {
|
||||
this.$nextTick(() => {
|
||||
this.ID = this.tempID;
|
||||
console.log(this.ID, this.bmText);
|
||||
this.$emit('input', this.ID);
|
||||
this.$emit('change', this.ID, this.bmText);
|
||||
});
|
||||
},
|
||||
onchange(e) {
|
||||
this.$nextTick(() => {
|
||||
this.ID = this.tempID;
|
||||
console.log(this.ID, this.bmText);
|
||||
this.$emit('input', this.ID);
|
||||
this.$emit('change', this.ID, e.detail.value);
|
||||
})
|
||||
},
|
||||
getData() {
|
||||
// console.log(111)
|
||||
let that = this;
|
||||
queryDepByCode(store.userinfo.workNo).then((res) => { //获取工作单位
|
||||
console.log(res)
|
||||
depart.value = res.departName
|
||||
orgCode.value = res.orgCode
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
51
components/kidoki-date-picker/kidoki-date-picker.vue
Normal file
@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<view class="date-picker-container">
|
||||
<picker mode=multiSelector @change="bindPickerChange" :value="index" :range="range">
|
||||
<slot />
|
||||
</picker>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
// 定义生成 range 的值的方法
|
||||
const getRange = () => {
|
||||
const dateArr = [[], []]
|
||||
for (var i = 2000; i <= 2099; i++) { dateArr[0].push(`${i}年`) }
|
||||
for (var i = 1; i <= 12; i++) { dateArr[1].push(`${i}月`) }
|
||||
return { dateArr }
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'date-picker',
|
||||
setup(props) {
|
||||
// range: 长度表示多少列,数组的每项表示每列的数据
|
||||
const { dateArr } = getRange()
|
||||
const range = ref(dateArr)
|
||||
|
||||
// index: 索引数组, 每一项的值表示选择了对应项中的第几个。
|
||||
// date 获取时间
|
||||
// 【[year, month]】 year、month 为选中的年月,例如选中2022年3月就是 year = 22、month = 2
|
||||
const date = dayjs(props.date).format("YYYY-MM")
|
||||
const year = Number(date.slice(2, 4))
|
||||
const month = Number(date.slice(5, 7))
|
||||
const index = ref([year, month - 1])
|
||||
console.log(index.value)
|
||||
|
||||
// bindPickerChange: index 改变时触发该事件
|
||||
const bindPickerChange = (e) => {
|
||||
index.value = e.detail.value
|
||||
console.log(`用户选中20${index.value[0]}年${index.value[1] + 1}月`)
|
||||
}
|
||||
|
||||
return { index, range, bindPickerChange }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.date-picker-container {
|
||||
}
|
||||
</style>
|
||||
289
components/treeSelect/data-select-item.vue
Normal file
@ -0,0 +1,289 @@
|
||||
<template>
|
||||
<view
|
||||
class="customthree-tree-select-content"
|
||||
:class="{
|
||||
border: border && node[dataChildren] && node[dataChildren].length && node.showChildren
|
||||
}"
|
||||
:style="{ marginLeft: `${level ? 14 : 0}px` }"
|
||||
>
|
||||
<view v-if="node.visible" class="custom-tree-select-item">
|
||||
<view class="item-content">
|
||||
<view class="left" @click.stop="handleNameClick(node)">
|
||||
<view class="icon-group">
|
||||
<view
|
||||
v-if="node[dataChildren] && node[dataChildren].length"
|
||||
:class="['right-icon', { active: node.showChildren }]"
|
||||
>
|
||||
<uni-icons type="right" size="14" color="#333"></uni-icons>
|
||||
</view>
|
||||
<view v-else class="smallcircle-filled">
|
||||
<uni-icons class="smallcircle-filled-icon" type="smallcircle-filled" size="10" color="#333"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="loadingArr.includes(node[props.dataValue].toString())" class="loading-icon-box">
|
||||
<uni-icons class="loading-icon" type="spinner-cycle" size="14" color="#333"></uni-icons>
|
||||
</view>
|
||||
<view class="name" :style="node.disabled ? 'color: #999' : ''">
|
||||
<text>{{ node[dataLabel] }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
v-if="
|
||||
choseParent ||
|
||||
(!choseParent && !node[dataChildren]) ||
|
||||
(!choseParent && node[dataChildren] && !node[dataChildren].length)
|
||||
"
|
||||
:class="['check-box', { disabled: node.disabled }]"
|
||||
:style="{ 'border-radius': mutiple ? '3px' : '50%' }"
|
||||
@click.stop="!node.disabled && nodeClick(node)"
|
||||
>
|
||||
<view v-if="!node.checked && node.partChecked && linkage" class="part-checked"></view>
|
||||
<uni-icons
|
||||
v-if="node.checked"
|
||||
type="checkmarkempty"
|
||||
size="18"
|
||||
:color="node.disabled ? '#333' : '#007aff'"
|
||||
></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="node.showChildren && node[dataChildren] && node[dataChildren].length">
|
||||
<data-select-item
|
||||
v-for="item in listData"
|
||||
:key="item[dataValue]"
|
||||
:node="item"
|
||||
:dataLabel="dataLabel"
|
||||
:dataValue="dataValue"
|
||||
:dataChildren="dataChildren"
|
||||
:choseParent="choseParent"
|
||||
:lazyLoadChildren="lazyLoadChildren"
|
||||
:border="border"
|
||||
:linkage="linkage"
|
||||
:level="level + 1"
|
||||
></data-select-item>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import dataSelectItem from './data-select-item.vue'
|
||||
import { paging } from './utils'
|
||||
import { ref, inject, watchEffect } from 'vue'
|
||||
|
||||
const { nodeClick, nameClick, loadNode, initData, addNode } = inject('nodeFn')
|
||||
|
||||
const props = defineProps({
|
||||
node: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
choseParent: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
dataLabel: {
|
||||
type: String,
|
||||
default: 'name'
|
||||
},
|
||||
dataValue: {
|
||||
type: String,
|
||||
default: 'value'
|
||||
},
|
||||
dataChildren: {
|
||||
type: String,
|
||||
default: 'children'
|
||||
},
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
linkage: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
lazyLoadChildren: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
level: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
mutiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
})
|
||||
|
||||
const listData = ref([])
|
||||
const clearTimerList = ref([])
|
||||
const loadingArr = ref([])
|
||||
|
||||
watchEffect(() => {
|
||||
if (props.node.showChildren && props.node[props.dataChildren] && props.node[props.dataChildren].length) {
|
||||
resetClearTimerList()
|
||||
renderTree(props.node[props.dataChildren])
|
||||
}
|
||||
})
|
||||
|
||||
// 中断懒加载
|
||||
function resetClearTimerList() {
|
||||
const list = [...clearTimerList.value]
|
||||
clearTimerList.value = []
|
||||
list.forEach((fn) => fn())
|
||||
}
|
||||
|
||||
// 懒加载
|
||||
function renderTree(arr: any[]) {
|
||||
const pagingArr = paging(arr)
|
||||
listData.value = pagingArr?.[0] || []
|
||||
lazyRenderList(pagingArr, 1)
|
||||
}
|
||||
|
||||
// 懒加载具体逻辑
|
||||
function lazyRenderList(arr: any[], startIndex: number) {
|
||||
for (let i = startIndex; i < arr.length; i++) {
|
||||
let timer: any = null
|
||||
timer = setTimeout(() => {
|
||||
listData.value.push(...arr[i])
|
||||
}, i * 500)
|
||||
clearTimerList.push(() => clearTimeout(timer))
|
||||
}
|
||||
}
|
||||
|
||||
// 点击名称懒加载子元素
|
||||
function handleNameClick(node: any) {
|
||||
if (!node.visible) return
|
||||
|
||||
if (!node[props.dataChildren]?.length && props.lazyLoadChildren) {
|
||||
loadingArr.value.push(node[props.dataValue].toString())
|
||||
|
||||
loadNode(node)
|
||||
.then((res: any) => {
|
||||
addNode(node, initData(res, node.visible))
|
||||
})
|
||||
.finally(() => {
|
||||
loadingArr.value = []
|
||||
})
|
||||
} else {
|
||||
nameClick(node)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$primary-color: #007aff;
|
||||
$col-sm: 4px;
|
||||
$col-base: 8px;
|
||||
$col-lg: 12px;
|
||||
$row-sm: 5px;
|
||||
$row-base: 10px;
|
||||
$row-lg: 15px;
|
||||
$radius-base: 6px;
|
||||
$border-color: #c8c7cc;
|
||||
|
||||
.customthree-tree-select-content {
|
||||
&.border {
|
||||
border-left: 1px solid $border-color;
|
||||
}
|
||||
|
||||
::v-deep .uni-checkbox-input {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.item-content {
|
||||
margin: 0 0 $col-lg;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 3px;
|
||||
background-color: #fff;
|
||||
transform: translateX(-2px);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.left {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.right-icon {
|
||||
transition: 0.15s ease;
|
||||
|
||||
&.active {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
.smallcircle-filled {
|
||||
width: 14px;
|
||||
height: 13.6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.smallcircle-filled-icon {
|
||||
transform-origin: center;
|
||||
transform: scale(0.55);
|
||||
}
|
||||
}
|
||||
|
||||
.loading-icon-box {
|
||||
margin-right: $row-sm;
|
||||
width: 14px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.loading-icon {
|
||||
transform-origin: center;
|
||||
animation: rotating infinite 0.2s ease;
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.check-box {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
width: 23.6px;
|
||||
height: 23.6px;
|
||||
border: 1px solid $border-color;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&.disabled {
|
||||
background-color: rgb(225, 225, 225);
|
||||
}
|
||||
|
||||
.part-checked {
|
||||
width: 60%;
|
||||
height: 2px;
|
||||
background-color: $primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotating {
|
||||
from {
|
||||
transform: rotate(0);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
240
components/treeSelect/readme.md
Normal file
@ -0,0 +1,240 @@
|
||||
# customthree-tree-select 使用指南
|
||||
|
||||
**提示:** 使用该插件前确保你已经导入 `uni-popup` `uni-icons` `uni-easyinput` 插件。
|
||||
|
||||
**有问题可以加 QQ 群:297080738**
|
||||
|
||||
## 优势
|
||||
|
||||
💪:基于 `uni-popup`、 `uni-icons`、 `uni-easyinput` 插件进行开发,默认样式与 `uni-easyinput` 样式对标。
|
||||
|
||||
⚡:全面支持懒加载应对大量数据。
|
||||
|
||||
🚀:v-model 绑定数据、数据回显、移除选项。
|
||||
|
||||
⚙ :提供更多配置项。
|
||||
|
||||
📦:开箱即用。
|
||||
|
||||
## Props
|
||||
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
| :--------------------: | :-----------------: | :-------------: | :----------------------------------------------------------: |
|
||||
| canSelectAll | Boolean | false | 开启一键全选功能 |
|
||||
| clearResetSearch | Boolean | false | 设置为 `true` 并且搜索之后,点击输入框清除按钮,会清空搜索内容并且会直接重置整个弹窗内树形选择器内容,默认情况下只有清除之后再次进行查询才会重置选择器 |
|
||||
| animation | Boolean | ture | 是否开启弹窗动画 |
|
||||
| is-mask-click | Boolean | true | 点击遮罩关闭弹窗 |
|
||||
| mask-background-color | String | rgba(0,0,0,0.4) | 蒙版颜色,建议使用 rgba 颜色值 |
|
||||
| background-color | String | none | 主窗口背景色 |
|
||||
| safe-area | Boolean | true | 是否适配底部安全区 |
|
||||
| **choseParent** | **Boolean** | **false** | **父节点是否可选** |
|
||||
| **linkage** | **Boolean** | **false** | **父子节点是否联动** |
|
||||
| placeholder | String | 请选择 | 空状态信息提示、弹窗标题 |
|
||||
| confirmText | String | 完成 | 确定按钮文字 |
|
||||
| confirmTextColor | String | #007aff | 确定按钮文字颜色 |
|
||||
| dataSource | Array | - | 展示的数据 |
|
||||
| **dataLabel** | **String** | **name** | **dataSource 中对应数据的 label** |
|
||||
| **dataValue** | **String** | **id** | **dataSource 中对应数据的 value** |
|
||||
| **dataChildren** | **String** | **children** | **dataSource 中对应数据的 children** |
|
||||
| clearable | Boolean | false | 是否显示清除按钮,点击清除所有已选项 |
|
||||
| **mutiple** | **Boolean** | **false** | **是否可以多选** |
|
||||
| **disabled** | **Boolean** | **false** | **是否允许修改** |
|
||||
| search | Boolean | false | 是否可以搜索(常用于数据较多的情况) |
|
||||
| showChildren | Boolean | false | 默认不展开(数据内部 showChildren 属性优先级更高,可以设置全局收起,单独展开某一条数据) |
|
||||
| border | Boolean | false | 显示引导线 |
|
||||
| load | Function | function(){} | lazyLoadChildren 设置为true 后,点击某个节点发送请求获取子节点数据,用法见下方异步懒加载示例 |
|
||||
| lazyLoadChildren | Boolean | false | 是否开启异步懒加载节点 |
|
||||
| **v-model/modelValue** | **Array \| String** | **[ ]** | **已选择的值,通过 v-model 进行绑定,例如:v-model="formData.selectedList" ,根据你绑定数据的类型自动返回相同类型的数据,String 类型通过 `,` 进行分隔** |
|
||||
| deleteSource | Boolean | false | 是否可删除已选数据
|
||||
## Events
|
||||
|
||||
| 事件名称 | 说明 | 返回值 |
|
||||
| ----------------- | ------------------------ | ------------------------------------------- |
|
||||
| change | 弹窗组件状态发生变化触发 | e={show: true | false,type:当前模式} |
|
||||
| maskClick | 点击遮罩层触发 | |
|
||||
| update:modelValue | 选中数据或取消选中时触发 | 以数组形式返回已选择数据的 dataValue 对应值 |
|
||||
| select-change | 选中数据或取消选中时触发 | 以数组形式返回选中数据完整信息 |
|
||||
| removeSelect | 从选择框内删除元素时触发 | |
|
||||
|
||||
## 基础使用示例
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<customthree-tree-select :listData="listData" v-model="formData.selectedArr" />
|
||||
<customthree-tree-select :listData="listData" v-model="formData.selectedString" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive } from 'vue'
|
||||
|
||||
const formData = reactive({
|
||||
selectedArr: [],
|
||||
selectedString: ''
|
||||
})
|
||||
|
||||
const listData = [
|
||||
{
|
||||
id: 1,
|
||||
name: '城市1',
|
||||
children: [
|
||||
{
|
||||
id: 3,
|
||||
name: '街道1',
|
||||
children: [
|
||||
{
|
||||
id: 4,
|
||||
name: '小区1'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '城市2',
|
||||
children: [
|
||||
{
|
||||
id: 6,
|
||||
name: '街道2'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
</script>
|
||||
```
|
||||
|
||||
## 禁用某些选项,或隐藏某些选项
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<customthree-tree-select
|
||||
mutiple
|
||||
linkage
|
||||
clearable
|
||||
search
|
||||
dataLabel="text"
|
||||
dataValue="value"
|
||||
:listData="listData"
|
||||
v-model="formData.selected"
|
||||
></custom-tree-select>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive } from 'vue'
|
||||
|
||||
const formData = reactive({
|
||||
selected: ''
|
||||
})
|
||||
|
||||
const listData = [
|
||||
{
|
||||
id: 1,
|
||||
name: '城市1',
|
||||
children: [
|
||||
{
|
||||
id: 3,
|
||||
name: '街道1',
|
||||
disabled: true
|
||||
children: [
|
||||
{
|
||||
id: 4,
|
||||
name: '小区1'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '城市2',
|
||||
children: [
|
||||
{
|
||||
id: 6,
|
||||
name: '街道2',
|
||||
visible: false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
</script>
|
||||
```
|
||||
|
||||
## 异步懒加载
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<view class="content">
|
||||
<customthree-tree-select
|
||||
search
|
||||
linkage
|
||||
clearable
|
||||
clearResetSearch
|
||||
border
|
||||
mutiple
|
||||
lazyLoadChildren
|
||||
canSelectAll
|
||||
:showChildren="false"
|
||||
:listData="listData"
|
||||
:load="loadNode"
|
||||
dataLabel="text"
|
||||
dataValue="value"
|
||||
v-model="selectedStr"
|
||||
></customthree-tree-select>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
selectedStr: '',
|
||||
listData: [
|
||||
{
|
||||
value: '0',
|
||||
text: '测试懒加载'
|
||||
},
|
||||
{
|
||||
value: '1',
|
||||
text: '城市1',
|
||||
children: [
|
||||
{
|
||||
value: '1-1',
|
||||
text: '街道1',
|
||||
disabled: true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadNode(node) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
const item = this.listData.find((item) => item.value === node.value)
|
||||
if (item) {
|
||||
resolve([
|
||||
{
|
||||
value: '0-1',
|
||||
text: '懒加载子元素'
|
||||
}
|
||||
])
|
||||
}
|
||||
resolve([])
|
||||
}, 500)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
811
components/treeSelect/treeSelect.vue
Normal file
@ -0,0 +1,811 @@
|
||||
<template>
|
||||
<view :class="['select-list', { disabled }, { active: selectList.length }]" @click="open">
|
||||
<view class="left">
|
||||
<view v-if="selectList.length" class="select-items">
|
||||
<view class="select-item" v-for="item in selectedListBaseinfo" :key="item[dataValue]">
|
||||
<view class="name">
|
||||
<text>{{ item[dataLabel] }}</text>
|
||||
</view>
|
||||
<view v-if="!disabled && !item.disabled && deleteSource" class="close"
|
||||
@click.stop="removeSelectedItem(item)">
|
||||
<uni-icons type="closeempty" size="16" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="no-data">
|
||||
<text>{{ placeholder }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view>
|
||||
<uni-icons v-if="!selectList.length || !clearable" type="bottom" color="#333333"></uni-icons>
|
||||
<view @click.stop>
|
||||
<uni-icons v-if="selectList.length && clearable" type="clear" size="24" color="#c0c4cc"
|
||||
@click="clearSelectList"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<uni-popup ref="popup" :animation="animation" :is-mask-click="isMaskClick"
|
||||
:mask-background-color="maskBackgroundColor" :background-color="backgroundColor" :safe-area="safeArea"
|
||||
type="bottom" @change="change" @maskClick="maskClick">
|
||||
<view class="popup-content" :style="{ height: contentHeight }">
|
||||
<view class="title">
|
||||
<view v-if="mutiple && canSelectAll" class="left" @click="handleSelectAll">
|
||||
<text>{{ isSelectedAll ? '取消全选' : '全选' }}</text>
|
||||
</view>
|
||||
<view class="center">
|
||||
<text>{{ placeholder }}</text>
|
||||
</view>
|
||||
<view class="right" :style="{ color: confirmTextColor }" @click="close">
|
||||
<text>{{ confirmText }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="search" class="search-box">
|
||||
<uni-easyinput :maxlength="-1" prefixIcon="search" placeholder="搜索" v-model="searchStr"
|
||||
confirm-type="search" @confirm="handleSearch(false)" @clear="handleSearch(true)">
|
||||
</uni-easyinput>
|
||||
<button type="primary" size="mini" class="search-btn" @click="handleSearch(false)">搜索</button>
|
||||
</view>
|
||||
<view v-if="treeData.length" class="select-content">
|
||||
<scroll-view class="scroll-view-box" :scroll-top="scrollTop" scroll-y="true" @touchmove.stop>
|
||||
<view v-if="!filterTreeData.length" class="no-data center">
|
||||
<text>暂无数据</text>
|
||||
</view>
|
||||
<data-select-item v-for="item in filterTreeData" :key="item[dataValue]" :node="item"
|
||||
:dataLabel="dataLabel" :dataValue="dataValue" :dataChildren="dataChildren"
|
||||
:choseParent="choseParent" :border="border" :linkage="linkage"
|
||||
:lazyLoadChildren="lazyLoadChildren"></data-select-item>
|
||||
<view class="sentry" />
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view v-else class="no-data center">
|
||||
<text>暂无数据</text>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, watch, onMounted, nextTick, provide } from 'vue'
|
||||
import dataSelectItem from './data-select-item.vue';
|
||||
import { isString, paging } from './utils';
|
||||
const props = defineProps({
|
||||
canSelectAll: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
safeArea: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
search: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
clearResetSearch: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
animation: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
'is-mask-click': {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
'mask-background-color': {
|
||||
type: String,
|
||||
default: 'rgba(0,0,0,0.4)'
|
||||
},
|
||||
'background-color': {
|
||||
type: String,
|
||||
default: 'none'
|
||||
},
|
||||
'safe-area': {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
choseParent: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择'
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: '确认'
|
||||
},
|
||||
confirmTextColor: {
|
||||
type: String,
|
||||
default: '#007aff'
|
||||
},
|
||||
dataSource: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
dataLabel: {
|
||||
type: String,
|
||||
default: 'name'
|
||||
},
|
||||
dataValue: {
|
||||
type: String,
|
||||
default: 'id'
|
||||
},
|
||||
dataChildren: {
|
||||
type: String,
|
||||
default: 'children'
|
||||
},
|
||||
linkage: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
removeLinkage: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
mutiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
deleteSource: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showChildren: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
lazyLoadChildren: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
load: {
|
||||
type: Function,
|
||||
default: function () { }
|
||||
},
|
||||
modelValue: {
|
||||
type: [Array, String],
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
const emits = defineEmits(['update:modelValue', 'change', 'maskClick', 'select-change', 'removeSelect'])
|
||||
|
||||
const contentHeight = ref('500px')
|
||||
const treeData = ref([])
|
||||
const filterTreeData = ref([])
|
||||
const clearTimerList = ref([])
|
||||
const selectedListBaseinfo = ref([])
|
||||
const showPopup = ref(false)
|
||||
const isSelectedAll = ref(false)
|
||||
const scrollTop = ref(0)
|
||||
const searchStr = ref('')
|
||||
const popup = ref<any>(null)
|
||||
|
||||
const partCheckedSet = new Set()
|
||||
|
||||
provide('nodeFn', {
|
||||
nodeClick: handleNodeClick,
|
||||
nameClick: handleHideChildren,
|
||||
loadNode: props.load,
|
||||
initData: initData,
|
||||
addNode: addNode
|
||||
})
|
||||
|
||||
const selectList = computed(() => {
|
||||
const newVal = props.modelValue === null ? '' : props.modelValue
|
||||
return isString(newVal) ? (newVal.length ? newVal.split(',') : []) : newVal.map((item : any) => item.toString())
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
getContentHeight(uni.getSystemInfoSync())
|
||||
})
|
||||
|
||||
function getContentHeight({ screenHeight } : { screenHeight : number }) {
|
||||
contentHeight.value = `${Math.floor(screenHeight * 0.7)}px`
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.dataSource,
|
||||
(newVal : any[]) => {
|
||||
if (newVal) {
|
||||
treeData.value = initData(newVal)
|
||||
if (showPopup.value) {
|
||||
resetClearTimerList()
|
||||
renderTree(treeData.value)
|
||||
}
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newVal : any[] | string) => {
|
||||
const ids = newVal ? (Array.isArray(newVal) ? newVal : newVal.split(',')) : []
|
||||
changeStatus(treeData.value, ids, true)
|
||||
filterTreeData.value.length && changeStatus(filterTreeData.value, ids)
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
// 搜索完成返回顶部
|
||||
function goTop() {
|
||||
scrollTop.val = 10
|
||||
nextTick(() => {
|
||||
scrollTop.value = 0
|
||||
})
|
||||
}
|
||||
|
||||
// 处理搜索
|
||||
function handleSearch(isClear = false) {
|
||||
resetClearTimerList()
|
||||
if (isClear) {
|
||||
// 点击清空按钮并且设置清空按钮会重置搜索
|
||||
if (props.clearResetSearch) {
|
||||
renderTree(treeData.value)
|
||||
}
|
||||
} else {
|
||||
renderTree(searchValue(searchStr.value, treeData.value))
|
||||
}
|
||||
goTop()
|
||||
uni.hideKeyboard()
|
||||
}
|
||||
|
||||
// 具体搜索方法
|
||||
function searchValue(str : any, arr : any[]) {
|
||||
const res : any = []
|
||||
arr.forEach((item) => {
|
||||
if (item.visible) {
|
||||
if (item[props.dataLabel].toString().toLowerCase().indexOf(str.toLowerCase()) > -1) {
|
||||
res.push(item)
|
||||
} else {
|
||||
if (item[props.dataChildren]?.length) {
|
||||
const data = searchValue(str, item[props.dataChildren])
|
||||
if (data?.length) {
|
||||
if (str && !item.showChildren && item[props.dataChildren]?.length) {
|
||||
item.showChildren = true
|
||||
}
|
||||
res.push({
|
||||
...item,
|
||||
[props.dataChildren]: data
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
return res
|
||||
}
|
||||
|
||||
// 打开弹窗
|
||||
async function open() {
|
||||
// disaled模式下禁止打开弹窗
|
||||
if (props.disabled) return
|
||||
showPopup.value = true
|
||||
popup.value.open()
|
||||
renderTree(treeData.value)
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
function close() {
|
||||
popup.value.close()
|
||||
}
|
||||
|
||||
// 弹窗状态变化 包括点击回显框和遮罩
|
||||
function change(data : any) {
|
||||
if (!data.show) {
|
||||
resetClearTimerList()
|
||||
searchStr.value = ''
|
||||
showPopup.value = false
|
||||
}
|
||||
emits('change', data)
|
||||
}
|
||||
|
||||
// 点击遮罩
|
||||
function maskClick() {
|
||||
emits('maskClick')
|
||||
}
|
||||
|
||||
// 初始化数据
|
||||
function initData(arr : any[], parentVisible ?: undefined | boolean) {
|
||||
if (!Array.isArray(arr)) return []
|
||||
const res = []
|
||||
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
const obj : any = {
|
||||
[props.dataLabel]: arr[i][props.dataLabel],
|
||||
[props.dataValue]: arr[i][props.dataValue]
|
||||
}
|
||||
|
||||
obj.checked = selectList.value.includes(arr[i][props.dataValue].toString())
|
||||
|
||||
obj.disabled = Boolean(arr[i].disabled)
|
||||
|
||||
//半选
|
||||
obj.partChecked = Boolean(arr[i].partChecked === undefined ? false : arr[i].partChecked)
|
||||
obj.partChecked && obj.partCheckedSet.add(obj[props.dataValue])
|
||||
!obj.partChecked && (isSelectedAll.value = false)
|
||||
|
||||
const parentVisibleState = parentVisible === undefined ? true : parentVisible
|
||||
const curVisibleState = arr[i].visible === undefined ? true : Boolean(arr[i].visible)
|
||||
if (parentVisibleState === curVisibleState) {
|
||||
obj.visible = parentVisibleState
|
||||
} else if (!parentVisibleState || !curVisibleState) {
|
||||
obj.visible = false
|
||||
} else {
|
||||
obj.visible = true
|
||||
}
|
||||
|
||||
obj.showChildren =
|
||||
'showChildren' in arr[i] && arr[i].showChildren != undefined ? arr[i].showChildren : props.showChildren
|
||||
|
||||
if (arr[i].visible && !arr[i].disabled && !arr[i].checked) {
|
||||
isSelectedAll.value = false
|
||||
}
|
||||
|
||||
if (arr[i][props.dataChildren]?.length) {
|
||||
obj[props.dataChildren] = initData(arr[i][props.dataChildren], obj.visible)
|
||||
}
|
||||
|
||||
res.push(obj)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
function addNode(node : any, children : any[]) {
|
||||
getReflectNode(node, treeData.value)[props.dataChildren] = children
|
||||
handleHideChildren(node)
|
||||
}
|
||||
|
||||
// 中断懒加载
|
||||
function resetClearTimerList() {
|
||||
const list = [...clearTimerList.value]
|
||||
clearTimerList.value = []
|
||||
list.forEach((fn) => fn())
|
||||
}
|
||||
|
||||
// 懒加载
|
||||
function renderTree(arr : any[]) {
|
||||
const pagingArr = paging(arr)
|
||||
filterTreeData.value = pagingArr?.[0] || []
|
||||
lazyRenderList(pagingArr, 1)
|
||||
}
|
||||
|
||||
// 懒加载具体逻辑
|
||||
function lazyRenderList(arr : any[], startIndex : number) {
|
||||
for (let i = startIndex; i < arr.length; i++) {
|
||||
let timer : any = null
|
||||
timer = setTimeout(() => {
|
||||
filterTreeData.value.push(...arr[i])
|
||||
}, i * 500)
|
||||
clearTimerList.push(() => clearTimeout(timer))
|
||||
}
|
||||
}
|
||||
|
||||
// 根据 dataValue 找节点
|
||||
function changeStatus(list : any[], ids : any[] | string, needEmit = false) {
|
||||
const arr = [...list]
|
||||
let flag = true
|
||||
needEmit && (selectedListBaseinfo.value = [])
|
||||
while (arr.length) {
|
||||
const item = arr.shift()
|
||||
|
||||
if (ids.includes(item[props.dataValue].toString())) {
|
||||
item.checked = true
|
||||
// 数据被选中清除半选状态
|
||||
item.partChecked = false
|
||||
partCheckedSet.delete(item[props.dataValue])
|
||||
needEmit && selectedListBaseinfo.value.push(item)
|
||||
} else {
|
||||
item.checked = false
|
||||
if (item.visible && !item.disabled) {
|
||||
flag = false
|
||||
}
|
||||
if (partCheckedSet.has(item[props.dataValue])) {
|
||||
// filtertreedata 更新状态
|
||||
item.partChecked = true
|
||||
} else {
|
||||
item.partChecked = false
|
||||
}
|
||||
}
|
||||
|
||||
if (item[props.dataChildren]?.length) {
|
||||
arr.push(...item[props.dataChildren])
|
||||
}
|
||||
}
|
||||
isSelectedAll.value = flag
|
||||
|
||||
needEmit && emits('select-change', [...selectedListBaseinfo.value])
|
||||
}
|
||||
|
||||
// 移除选项
|
||||
function removeSelectedItem(node : any) {
|
||||
isSelectedAll.value = false
|
||||
if (props.linkage) {
|
||||
handleNodeClick(node, false)
|
||||
emits('removeSelect', node)
|
||||
} else {
|
||||
const emitData = selectList.value.filter((item : any) => item !== node[props.dataValue].toString())
|
||||
emits('removeSelect', node)
|
||||
emits('update:modelValue', isString(props.modelValue) ? emitData.join(',') : emitData)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取对应数据
|
||||
function getReflectNode(node : any, arr : any[]) {
|
||||
const array = [...arr]
|
||||
while (array.length) {
|
||||
const item = array.shift()
|
||||
if (item[props.dataValue] === node[props.dataValue]) {
|
||||
return item
|
||||
}
|
||||
if (item[props.dataChildren]?.length) {
|
||||
array.push(...item[props.dataChildren])
|
||||
}
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
// 获取某个节点孩子节点
|
||||
function getChildren(node : any) {
|
||||
if (!node[props.dataChildren]?.length) return []
|
||||
const res = node[props.dataChildren].reduce((pre : any, val : any) => {
|
||||
if (val.visible) {
|
||||
return [...pre, val]
|
||||
}
|
||||
return pre
|
||||
}, [])
|
||||
for (let i = 0; i < node[props.dataChildren].length; i++) {
|
||||
res.push(...getChildren(node[props.dataChildren][i]))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// 获取某个节点祖先元素
|
||||
function getParentNode(target : any, arr : any[]) {
|
||||
let res : any[] = []
|
||||
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if (arr[i][props.dataValue] === target[props.dataValue]) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (arr[i][props.dataChildren]?.length) {
|
||||
const childRes = getParentNode(target, arr[i][props.dataChildren])
|
||||
if (typeof childRes === 'boolean' && childRes) {
|
||||
res = [arr[i]]
|
||||
} else if (Array.isArray(childRes) && childRes.length) {
|
||||
res = [...childRes, arr[i]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// 点击checkbox
|
||||
function handleNodeClick(data : any, status : boolean | undefined) {
|
||||
const node = getReflectNode(data, treeData.value)
|
||||
node.checked = typeof status === 'boolean' ? status : !node.checked
|
||||
node.partChecked = false
|
||||
partCheckedSet.delete(node[props.dataValue])
|
||||
// 如果是单选不考虑其他情况
|
||||
if (!props.mutiple) {
|
||||
let emitData : any[] = []
|
||||
if (node.checked) {
|
||||
emitData = [node[props.dataValue].toString()]
|
||||
}
|
||||
emits('update:modelValue', isString(props.modelValue) ? emitData.join(',') : emitData)
|
||||
} else {
|
||||
// 多选情况
|
||||
if (!props.linkage) {
|
||||
// 不需要联动
|
||||
let emitData = null
|
||||
if (node.checked) {
|
||||
emitData = Array.from(new Set([...selectList.value, node[props.dataValue].toString()]))
|
||||
} else {
|
||||
emitData = selectList.value.filter((id : number | string) => id !== node[props.dataValue].toString())
|
||||
}
|
||||
emits('update:modelValue', isString(props.modelValue) ? emitData.join(',') : emitData)
|
||||
} else {
|
||||
// 需要联动
|
||||
let emitData = [...selectList.value]
|
||||
const parentNodes : any = getParentNode(node, treeData.value)
|
||||
const childrenVal = getChildren(node).filter((item : any) => !item.disabled)
|
||||
if (node.checked) {
|
||||
// 选中
|
||||
emitData = Array.from(new Set([...emitData, node[props.dataValue].toString()]))
|
||||
if (childrenVal.length) {
|
||||
emitData = Array.from(
|
||||
new Set([...emitData, ...childrenVal.map((item : any) => item[props.dataValue].toString())])
|
||||
)
|
||||
// 孩子节点全部选中并且清除半选状态
|
||||
childrenVal.forEach((childNode : any) => {
|
||||
childNode.partChecked = false
|
||||
partCheckedSet.delete(childNode[props.dataValue])
|
||||
})
|
||||
}
|
||||
if (parentNodes.length) {
|
||||
let flag = false
|
||||
// 有父元素 如果父元素下所有子元素全部选中,选中父元素
|
||||
while (parentNodes.length) {
|
||||
const item = parentNodes.shift()
|
||||
if (!item.disabled) {
|
||||
if (flag) {
|
||||
// 前一个没选中并且为半选那么之后的全为半选
|
||||
item.partChecked = true
|
||||
partCheckedSet.add(item[props.dataValue])
|
||||
} else {
|
||||
const allChecked = item[props.dataChildren]
|
||||
.filter((node : any) => node.visible && !node.disabled)
|
||||
.every((node : any) => node.checked)
|
||||
if (allChecked) {
|
||||
item.checked = true
|
||||
item.partChecked = false
|
||||
partCheckedSet.delete(item[props.dataValue])
|
||||
emitData = Array.from(new Set([...emitData, item[props.dataValue].toString()]))
|
||||
} else {
|
||||
item.partChecked = true
|
||||
partCheckedSet.add(item[props.dataValue])
|
||||
flag = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 取消选中
|
||||
emitData = emitData.filter((id) => id !== node[props.dataValue].toString())
|
||||
if (childrenVal.length) {
|
||||
// 取消选中全部子节点
|
||||
childrenVal.forEach((childNode : any) => {
|
||||
emitData = emitData.filter((id) => id !== childNode[props.dataValue].toString())
|
||||
})
|
||||
}
|
||||
if (parentNodes.length) {
|
||||
parentNodes.forEach((parentNode : any) => {
|
||||
if (emitData.includes(parentNode[props.dataValue].toString())) {
|
||||
parentNode.checked = false
|
||||
}
|
||||
emitData = emitData.filter((id) => id !== parentNode[props.dataValue].toString())
|
||||
const hasChecked = parentNode[props.dataChildren]
|
||||
.filter((node : any) => node.visible && !node.disabled)
|
||||
.some((node : any) => node.checked || node.partChecked)
|
||||
|
||||
parentNode.partChecked = hasChecked
|
||||
if (hasChecked) {
|
||||
partCheckedSet.add(parentNode[props.dataValue])
|
||||
} else {
|
||||
partCheckedSet.delete(parentNode[props.dataValue])
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
emits('update:modelValue', isString(props.modelValue) ? emitData.join(',') : emitData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 点击名称折叠或展开
|
||||
function handleHideChildren(node : any) {
|
||||
const status = !node.showChildren
|
||||
getReflectNode(node, treeData.value).showChildren = status
|
||||
getReflectNode(node, filterTreeData.value).showChildren = status
|
||||
}
|
||||
|
||||
// 全部选中
|
||||
function handleSelectAll() {
|
||||
isSelectedAll.value = !isSelectedAll.value
|
||||
if (isSelectedAll.value) {
|
||||
if (!props.mutiple) {
|
||||
uni.showToast({
|
||||
title: '单选模式下不能全选',
|
||||
icon: 'none',
|
||||
duration: 1000
|
||||
})
|
||||
return
|
||||
}
|
||||
let emitData : any[] = []
|
||||
treeData.value.forEach((item : any) => {
|
||||
if (item.visible || (item.disabled && item.checked)) {
|
||||
emitData = Array.from(new Set([...emitData, item[props.dataValue].toString()]))
|
||||
if (item[props.dataChildren]?.length) {
|
||||
emitData = Array.from(
|
||||
new Set([
|
||||
...emitData,
|
||||
...getChildren(item)
|
||||
.filter((item : any) => !item.disabled || (item.disabled && item.checked))
|
||||
.map((item : any) => item[props.dataValue].toString())
|
||||
])
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
emits('update:modelValue', isString(props.modelValue) ? emitData.join(',') : emitData)
|
||||
} else {
|
||||
clearSelectList()
|
||||
}
|
||||
}
|
||||
// 清空选项
|
||||
function clearSelectList() {
|
||||
if (props.disabled) return
|
||||
partCheckedSet.clear()
|
||||
const emitData : any[] = []
|
||||
selectedListBaseinfo.value.forEach((node : any) => {
|
||||
if (node.visible && node.checked && node.disabled) {
|
||||
emitData.push(node[props.dataValue])
|
||||
}
|
||||
})
|
||||
emits('update:modelValue', isString(props.modelValue) ? emitData.join(',') : emitData)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$primary-color: #007aff;
|
||||
$col-sm: 4px;
|
||||
$col-base: 8px;
|
||||
$col-lg: 12px;
|
||||
$row-sm: 5px;
|
||||
$row-base: 10px;
|
||||
$row-lg: 15px;
|
||||
$radius-sm: 3px;
|
||||
$radius-base: 6px;
|
||||
|
||||
.select-list {
|
||||
padding-left: $row-base;
|
||||
min-height: 35px;
|
||||
// border: 1px solid #e5e5e5;
|
||||
// border-radius: $radius-sm;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
&.active {
|
||||
padding: calc(#{$col-sm} / 2) 0 calc(#{$col-sm} / 2) $row-base;
|
||||
}
|
||||
|
||||
.left {
|
||||
flex: 1;
|
||||
|
||||
.select-items {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.select-item {
|
||||
max-width: auto;
|
||||
height: auto;
|
||||
// background-color: #eaeaea;
|
||||
// border-radius: $radius-sm;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.name {
|
||||
flex: 1;
|
||||
// padding-right: $row-base;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.close {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// .right {
|
||||
// margin-right: $row-sm;
|
||||
// display: flex;
|
||||
// justify-content: flex-end;
|
||||
// align-items: center;
|
||||
// }
|
||||
|
||||
&.disabled {
|
||||
background-color: #f5f7fa;
|
||||
|
||||
.left {
|
||||
.select-item {
|
||||
.name {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
flex: 1;
|
||||
background-color: #fff;
|
||||
border-top-left-radius: 20px;
|
||||
border-top-right-radius: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.title {
|
||||
padding: $col-base 3rem;
|
||||
border-bottom: 1px solid $uni-border-color;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
|
||||
.left {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.center {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.right {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.search-box {
|
||||
margin: $col-base $row-base 0;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.search-btn {
|
||||
margin-left: $row-base;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
}
|
||||
}
|
||||
|
||||
.select-content {
|
||||
margin: $col-base $row-base;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.scroll-view-box {
|
||||
touch-action: none;
|
||||
flex: 1;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.sentry {
|
||||
height: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
.no-data {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
// .no-data.center {
|
||||
// text-align: center;
|
||||
// }
|
||||
</style>
|
||||
17
components/treeSelect/utils.ts
Normal file
@ -0,0 +1,17 @@
|
||||
export function isString(data: any) {
|
||||
return typeof data === 'string'
|
||||
}
|
||||
|
||||
// 分页
|
||||
export function paging(data: any[], PAGENUM = 50) {
|
||||
if (!Array.isArray(data) || !data.length) return data
|
||||
const pages: any[] = []
|
||||
data.forEach((item, index) => {
|
||||
const i = Math.floor(index / PAGENUM)
|
||||
if (!pages[i]) {
|
||||
pages[i] = []
|
||||
}
|
||||
pages[i].push(item)
|
||||
})
|
||||
return pages
|
||||
}
|
||||
20
index.html
Normal file
@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<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="/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
38
main.js
Normal file
@ -0,0 +1,38 @@
|
||||
import App from './App';
|
||||
import {
|
||||
toast
|
||||
} from './utils/index.js';
|
||||
import {
|
||||
createPinia
|
||||
} from "pinia";
|
||||
import leaveApplication from '@/bpm/leaveApplication/index.vue';
|
||||
import supervise from '@/bpm/supervise.vue'
|
||||
const pinia = createPinia();
|
||||
|
||||
// #ifndef VUE3
|
||||
import Vue from 'vue'
|
||||
import './uni.promisify.adaptor'
|
||||
Vue.config.productionTip = false
|
||||
App.mpType = 'app'
|
||||
const app = new Vue({
|
||||
...App
|
||||
})
|
||||
app.$mount()
|
||||
// #endif
|
||||
|
||||
// #ifdef VUE3
|
||||
import {
|
||||
createSSRApp
|
||||
} from 'vue'
|
||||
|
||||
export function createApp() {
|
||||
const app = createSSRApp(App)
|
||||
app.use(pinia)
|
||||
app.component('leaveApplication', leaveApplication)
|
||||
app.component('supervise', supervise)
|
||||
app.config.globalProperties.$toast = toast
|
||||
return {
|
||||
app
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
122
manifest.json
Normal file
@ -0,0 +1,122 @@
|
||||
{
|
||||
"name": "数智产销",
|
||||
"appid": "__UNI__9F097F0",
|
||||
"description": "",
|
||||
"versionName": "1.1.11",
|
||||
"versionCode": 20250303,
|
||||
"transformPx": false,
|
||||
/* 5+App特有相关 */
|
||||
"app-plus": {
|
||||
"usingComponents": true,
|
||||
"nvueStyleCompiler": "uni-app",
|
||||
"compilerVersion": 3,
|
||||
"splashscreen": {
|
||||
"alwaysShowBeforeRender": true,
|
||||
"waiting": true,
|
||||
"autoclose": true,
|
||||
"delay": 0
|
||||
},
|
||||
"compatible": {
|
||||
"ignoreVersion": true
|
||||
},
|
||||
/* 模块配置 */
|
||||
"modules": {
|
||||
"Geolocation": {},
|
||||
"Fingerprint": {},
|
||||
"Camera": {},
|
||||
"Barcode": {}
|
||||
},
|
||||
/* 应用发布信息 */
|
||||
"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": {},
|
||||
"geolocation": {
|
||||
"system": {
|
||||
"__platform__": ["android"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
/* 快应用特有相关 */
|
||||
"quickapp": {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin": {
|
||||
"appid": "",
|
||||
"setting": {
|
||||
"urlCheck": false
|
||||
},
|
||||
"usingComponents": true
|
||||
},
|
||||
"mp-alipay": {
|
||||
"usingComponents": true
|
||||
},
|
||||
"mp-baidu": {
|
||||
"usingComponents": true
|
||||
},
|
||||
"mp-toutiao": {
|
||||
"usingComponents": true
|
||||
},
|
||||
"uniStatistics": {
|
||||
"enable": false
|
||||
},
|
||||
"vueVersion": "3"
|
||||
}
|
||||
/* 模块配置 */
|
||||
56
package-lock.json
generated
Normal file
@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "cxc-szcx-uniapp",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@dcloudio/uni-ui": "^1.5.6",
|
||||
"base-64": "^1.0.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"echarts": "^5.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@dcloudio/uni-ui": {
|
||||
"version": "1.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@dcloudio/uni-ui/-/uni-ui-1.5.6.tgz",
|
||||
"integrity": "sha512-jmb98PasFvZkrIDXGh94GbdWg2/jyhgs1HUG+bU8eyL7Ltias/5XBz4q8w9RXyWUfqepJRqapPA2IIQpLCuTIg==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/base-64": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/base-64/-/base-64-1.0.0.tgz",
|
||||
"integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg=="
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.13",
|
||||
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
|
||||
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
|
||||
},
|
||||
"node_modules/echarts": {
|
||||
"version": "5.6.0",
|
||||
"resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.6.0.tgz",
|
||||
"integrity": "sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": "2.3.0",
|
||||
"zrender": "5.6.1"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
|
||||
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/zrender": {
|
||||
"version": "5.6.1",
|
||||
"resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.6.1.tgz",
|
||||
"integrity": "sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"tslib": "2.3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
package.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@dcloudio/uni-ui": "^1.5.6",
|
||||
"base-64": "^1.0.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"echarts": "^5.6.0"
|
||||
}
|
||||
}
|
||||
331
pages.json
Normal file
@ -0,0 +1,331 @@
|
||||
{
|
||||
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
|
||||
{
|
||||
"path": "pages/login/login",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/tab/index",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/task/todotask",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/tab/office",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/tab/product",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/tab/my",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"path": "pages/task/index",
|
||||
"style": {
|
||||
"enablePullDownRefresh": true,
|
||||
"app-plus": {
|
||||
"titleNView": {
|
||||
"titleText": "我的任务",
|
||||
"titleColor": "#fff"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/task/handle",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/talk/message_list",
|
||||
"style": {
|
||||
"navigationBarTitleText": "消息",
|
||||
"enablePullDownRefresh": true,
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/talk/conversation",
|
||||
"style": {
|
||||
"navigationBarTitleText": "昵称",
|
||||
"enablePullDownRefresh": true,
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/talk/system",
|
||||
"style": {
|
||||
"navigationBarTitleText": "系统通知",
|
||||
"enablePullDownRefresh": true,
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/document/index",
|
||||
"style": {
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/document/detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "详情",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/document/onlinePreview",
|
||||
"style": {
|
||||
"navigationBarTitleText": "在线预览",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/views/zhongheguanli/meeting/index",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/views/zhongheguanli/meeting/detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "详情",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/checkin/index",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/useredit/useredit",
|
||||
"style": {
|
||||
"navigationBarTitleText": "资料编辑",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/useredit/address",
|
||||
"style": {
|
||||
"navigationBarTitleText": "地址",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/useredit/add_address",
|
||||
"style": {
|
||||
"navigationBarTitleText": "添加地址",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/useredit/addressbook",
|
||||
"style": {
|
||||
"navigationBarTitleText": "通讯录",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
// {
|
||||
// "path": "pages/task/todotask",
|
||||
// "style": {
|
||||
// "navigationBarTitleText": "个人办公",
|
||||
// "enablePullDownRefresh": false,
|
||||
// "navigationBarTextStyle": "white"
|
||||
// }
|
||||
// },
|
||||
{
|
||||
"path": "pages/safe/manage",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/views/shengchan/index",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
// "navigationBarTitleText": "生产数据",
|
||||
// "enablePullDownRefresh": false,
|
||||
// "navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/views/shengchan/ribaoshuju/rbsjLsxq",
|
||||
"style": {
|
||||
// "navigationStyle": "custom"
|
||||
"navigationBarTitleText": "历史详情",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/userlist/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/safe/detail",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/views/zhongheguanli/zhiban/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "值班信息",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/task/self",
|
||||
"style": {
|
||||
"navigationBarTitleText": "本人发起",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/views/renliziyuan/renyuanxinxi/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "人员信息",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/views/renliziyuan/renyuanxinxi/taizhang",
|
||||
"style": {
|
||||
"navigationBarTitleText": "台账信息",
|
||||
"navigationBarTextStyle": "white"
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/views/renliziyuan/renyuanxinxi/detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "人员详细信息",
|
||||
"navigationBarTextStyle": "white"
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/views/renliziyuan/renyuanxinxi/tongji",
|
||||
"style": {
|
||||
"navigationBarTitleText": "人员年龄分组统计信息",
|
||||
"navigationBarTextStyle": "white"
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/views/renliziyuan/renyuanxinxi/qttongji",
|
||||
"style": {
|
||||
"navigationBarTitleText": "其他统计信息",
|
||||
"navigationBarTextStyle": "white"
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/views/renliziyuan/qingjiaxinxi/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "请假信息",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/views/renliziyuan/qingjiaxinxi/detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "请假详情",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/views/renliziyuan/qingjiaxinxi/application",
|
||||
"style": {
|
||||
"navigationBarTitleText": "请假申请",
|
||||
"enablePullDownRefresh": false,
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tabBar": {
|
||||
"color": "#333333",
|
||||
"selectedColor": "#01508B",
|
||||
"borderStyle": "black",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
|
||||
"list": [{
|
||||
"text": "首页",
|
||||
"pagePath": "pages/tab/index",
|
||||
"iconPath": "static/tab/index1.png",
|
||||
"selectedIconPath": "static/tab/index2.png"
|
||||
},
|
||||
|
||||
{
|
||||
"text": "生产",
|
||||
"pagePath": "pages/tab/product",
|
||||
"iconPath": "/static/tab/product.png",
|
||||
"selectedIconPath": "/static/tab/product2.png"
|
||||
},
|
||||
{
|
||||
"text": "办公",
|
||||
"pagePath": "pages/tab/office",
|
||||
"iconPath": "static/tab/OA.png",
|
||||
"selectedIconPath": "static/tab/OA1.png"
|
||||
}, {
|
||||
"text": "任务",
|
||||
"pagePath": "pages/task/todotask",
|
||||
"iconPath": "static/tab/office1.png",
|
||||
"selectedIconPath": "static/tab/office2.png"
|
||||
},
|
||||
{
|
||||
"text": "我的",
|
||||
"pagePath": "pages/tab/my",
|
||||
"iconPath": "static/tab/user1.png",
|
||||
"selectedIconPath": "static/tab/user2.png"
|
||||
}
|
||||
]
|
||||
|
||||
// "midButton": {
|
||||
// "width": "65px",
|
||||
// "height": "75px",
|
||||
// "text": "",
|
||||
// "iconPath": "static/tab/todo.png",
|
||||
// "iconWidth": "50px",
|
||||
// }
|
||||
},
|
||||
"globalStyle": {
|
||||
"app-plus": {
|
||||
"titleNView": {
|
||||
"backgroundImage": "linear-gradient(to left , #256FBC, #044D87)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"uniIdRouter": {}
|
||||
}
|
||||
232
pages/checkin/index.vue
Normal file
@ -0,0 +1,232 @@
|
||||
<template>
|
||||
<view :class="['content',{'gray':store.isgray==1}]">
|
||||
<customNav>
|
||||
<view class="nav_box f-row aic">
|
||||
<view class="back" @click="back">
|
||||
<uni-icons type="left" size="20" color="#fff"></uni-icons>
|
||||
</view>
|
||||
<view class="avatar">
|
||||
<image :src="store.userinfo.avatar" mode=""></image>
|
||||
</view>
|
||||
<view class="f-col">
|
||||
<view class="name">
|
||||
{{store.userinfo.realname}}
|
||||
</view>
|
||||
<view class="position">
|
||||
{{store.role}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</customNav>
|
||||
<view class="time_box f-row aic jcb">
|
||||
<view class="box">
|
||||
<view class="time f-row aic">
|
||||
<view class="">
|
||||
上班 9:30
|
||||
</view>
|
||||
<image src="../../static/checkin/chenggong.png" mode=""></image>
|
||||
</view>
|
||||
<view class="text">
|
||||
重庆市渝北区上弯路
|
||||
</view>
|
||||
</view>
|
||||
<view class="box">
|
||||
<view class="time f-row aic">
|
||||
<view class="">
|
||||
下班 16:30
|
||||
</view>
|
||||
<image src="../../static/checkin/shibai.png" mode=""></image>
|
||||
</view>
|
||||
<view class="text">
|
||||
打卡已超时
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="checkin">
|
||||
<view class=" f-col aic">
|
||||
<view class="status f-col aic">
|
||||
<!-- <image src="../../static/checkin/position1.png" mode=""></image>
|
||||
<image src="../../static/checkin/position2.png" mode=""></image>
|
||||
<image src="../../static/checkin/position3.png" mode=""></image> -->
|
||||
<image src="../../static/checkin/position4.png" mode=""></image>
|
||||
<text>打卡失败</text>
|
||||
</view>
|
||||
<view :class="['circle', 'f-col', 'aic','out','check','success','fail']">
|
||||
<view class="title">
|
||||
上班打卡
|
||||
</view>
|
||||
<view class="time">
|
||||
9:00
|
||||
</view>
|
||||
<view class="ontime">
|
||||
已超时
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
const store = useStore();
|
||||
import customNav from '../../bpm/customNav.vue';
|
||||
const back = () => {
|
||||
uni.navigateBack()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
padding-bottom: 120rpx;
|
||||
}
|
||||
|
||||
.nav_box {
|
||||
position: absolute;
|
||||
bottom: 16rpx;
|
||||
left: 0;
|
||||
width: calc(100% - 60rpx);
|
||||
}
|
||||
|
||||
.back {
|
||||
padding-left: 30rpx;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
border-radius: 32rpx;
|
||||
background-color: #fff;
|
||||
margin-right: 20rpx;
|
||||
margin-left: 50rpx;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 28rpx;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.position {
|
||||
font-size: 24rpx;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
|
||||
.time_box {
|
||||
padding: 30rpx;
|
||||
|
||||
.box {
|
||||
padding: 40rpx 30rpx;
|
||||
flex: 1;
|
||||
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.box:nth-child(1) {
|
||||
border: 1rpx solid #3AC050;
|
||||
background: #F5FFF7;
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
|
||||
.box:nth-child(2) {
|
||||
background: #FFF7F5;
|
||||
border: 1rpx solid #F05C43;
|
||||
}
|
||||
|
||||
.time {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
|
||||
image {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 24rpx;
|
||||
color: #888888;
|
||||
margin-top: 18rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.checkin {
|
||||
margin: 0 30rpx;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
height: 818rpx;
|
||||
|
||||
.status {
|
||||
image {
|
||||
width: 58rpx;
|
||||
height: 69rpx;
|
||||
margin-top: 71rpx;
|
||||
}
|
||||
|
||||
font-weight: 600;
|
||||
font-size: 46rpx;
|
||||
color: #F05C43;
|
||||
|
||||
text {
|
||||
margin-top: 23rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.out {
|
||||
background-image: url('../../static/checkin/circle1.png');
|
||||
}
|
||||
|
||||
.check {
|
||||
background-image: url('../../static/checkin/circle2.png');
|
||||
}
|
||||
|
||||
.success {
|
||||
background-image: url('../../static/checkin/circle3.png');
|
||||
}
|
||||
|
||||
.fail {
|
||||
background-image: url('../../static/checkin/circle4.png');
|
||||
}
|
||||
|
||||
.circle {
|
||||
width: 350rpx;
|
||||
height: 350rpx;
|
||||
|
||||
background-size: 350rpx 350rpx;
|
||||
margin-top: 150rpx;
|
||||
|
||||
.title,
|
||||
.time {
|
||||
font-weight: 600;
|
||||
font-size: 46rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-top: 80rpx;
|
||||
}
|
||||
|
||||
.time {
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.ontime {
|
||||
font-size: 28rpx;
|
||||
color: #888888;
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
120
pages/document/detail.vue
Normal file
@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<view :class="['content',{'gray':store.isgray==1}]">
|
||||
<view class="title_box">
|
||||
<view class="title">
|
||||
{{detail._title}}
|
||||
</view>
|
||||
<view class="time">
|
||||
{{detail._time}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="document f-row">
|
||||
<text class="">
|
||||
附件:
|
||||
</text>
|
||||
<view class="f-col">
|
||||
<view v-if="ifH5">
|
||||
<!-- 在线预览 by 闵 -->
|
||||
<view class="" style="padding: 5rpx 0;" @click="onlinePreview(`/pages/document/onlinePreview?data=${JSON.stringify(item)}`)"
|
||||
v-for="item,i in detail?.pdf?.split(',')">
|
||||
{{item}}
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view v-else>
|
||||
<view class="" style="padding: 5rpx 0;" @click="opendocument(item)"
|
||||
v-for="item,i in detail?.pdf?.split(',')">
|
||||
{{item}}
|
||||
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from 'vue'
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
opendocument
|
||||
} from '@/utils/index.js';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
const store = useStore();
|
||||
|
||||
const detail = ref({})
|
||||
//判断是否h5 by 闵
|
||||
var ifH5 = false;
|
||||
|
||||
const onlinePreview = (url)=>{ //在线预览文件 by 闵
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
}
|
||||
|
||||
onLoad((options) => {
|
||||
detail.value = JSON.parse(options.data)
|
||||
if (options.id == 0) {
|
||||
detail.value.pdf = detail.value.wjbt
|
||||
} else if (options.id == 2) {
|
||||
if (detail.value.jdwj) {
|
||||
detail.value.pdf = detail.value.jdwj + ',' + detail.value.sszd
|
||||
} else {
|
||||
detail.value.pdf = detail.value.sszd
|
||||
}
|
||||
|
||||
} else if (options.id == 3) {
|
||||
detail.value.pdf = detail.value.mingcheng
|
||||
}
|
||||
//#ifdef H5 || MP-WEIXIN
|
||||
ifH5 = true;
|
||||
//#endif
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* page{
|
||||
background-color: #f8f8f8;
|
||||
} */
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.title_box {
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
padding: 30rpx 0 20rpx 0;
|
||||
}
|
||||
|
||||
.time {
|
||||
font-size: 24rpx;
|
||||
color: #888888;
|
||||
padding-bottom: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.document {
|
||||
text {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
view {
|
||||
font-size: 28rpx;
|
||||
color: #5A79F8;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
322
pages/document/index.vue
Normal file
@ -0,0 +1,322 @@
|
||||
<template>
|
||||
<view :class="['content',{'gray':store.isgray==1}]">
|
||||
<customNav>
|
||||
<view class="nav_box f-row aic jcb">
|
||||
<view class="back f-row aic" @click="back">
|
||||
<uni-icons type="left" size="20" color="#fff"></uni-icons>
|
||||
</view>
|
||||
<view class="search f-row aic">
|
||||
<input type="text" v-model="searchKey" @confirm="search" @blur="showicon=true&&!searchKey"
|
||||
@focus="showicon=false" />
|
||||
<view class="f-row aic" v-if="showicon">
|
||||
<image src="../../static/search.png" mode=""></image>
|
||||
<text>搜索</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</customNav>
|
||||
<view class="list">
|
||||
<view class="item" v-for="item,i in list" :key="i"
|
||||
@click="jump(`/pages/document/detail?data=${JSON.stringify(item)}&id=${id}`,item)">
|
||||
<view class="title">
|
||||
{{item._title}}
|
||||
</view>
|
||||
<view class="time_box f-row aic">
|
||||
<view class="time">
|
||||
{{item._time}}
|
||||
</view>
|
||||
<view class="look f-row aic" v-if="item._depart">
|
||||
{{item._depart}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
watch
|
||||
} from 'vue';
|
||||
import {
|
||||
onReachBottom,
|
||||
onPullDownRefresh,
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
gongwenlistApi,
|
||||
faguiApi,
|
||||
zhiduApi,
|
||||
gonggaolistApi,
|
||||
cjzhiduApi
|
||||
} from '@/api/api.js';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
const store = useStore();
|
||||
import customNav from '@/bpm/customNav.vue';
|
||||
import {
|
||||
beforeJump,
|
||||
opendocument
|
||||
} from '@/utils/index.js';
|
||||
const showicon = ref(true)
|
||||
const searchKey = ref('')
|
||||
const list = ref([])
|
||||
let pageNo = 1
|
||||
let pageSize = 15
|
||||
let loading = false
|
||||
/**公文接口*/
|
||||
const bpmlist = () => {
|
||||
loading = true
|
||||
gongwenlistApi({
|
||||
pageNo,
|
||||
pageSize,
|
||||
fwbt: formatSearchkey()
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
list.value = [...list.value, ...formatObj(res.result.records, 'fwbt', 'fwtime', null)]
|
||||
}
|
||||
loading = false
|
||||
}).catch((err) => {
|
||||
console.log('err', err);
|
||||
})
|
||||
}
|
||||
|
||||
/**制度接口*/
|
||||
const zhidu = () => {
|
||||
loading = true
|
||||
let getzhidu = zhiduid == 0 ? zhiduApi : cjzhiduApi
|
||||
getzhidu({
|
||||
pageNo,
|
||||
pageSize,
|
||||
zdmc: formatSearchkey()
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
let str = zhiduid == 0 ? 'zbbm_dictText' : 'sbbm'
|
||||
list.value = [...list.value, ...formatObj(res.result.records, 'zdmc', str, null)]
|
||||
}
|
||||
loading = false
|
||||
}).catch((err) => {
|
||||
console.log('err', err);
|
||||
})
|
||||
}
|
||||
/**法规接口*/
|
||||
const fagui = () => {
|
||||
loading = true
|
||||
faguiApi({
|
||||
pageNo,
|
||||
pageSize,
|
||||
flfgmc: formatSearchkey()
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
list.value = [...list.value, ...formatObj(res.result.records, 'flfgmc', 'ssbm', null)]
|
||||
|
||||
}
|
||||
loading = false
|
||||
}).catch((err) => {
|
||||
console.log('err', err);
|
||||
})
|
||||
}
|
||||
|
||||
/**公告接口*/
|
||||
const gonggaolist = () => {
|
||||
loading = true
|
||||
gonggaolistApi({
|
||||
pageNo,
|
||||
pageSize,
|
||||
neirong:formatSearchkey()
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
list.value = [...list.value, ...formatObj(res.result.records, 'neirong', 'fbdw', 'createTime')]
|
||||
}
|
||||
loading = false
|
||||
}).catch((err) => {
|
||||
console.log('err', err);
|
||||
})
|
||||
}
|
||||
const formatObj = (arr, title, time, depart) => {
|
||||
arr.map((item) => {
|
||||
item['_title'] = item[title]
|
||||
item['_time'] = item[time]
|
||||
item['_depart'] = item[depart]
|
||||
})
|
||||
return arr
|
||||
}
|
||||
const formatSearchkey = () => {
|
||||
if (searchKey.value.trim()) {
|
||||
return '*' + searchKey.value + '*'
|
||||
}
|
||||
}
|
||||
const search = () => {
|
||||
pageNo = 1
|
||||
loading = false
|
||||
list.value = []
|
||||
getlist()
|
||||
}
|
||||
watch(searchKey, (nval, oval) => {
|
||||
if (!nval.trim()) {
|
||||
getlist()
|
||||
}
|
||||
})
|
||||
const back = () => {
|
||||
uni.navigateBack()
|
||||
}
|
||||
const jump = (url, item) => {
|
||||
if (id.value == 3) {
|
||||
return opendocument(item.mingcheng)
|
||||
}
|
||||
beforeJump(url, () => {
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
})
|
||||
}
|
||||
const id = ref(null)
|
||||
let zhiduid = null
|
||||
onLoad((options) => {
|
||||
id.value = options.id
|
||||
zhiduid = options.zhiduid
|
||||
getlist()
|
||||
})
|
||||
const getlist = () => {
|
||||
if (id.value == 0) {
|
||||
bpmlist()
|
||||
} else if (id.value == 1) {
|
||||
gonggaolist()
|
||||
} else if (id.value == 2) {
|
||||
zhidu()
|
||||
} else if (id.value == 3) {
|
||||
fagui()
|
||||
}
|
||||
}
|
||||
onPullDownRefresh(() => {
|
||||
pageNo = 1
|
||||
loading = false
|
||||
list.value = []
|
||||
getlist()
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
onReachBottom(() => {
|
||||
if (loading) return
|
||||
pageNo++
|
||||
getlist()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
padding-top: v-bind(cusnavbarheight);
|
||||
padding-bottom: 24rpx;
|
||||
|
||||
}
|
||||
|
||||
.list {
|
||||
padding: 0 30rpx;
|
||||
|
||||
.item {
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-top: 24rpx;
|
||||
position: relative;
|
||||
|
||||
.dot {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
background: #ED361D;
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
left: 9rpx;
|
||||
top: 44rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-bottom: 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.time_box {
|
||||
font-size: 24rpx;
|
||||
color: #888888;
|
||||
|
||||
|
||||
|
||||
.look {
|
||||
position: relative;
|
||||
margin-left: 60rpx;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
content: ' ';
|
||||
width: 2rpx;
|
||||
height: 20rpx;
|
||||
background: #999999;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
left: -30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
image {
|
||||
width: 28rpx;
|
||||
height: 22rpx;
|
||||
margin-left: 62rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.nav_box {
|
||||
position: absolute;
|
||||
bottom: 14rpx;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.back {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.search {
|
||||
position: relative;
|
||||
padding-right: 30rpx;
|
||||
flex: 1;
|
||||
|
||||
view {
|
||||
position: absolute;
|
||||
left: 28rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
|
||||
}
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
height: 72rpx;
|
||||
background: #F8F8F8;
|
||||
border-radius: 44rpx;
|
||||
padding: 0 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
44
pages/document/onlinePreview.vue
Normal file
@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<view :class="['content',{'gray':store.isgray==1}]">
|
||||
<iframe id="bdIframe" :src="fileUrl" ref="bdIframe" style="border: none;" class="iframe" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
import Base64 from '@/utils/code.js';
|
||||
const baseUrl = import.meta.env.VITE_REQUEST_BASE_URL + '/jeecg-boot/sys/common/static/'
|
||||
const store = useStore();
|
||||
|
||||
var fileUrl = "";
|
||||
|
||||
onLoad((options) => {
|
||||
let base64 = new Base64();
|
||||
var url= JSON.parse(options.data)
|
||||
url = baseUrl + url;
|
||||
fileUrl = 'https://10.75.166.6/preview/onlinePreview' + '?url=' + encodeURIComponent(base64.encode(url))
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
|
||||
}
|
||||
#bdIframe {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
|
||||
}
|
||||
</style>
|
||||
385
pages/leave/application.vue
Normal file
@ -0,0 +1,385 @@
|
||||
<template>
|
||||
<view :class="{'gray':store.isgray==1}">
|
||||
<view class="form">
|
||||
<view class="f-row aic jcb input_box">
|
||||
<view class="title">
|
||||
职工姓名:
|
||||
</view>
|
||||
<input v-model="realname" disabled />
|
||||
</view>
|
||||
<view class="f-row aic jcb input_box">
|
||||
<view class="title">
|
||||
工作单位:
|
||||
</view>
|
||||
<input v-model="depart" disabled />
|
||||
</view>
|
||||
<view class="f-row aic jcb input_box">
|
||||
<view class="title">
|
||||
联系方式:
|
||||
</view>
|
||||
<input v-model="phone" />
|
||||
</view>
|
||||
<view class="f-row aic jcb input_box">
|
||||
<view class="title">
|
||||
请假类型:
|
||||
</view>
|
||||
<tree-select :dataSource="dataSource" v-model="type" dataValue="name" />
|
||||
</view>
|
||||
<picker mode="date" fields="day" @change="chooseStart" :value="beginTime" :end="endTime">
|
||||
<view class="f-row aic jcb box">
|
||||
<view class="title">
|
||||
开始时间:
|
||||
</view>
|
||||
<view class="f-row aic">
|
||||
<view :class="[{'choose':!beginTime},{'choosed':beginTime}]">
|
||||
{{beginTime?beginTime:'请选择'}}
|
||||
</view>
|
||||
<uni-icons type="bottom" color="#333333"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</picker>
|
||||
<picker mode="date" fields="day" @change="chooseEnd" :value="endTime" :start="beginTime">
|
||||
<view class="f-row aic jcb box">
|
||||
<view class="title">
|
||||
截止时间:
|
||||
</view>
|
||||
<view class="f-row aic">
|
||||
<view :class="[{'choose':!endTime},{'choosed':endTime}]">
|
||||
{{endTime?endTime:'请选择'}}
|
||||
</view>
|
||||
<uni-icons type="bottom" color="#333333"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</picker>
|
||||
<picker @change="bindType" :value="typeIndex" :range="typeArr" range-key="realname" v-if="ifShow">
|
||||
<view class="f-row aic jcb box">
|
||||
<view class="title">
|
||||
审批领导:
|
||||
</view>
|
||||
<view class="f-row aic">
|
||||
<view :class="[{'choose':typeIndex==null},{'choosed':typeIndex!=null}]">
|
||||
{{typeIndex!=null?typeArr[typeIndex].realname:'请选择'}}
|
||||
</view>
|
||||
<uni-icons type="bottom" color="#333333"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</picker>
|
||||
<view class="f-row aic jcb input_box">
|
||||
<view class="title">
|
||||
出发地:
|
||||
</view>
|
||||
<input v-model="departure" placeholder="请输入" nplaceholder-style="font-size: 28rpx;color: #999999;" />
|
||||
</view>
|
||||
<view class="f-row aic jcb input_box">
|
||||
<view class="title">
|
||||
目的地:
|
||||
</view>
|
||||
<input v-model="destination" placeholder="请输入" nplaceholder-style="font-size: 28rpx;color: #999999;" />
|
||||
</view>
|
||||
<view class="f-row aic jcb input_box">
|
||||
<view class="title">
|
||||
请假事由:
|
||||
</view>
|
||||
<input v-model="reason" placeholder="请输入" placeholder-style="font-size: 28rpx;color: #999999;" />
|
||||
</view>
|
||||
<view class="f-row aic jcb input_box">
|
||||
<view class="title">
|
||||
上传附件:
|
||||
</view>
|
||||
<uni-file-picker @select="select" :image-styles="imageStyles" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="btn f-col aic">
|
||||
<view @click="qjAdd">
|
||||
提交
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
getCurrentInstance
|
||||
} from 'vue';
|
||||
import {
|
||||
startMutilProcessApi,
|
||||
getCategoryItemsApi,
|
||||
} from '@/api/api.js';
|
||||
import {
|
||||
qjAddApi,
|
||||
queryZwmcAndExaApi,
|
||||
queryHisDateApi
|
||||
} from '@/api/pages.js';
|
||||
import {
|
||||
queryDepByCode,
|
||||
queryZbDepByLdhth
|
||||
} from '@/api/depart.js'
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app'
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
import treeSelect from "@/components/treeSelect/treeSelect.vue"
|
||||
|
||||
const store = useStore()
|
||||
const {
|
||||
proxy
|
||||
} = getCurrentInstance()
|
||||
|
||||
/**职工姓名*/
|
||||
const realname = ref(store.userinfo.realname)
|
||||
/**工作单位*/
|
||||
const depart = ref('')
|
||||
/**工作单位*/
|
||||
const orgCode = ref('')
|
||||
/**联系方式*/
|
||||
const phone = ref(store.userinfo.phone)
|
||||
/**请假类型*/
|
||||
const type = ref('')
|
||||
const dataSource = ref([])
|
||||
/**开始时间*/
|
||||
const beginTime = ref('')
|
||||
const chooseStart = (e) => {
|
||||
beginTime.value = e.detail.value
|
||||
}
|
||||
/**结束时间*/
|
||||
const endTime = ref('')
|
||||
const chooseEnd = (e) => {
|
||||
endTime.value = e.detail.value
|
||||
}
|
||||
/**审批领导*/
|
||||
const typeArr = ref([])
|
||||
const typeIndex = ref(null)
|
||||
/**判断是否显示审批领导字段*/
|
||||
const ifShow = ref(true)
|
||||
/**职位层级*/
|
||||
const zwcj = ref('')
|
||||
/**出发地*/
|
||||
const departure = ref('')
|
||||
/**目的地*/
|
||||
const destination = ref('')
|
||||
/**请假事由*/
|
||||
const reason = ref('')
|
||||
/**附件路径*/
|
||||
const path = ref([])
|
||||
const baseUrl = import.meta.env.VITE_REQUEST_BASE_URL + '/jeecg-boot/sys/common/upload/'
|
||||
const imageStyles = {
|
||||
width: 64,
|
||||
height: 64,
|
||||
border: {
|
||||
color: "#dce7e1",
|
||||
width: 2,
|
||||
style: 'dashed',
|
||||
radius: '2px'
|
||||
}
|
||||
}
|
||||
onLoad(() => {
|
||||
loadData()
|
||||
// getTomorrowDate()
|
||||
})
|
||||
|
||||
const select = (e) => {
|
||||
const tempFilePaths = e.tempFilePaths
|
||||
for (let i = 0; i < e.tempFilePaths.length; i++) {
|
||||
let photoPath = '职工请假/' + depart.value + '/' + store.userinfo.realname
|
||||
uni.uploadFile({
|
||||
url: baseUrl,
|
||||
filePath: e.tempFilePaths[i],
|
||||
name: 'file',
|
||||
formData: {
|
||||
appPath: photoPath
|
||||
},
|
||||
success: (res) => {
|
||||
path.value.push(JSON.parse(res.data).message)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const qjAdd = () => {
|
||||
if (!phone.value.trim()) return proxy.$toast('请输入联系方式')
|
||||
if (!type.value) return proxy.$toast('请选择请假类型')
|
||||
if (!beginTime.value) return proxy.$toast('请选择开始时间')
|
||||
if (!endTime.value) return proxy.$toast('请选择结束时间')
|
||||
if (ifShow.value) {
|
||||
if (typeIndex.value == null) { //副职、员工需要选择审批领导
|
||||
return proxy.$toast('请选择审批领导')
|
||||
}
|
||||
}
|
||||
if (!departure.value.trim()) return proxy.$toast('请输入出发地')
|
||||
if (!destination.value.trim()) return proxy.$toast('请输入目的地')
|
||||
if (!reason.value.trim()) return proxy.$toast('请输入请假事由')
|
||||
|
||||
qjAddApi({
|
||||
sysOrgCode: orgCode.value,
|
||||
username: store.userinfo.username,
|
||||
phone: phone.value,
|
||||
type: type.value,
|
||||
begintime: beginTime.value,
|
||||
endtime: endTime.value,
|
||||
examineleader: typeArr.value[typeIndex.value] ? typeArr.value[typeIndex.value].username : '',
|
||||
departure: departure.value,
|
||||
destination: destination.value,
|
||||
reason: reason.value,
|
||||
zwmc: zwcj.value,
|
||||
path: path.value.toString()
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
startMutilProcess(res.message)
|
||||
} else {
|
||||
proxy.$toast(res.message);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const startMutilProcess = (id) => {
|
||||
startMutilProcessApi({
|
||||
flowCode: "dev_cxc_qxj",
|
||||
id,
|
||||
formUrl: "modules/qxj/modules/CxcQxjBpmModel",
|
||||
formUrlMobile: "leaveApplication" //对应main.js里全局注册createApp()里的 app.component('leaveApplication',index)
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
proxy.$toast(res.message)
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 2000)
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
})
|
||||
}
|
||||
const loadData = () => {
|
||||
getCategoryItemsApi('1838487445813645313').then((res) => { //请假类型
|
||||
if (res.success) {
|
||||
dataSource.value = res.result
|
||||
}
|
||||
})
|
||||
|
||||
queryZbDepByLdhth(store.userinfo.workNo).then((res) => { //获取工作单位
|
||||
depart.value = res.departName
|
||||
orgCode.value = res.orgCode
|
||||
})
|
||||
|
||||
queryZwmcAndExaApi(store.userinfo.username).then((res) => { //本人职位及审批领导列表
|
||||
if (res.success) {
|
||||
typeArr.value = res.result.list
|
||||
zwcj.value = res.result.zwmc
|
||||
if (zwcj.value == '单位专家' || zwcj.value == '基层正职' || zwcj.value == '高级主管') {
|
||||
ifShow.value = false;
|
||||
}
|
||||
} else {
|
||||
proxy.$toast(res.message);
|
||||
}
|
||||
})
|
||||
|
||||
queryHisDateApi(store.userinfo.username).then((res) => { // 最新请假结束日期
|
||||
if (res) {
|
||||
console.log('--0', res)
|
||||
getTomorrowDate(res);
|
||||
} else {
|
||||
console.log('--1', res)
|
||||
getTomorrowDate();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const bindType = (e) => {
|
||||
typeIndex.value = e.detail.value
|
||||
}
|
||||
|
||||
const getTomorrowDate = (e) => {
|
||||
let tomorrow;
|
||||
if (e) {
|
||||
// 将传入的日期字符串转换为Date对象
|
||||
const dateParts = e.split('-').map(Number);
|
||||
tomorrow = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);
|
||||
} else {
|
||||
// 如果没有提供日期,则使用当前日期
|
||||
tomorrow = new Date();
|
||||
}
|
||||
// 设置为明天的日期
|
||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||
// 格式化日期
|
||||
const year = tomorrow.getFullYear();
|
||||
const month = (tomorrow.getMonth() + 1).toString().padStart(2, '0');
|
||||
const day = tomorrow.getDate().toString().padStart(2, '0');
|
||||
beginTime.value = `${year}-${month}-${day}`;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page {
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.btn {
|
||||
border-top: 1px solid #EFEFEF;
|
||||
height: 120rpx;
|
||||
justify-content: center;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100vw;
|
||||
|
||||
view {
|
||||
width: 690rpx;
|
||||
height: 88rpx;
|
||||
background: #01508B;
|
||||
border-radius: 16rpx;
|
||||
font-size: 28rpx;
|
||||
color: #FFFFFF;
|
||||
text-align: center;
|
||||
line-height: 88rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.input_box {
|
||||
height: 100rpx;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
text-align: right;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.form {
|
||||
padding: 0 30rpx;
|
||||
background-color: #fff;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.box {
|
||||
height: 100rpx;
|
||||
}
|
||||
|
||||
.box:not(:last-child) {
|
||||
border-bottom: 1px solid #EFEFEF;
|
||||
|
||||
}
|
||||
|
||||
.choose {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.choosed {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
321
pages/login/login.vue
Normal file
@ -0,0 +1,321 @@
|
||||
<template>
|
||||
<view :class="{'gray':store.isgray==1}">
|
||||
<view class="logo f-col aic">
|
||||
<image src="@/static/login/logo.png"></image>
|
||||
</view>
|
||||
<view class="form f-col aic">
|
||||
<view class="box f-row aic">
|
||||
<image src="@/static/login/phone.png"></image>
|
||||
<input v-model="username" type="text" placeholder="请输入统一身份认证"
|
||||
placeholder-style="font-size: 28rpx;color: #999999;" />
|
||||
</view>
|
||||
<view class="box f-row aic">
|
||||
<image src="@/static/login/pwd.png"></image>
|
||||
<input v-model="password" :type="!showpwd?'password':'text'" placeholder="请输入密码"
|
||||
placeholder-style="font-size: 28rpx;color: #999999;" />
|
||||
<image v-if="showpwd" src="@/static/login/eye.png" @click="showpwd = !showpwd"></image>
|
||||
<image v-else src="@/static/login/eye-off.png" @click="showpwd = !showpwd"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="pwd f-row aic">
|
||||
<view style="display: inline-block;" @click="check = !check">
|
||||
<view class="f-row aic">
|
||||
<image v-if="!check" src="@/static/login/nocheck.png"></image>
|
||||
<image v-else src="@/static/login/checked.png"></image>
|
||||
<text>记住密码</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="login f-col aic">
|
||||
<view @click="login">
|
||||
登录
|
||||
</view>
|
||||
</view>
|
||||
<view class="login f-col aic">
|
||||
<text style="font-size: 10px;">Copyright (c) 2024 天然气产销厂</text>
|
||||
<text style="font-size: 10px;">版本号:{{systemInfo.appWgtVersion}}</text>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
getCurrentInstance,
|
||||
watch
|
||||
} from 'vue';
|
||||
import {
|
||||
loginApi,
|
||||
localLoginApi,
|
||||
queryRoleApi
|
||||
} from '@/api/login.js';
|
||||
import {
|
||||
taskListApi
|
||||
} from '@/api/api.js';
|
||||
import Base64 from 'base-64';
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app'
|
||||
import {
|
||||
useStore
|
||||
} from '@/store'
|
||||
const store = useStore()
|
||||
const {
|
||||
proxy
|
||||
} = getCurrentInstance()
|
||||
|
||||
/** 系统信息 */
|
||||
const systemInfo = uni.getSystemInfoSync()
|
||||
/**是否明文显示密码*/
|
||||
const showpwd = ref(false)
|
||||
/**用于用户缓存账号和密码*/
|
||||
let localObj = {}
|
||||
/**记住账号和密码*/
|
||||
const savePwd = () => {
|
||||
let localObj = {
|
||||
un: username.value
|
||||
}
|
||||
if (check.value) {
|
||||
localObj.pw = password.value
|
||||
}
|
||||
uni.setStorageSync('accountObj', JSON.stringify(localObj))
|
||||
}
|
||||
|
||||
/**是否选中记住密码*/
|
||||
const check = ref(true);
|
||||
/**账号*/
|
||||
const username = ref('')
|
||||
/**密码*/
|
||||
const password = ref('')
|
||||
const login = () => {
|
||||
if (!username.value.trim()) return proxy.$toast('请输入账号')
|
||||
if (!password.value.trim()) return proxy.$toast('请输入密码')
|
||||
let un = Base64.encode(encodeURIComponent(username.value))
|
||||
let pw = Base64.encode(encodeURIComponent(password.value))
|
||||
uni.showLoading({
|
||||
title: '登录中...'
|
||||
});
|
||||
|
||||
/*生产环境 begin */
|
||||
loginApi({
|
||||
username: un,
|
||||
password: pw,
|
||||
ip: getDeviceIp()
|
||||
/*生产环境 end */
|
||||
|
||||
/*开发环境 begin */
|
||||
// localLoginApi({
|
||||
// username: username.value,
|
||||
// password: password.value,
|
||||
// captcha: 'app'
|
||||
/*开发环境 end */
|
||||
}).then((loginres) => {
|
||||
if (loginres.success) {
|
||||
uni.setStorageSync('token', loginres.result.token)
|
||||
store.setToken(loginres.result.token)
|
||||
savePwd()
|
||||
queryRoleApi({
|
||||
roles: loginres.result.userInfo.roles
|
||||
}).then((roleres) => {
|
||||
//登录时间
|
||||
uni.setStorageSync('logintime', Date.now())
|
||||
// 登录人的角色
|
||||
uni.setStorageSync('role', roleres)
|
||||
store.setRole(roleres)
|
||||
|
||||
// 登录人信息
|
||||
uni.setStorageSync('user', JSON.stringify(loginres.result
|
||||
.userInfo))
|
||||
store.setUserInfo(loginres.result.userInfo)
|
||||
//获取任务列表角标
|
||||
loadBadge()
|
||||
|
||||
// 跳转首页
|
||||
uni.switchTab({
|
||||
url: '/pages/tab/index'
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
})
|
||||
}
|
||||
|
||||
let localAccountArr = []
|
||||
const accountArr = ref([])
|
||||
onLoad(() => {
|
||||
if (uni.getStorageSync('accountObj')) {
|
||||
let obj = JSON.parse(uni.getStorageSync('accountObj'))
|
||||
username.value = obj.un ? obj.un : ''
|
||||
password.value = obj.pw ? obj.pw : ''
|
||||
}
|
||||
// localAccountArr = uni.getStorageSync('accountArr') ? JSON.parse(uni.getStorageSync('accountArr')) : []
|
||||
// accountArr.value = localAccountArr
|
||||
})
|
||||
|
||||
const loadBadge = () => {
|
||||
taskListApi().then((res) => {
|
||||
if (res.success) {
|
||||
if (res.result.total > 0) {
|
||||
uni.setTabBarBadge({
|
||||
index: '1',
|
||||
text: res.result.total // 角标内容
|
||||
});
|
||||
} else {
|
||||
uni.removeTabBarBadge({ // 移除角标
|
||||
index: '1',
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getDeviceIp() {
|
||||
// #ifdef APP-PLUS
|
||||
|
||||
let deviceIp
|
||||
if (plus.os.name == "Android") {
|
||||
let Context = plus.android.importClass('android.content.Context')
|
||||
let main = plus.android.runtimeMainActivity()
|
||||
let cm = main.getSystemService(Context.CONNECTIVITY_SERVICE)
|
||||
plus.android.importClass(cm)
|
||||
let linkProperties = cm.getLinkProperties(cm.getActiveNetwork())
|
||||
let linkAddrs = plus.android.invoke(linkProperties, 'getLinkAddresses')
|
||||
plus.android.importClass(linkAddrs)
|
||||
for (var i = 0; i < linkAddrs.size(); i++) {
|
||||
let inetAddr = plus.android.invoke(linkAddrs.get(i), 'getAddress')
|
||||
deviceIp = plus.android.invoke(inetAddr, 'getHostAddress')
|
||||
}
|
||||
//再看有没有wifi
|
||||
if (deviceIp == '') {
|
||||
var wifiManager = plus.android.runtimeMainActivity().getSystemService(Context.WIFI_SERVICE);
|
||||
var wifiInfo = plus.android.invoke(wifiManager, "getConnectionInfo");
|
||||
var ipAddress = plus.android.invoke(wifiInfo, "getIpAddress");
|
||||
if (ipAddress != 0) {
|
||||
deviceIp = ((ipAddress & 0xff) + "." + (ipAddress >> 8 & 0xff) + "." + (ipAddress >> 16 &
|
||||
0xff) + "." + (ipAddress >> 24 & 0xff));
|
||||
}
|
||||
}
|
||||
}
|
||||
return deviceIp;
|
||||
// #endif
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.uni-select) {
|
||||
border: none;
|
||||
padding-left: 0;
|
||||
height: 88rpx;
|
||||
}
|
||||
|
||||
:deep(.uni-select__input-placeholder) {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
:deep(.uni-icons) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.logo {
|
||||
padding-top: 184rpx;
|
||||
|
||||
image {
|
||||
width: 475rpx;
|
||||
height: 199rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.form {
|
||||
margin-top: 60rpx;
|
||||
|
||||
.box {
|
||||
width: 570rpx;
|
||||
height: 88rpx;
|
||||
background: #F8F8F8;
|
||||
border-radius: 44rpx;
|
||||
padding: 0 30rpx;
|
||||
margin-top: 40rpx;
|
||||
position: relative;
|
||||
|
||||
.account_box {
|
||||
position: absolute;
|
||||
top: 100rpx;
|
||||
left: 90rpx;
|
||||
width: 500rpx;
|
||||
background-color: #fff;
|
||||
box-shadow: 0px 0px 3px 1px #dfdfdf;
|
||||
z-index: 99;
|
||||
border-radius: 10rpx;
|
||||
|
||||
// &::after {
|
||||
// position: absolute;
|
||||
// content: ' ';
|
||||
// border: 15rpx solid;
|
||||
// border-color: transparent transparent #fff transparent;
|
||||
// top: -30rpx;
|
||||
// left: 30rpx;
|
||||
// z-index: 999;
|
||||
// }
|
||||
|
||||
|
||||
.account {
|
||||
max-height: 200rpx;
|
||||
|
||||
overflow-y: auto;
|
||||
|
||||
view {
|
||||
padding: 10rpx;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
image {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
input {
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pwd {
|
||||
image {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
margin-right: 4rpx;
|
||||
}
|
||||
|
||||
justify-content: flex-end;
|
||||
margin-top: 20rpx;
|
||||
margin-right: 60rpx;
|
||||
font-size: 24rpx;
|
||||
color: #01508B;
|
||||
}
|
||||
|
||||
.login {
|
||||
margin-top: 63rpx;
|
||||
|
||||
view {
|
||||
width: 630rpx;
|
||||
height: 88rpx;
|
||||
background: #4e74fb;
|
||||
border-radius: 44rpx;
|
||||
font-size: 32rpx;
|
||||
color: #FFFFFF;
|
||||
text-align: center;
|
||||
line-height: 88rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
47
pages/safe/detail.vue
Normal file
@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<view :class="['content',{'gray':store.isgray==1}]">
|
||||
<view class="">
|
||||
<video src=""></video>
|
||||
<view class="title">
|
||||
五月天“突然好想你”线上演唱会精彩回放,这里就是标题
|
||||
</view>
|
||||
</view>
|
||||
<view class="listcom">
|
||||
<safeCom></safeCom>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import safeCom from '../../bpm/safeCom.vue';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store'
|
||||
const store = useStore()
|
||||
</script>
|
||||
<style>
|
||||
page{
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
.title{
|
||||
background-color: #fff;
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
line-height: 45rpx;
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
video{
|
||||
width: 750rpx;
|
||||
height: 500rpx;
|
||||
}
|
||||
}
|
||||
.listcom{
|
||||
padding:0 30rpx 30rpx 30rpx;
|
||||
margin-top: 20rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
86
pages/safe/manage.vue
Normal file
@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<view :class="['content',{'gray':store.isgray==1}]">
|
||||
<customNav>
|
||||
<view class="nav_box f-row aic jcb">
|
||||
<view class="back f-row aic" @click="back">
|
||||
<uni-icons type="left" size="20" color="#fff"></uni-icons>
|
||||
</view>
|
||||
<view class="search f-row aic">
|
||||
<input type="text" v-model="searchKey" @confirm="search" @blur="showicon=true&&!searchKey"
|
||||
@focus="showicon=false" />
|
||||
<view class="f-row aic" v-if="showicon">
|
||||
<image src="../../static/search.png" mode=""></image>
|
||||
<text>搜索</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</customNav>
|
||||
<view class="">
|
||||
<safeCom></safeCom>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from 'vue';
|
||||
import safeCom from '../../bpm/safeCom.vue';
|
||||
import customNav from '../../bpm/customNav.vue';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
const store = useStore()
|
||||
const showicon = ref(true)
|
||||
const searchKey = ref('')
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
padding: 0 30rpx 30rpx 30rpx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.nav_box {
|
||||
position: absolute;
|
||||
bottom: 14rpx;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.back {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.search {
|
||||
position: relative;
|
||||
padding-right: 30rpx;
|
||||
flex: 1;
|
||||
|
||||
view {
|
||||
position: absolute;
|
||||
left: 28rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
|
||||
}
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
height: 72rpx;
|
||||
background: #F8F8F8;
|
||||
border-radius: 44rpx;
|
||||
padding: 0 28rpx;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
666
pages/tab/index.vue
Normal file
@ -0,0 +1,666 @@
|
||||
<template>
|
||||
<view :class="['content',{'gray':store.isgray==1}]">
|
||||
<view class="nav">
|
||||
<view class="nav_box f-row aic jcb">
|
||||
<!-- <view class="menu" @click="showDrawer()">
|
||||
<image src="../../static/index/menu.png" mode=""></image>
|
||||
</view> -->
|
||||
<view class="weather_calender f-row aic">
|
||||
<view class="position f-row aic">
|
||||
<image src="../../static/index/position.png" mode=""></image>
|
||||
<text>{{!store.position?'暂未定位':store.position}}</text>
|
||||
</view>
|
||||
<view class="position f-row aic">
|
||||
<image style="height:80rpx;width:80rpx;"
|
||||
:src="`http://openweathermap.org/img/w/${store.wenduIcon}.png`" mode=""></image>
|
||||
<text>{{store.wendu}}℃</text>
|
||||
</view>
|
||||
<uni-datetime-picker type="date">
|
||||
<view class="position f-row aic">
|
||||
<image src="../../static/index/calendar.png" mode=""></image>
|
||||
<text>{{getTime()}}</text>
|
||||
</view>
|
||||
</uni-datetime-picker>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="f-col aic">
|
||||
<swiper class="swiper" autoplay>
|
||||
<swiper-item v-for="item,i in banner" :key="i" class="swiper-item">
|
||||
<image :src="item" mode="aspectFill"></image>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
<view class="wrapper f-col aic">
|
||||
<view class="onduty">
|
||||
<view class="title f-row aic jcb">
|
||||
值班信息
|
||||
<view class="more" @click="jump(`/pages/views/zhongheguanli/zhiban/index`)">
|
||||
查看更多
|
||||
<image src="../../static/index/back.png" mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="info_title f-row aic">
|
||||
<view class="">
|
||||
日期
|
||||
</view>
|
||||
<view class="">
|
||||
带班领导
|
||||
</view>
|
||||
<view class="">
|
||||
值班领导
|
||||
</view>
|
||||
<view class="">
|
||||
值班干部
|
||||
</view>
|
||||
</view>
|
||||
<view class="data_box">
|
||||
<view :class="['data',' f-row', 'aic',{'first':i==0}]" v-for="item,i in zhibanArr">
|
||||
<view class="">
|
||||
{{item.date}}
|
||||
</view>
|
||||
<view class="">
|
||||
{{item.dbld_dictText}}
|
||||
</view>
|
||||
<view class="">
|
||||
{{item.zbld_dictText}}
|
||||
</view>
|
||||
<view class="">
|
||||
{{item.zbgbrealname}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="list_wrapper">
|
||||
<view class="">
|
||||
<view class="list_title f-row aic jca">
|
||||
<view v-for="item,i in tabArr" :class="{'active':current==i}" @click="changeTab(i)">
|
||||
{{item}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="f-row aic zhidu" v-if="current==2">
|
||||
<view :class="{'active':current_zhidu==0}" @click="changeZhidu(0)">
|
||||
厂级制度
|
||||
</view>
|
||||
<view :class="{'active':current_zhidu==1}" @click="changeZhidu(1)">
|
||||
上级制度
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view style="padding-top: 24rpx;" class="more"
|
||||
@click="jump(`/pages/document/index?id=${current}`,current)">
|
||||
查看更多
|
||||
<image src="../../static/index/back.png" mode=""></image>
|
||||
</view>
|
||||
<view class="list_box">
|
||||
<view class="list" v-for="item,i in list" :key="i"
|
||||
@click="jump(`/pages/document/detail?data=${JSON.stringify(item)}&id=${current}`,current,item,'detail')">
|
||||
<view class="topic">
|
||||
{{item._title}}
|
||||
</view>
|
||||
<view class="time_Box f-row aic" v-if="item._time||item._depart">
|
||||
<view class="time" v-if="item._time">
|
||||
{{item._time}}
|
||||
</view>
|
||||
<view class="look f-row aic" v-if="item._depart">
|
||||
{{item._depart}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <uni-drawer ref="showLeft" mode="left" :width="156">
|
||||
<view class="menu_list">
|
||||
<view class="f-row aic jcb" v-for="item,i in menu" :key="i" @click="totask(item.path)">
|
||||
<text>{{item.text}}</text>
|
||||
<uni-icons type="right" size="20" color="#333333"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</uni-drawer> -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from 'vue';
|
||||
import {
|
||||
onLoad,
|
||||
onPullDownRefresh,
|
||||
// onReachBottom
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
gongwenlistApi,
|
||||
gonggaolistApi,
|
||||
zhibanApi,
|
||||
faguiApi,
|
||||
cjzhiduApi,
|
||||
zhiduApi,
|
||||
cxcDapingApi
|
||||
} from '@/api/api.js';
|
||||
import {
|
||||
getUserPermissionApi
|
||||
} from '@/api/login.js';
|
||||
import customNav from '../../bpm/customNav.vue';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
import {
|
||||
beforeJump,
|
||||
getTime,
|
||||
opendocument,
|
||||
preview
|
||||
} from '@/utils/index.js';
|
||||
const baseurl = import.meta.env.VITE_REQUEST_BASE_URL + '/jeecg-boot'
|
||||
|
||||
const store = useStore();
|
||||
onLoad(() => {
|
||||
// list.value = []
|
||||
// if (!uni.getStorageSync('token')) {
|
||||
// return uni.navigateTo({
|
||||
// url: '/pages/login/login'
|
||||
// })
|
||||
// }
|
||||
cxcDaping()
|
||||
zhiban()
|
||||
// bpmlist()
|
||||
// gonggaolist()
|
||||
// zhidu()
|
||||
// fagui()
|
||||
getlist()
|
||||
})
|
||||
|
||||
|
||||
const banner = ref([])
|
||||
/**轮播图*/
|
||||
const cxcDaping = () => {
|
||||
cxcDapingApi({
|
||||
zslb: 6
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
let arr = res.result.records[0].wenjian.split(',')
|
||||
banner.value = arr.map((item) => {
|
||||
return baseurl + '/sys/common/static/' + item
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**公文公告制度法规切换index*/
|
||||
const current = ref(0)
|
||||
/**厂级制度上级制度index 默认厂级*/
|
||||
const current_zhidu = ref(0)
|
||||
/**公文公告制度法规*/
|
||||
const tabArr = ['公文', '公告', '制度', '法规']
|
||||
/**公文公告制度法规切换*/
|
||||
const changeTab = (i) => {
|
||||
current.value = i
|
||||
pageNo = 1
|
||||
loading = false
|
||||
list.value = []
|
||||
getlist()
|
||||
}
|
||||
/**厂级制度上级制度切换*/
|
||||
const changeZhidu = (i) => {
|
||||
current_zhidu.value = i
|
||||
pageNo = 1
|
||||
loading = false
|
||||
list.value = []
|
||||
zhidu()
|
||||
}
|
||||
const res = wx.getSystemInfoSync();
|
||||
const statusHeight = res.statusBarHeight; //状态栏高度
|
||||
const cusnavbarheight = (statusHeight + 44) + "px";
|
||||
const showLeft = ref(null)
|
||||
const showDrawer = (e) => {
|
||||
showLeft.value.open()
|
||||
}
|
||||
// 关闭窗口
|
||||
const closeDrawer = (e) => {
|
||||
showLeft.value.close()
|
||||
}
|
||||
|
||||
const totask = (url) => {
|
||||
closeDrawer()
|
||||
jump(url)
|
||||
}
|
||||
const jump = (url, type, item, page) => {
|
||||
// 公告不可进入详情
|
||||
if (type && type == 1 && page == 'detail') return
|
||||
// 法规点击直接打开附件
|
||||
if (type && type == 3 && item) {
|
||||
return opendocument(item.mingcheng)
|
||||
}
|
||||
// 制度查看更多 判断是厂级还是上级
|
||||
if (type && type == 2) {
|
||||
url = url + `&zhiduid=${current_zhidu.value}`
|
||||
}
|
||||
beforeJump(url, () => {
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// const menu = ref([{
|
||||
// text: '我的任务',
|
||||
// path: '/pages/task/index?id=0'
|
||||
// },{
|
||||
// text: '历史任务',
|
||||
// path: '/pages/task/index?id=2'
|
||||
// }])
|
||||
let pageNo = 1
|
||||
let pageSize = 5
|
||||
let loading = false
|
||||
const list = ref([])
|
||||
/**公文接口*/
|
||||
const bpmlist = () => {
|
||||
loading = true
|
||||
gongwenlistApi({
|
||||
pageNo,
|
||||
pageSize
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
list.value = [...list.value, ...formatObj(res.result.records, 'fwbt', 'fwtime', null)]
|
||||
}
|
||||
loading = false
|
||||
}).catch((err) => {
|
||||
console.log('err', err);
|
||||
})
|
||||
}
|
||||
/**公告接口*/
|
||||
const gonggaolist = () => {
|
||||
loading = true
|
||||
gonggaolistApi({
|
||||
pageNo,
|
||||
pageSize
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
console.log('--',res.result.records)
|
||||
list.value = [...list.value, ...formatObj(res.result.records, 'neirong', 'fbdw', 'createTime')]
|
||||
}
|
||||
loading = false
|
||||
}).catch((err) => {
|
||||
console.log('err', err);
|
||||
})
|
||||
}
|
||||
const zhibanArr = ref([])
|
||||
/**值班接口*/
|
||||
const zhiban = () => {
|
||||
zhibanApi().then((res) => {
|
||||
if (res.success) {
|
||||
zhibanArr.value = res.result.records.slice(0, 2)
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log('err', err);
|
||||
})
|
||||
}
|
||||
/**法规接口*/
|
||||
const fagui = () => {
|
||||
loading = true
|
||||
faguiApi({
|
||||
pageNo,
|
||||
pageSize
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
list.value = [...list.value, ...formatObj(res.result.records, 'flfgmc', 'ssbm', null)]
|
||||
}
|
||||
loading = false
|
||||
}).catch((err) => {
|
||||
console.log('err', err);
|
||||
})
|
||||
}
|
||||
/**制度接口*/
|
||||
const zhidu = () => {
|
||||
loading = true
|
||||
let getzhidu = current_zhidu.value == 0 ? zhiduApi : cjzhiduApi
|
||||
getzhidu({
|
||||
pageNo,
|
||||
pageSize
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
let str = current_zhidu.value == 0 ? 'zbbm_dictText' : 'sbbm'
|
||||
list.value = [...list.value, ...formatObj(res.result.records, 'zdmc', str, null)]
|
||||
}
|
||||
loading = false
|
||||
}).catch((err) => {
|
||||
console.log('err', err);
|
||||
})
|
||||
}
|
||||
const formatObj = (arr, title, time, depart) => {
|
||||
arr.map((item) => {
|
||||
item['_title'] = item[title]
|
||||
item['_time'] = item[time]
|
||||
item['_depart'] = item[depart]
|
||||
})
|
||||
return arr
|
||||
}
|
||||
onPullDownRefresh(() => {
|
||||
loading = false
|
||||
list.value = []
|
||||
cxcDaping()
|
||||
zhiban()
|
||||
getlist()
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
|
||||
const getlist = () => {
|
||||
if (current.value == 0) {
|
||||
bpmlist()
|
||||
} else if (current.value == 1) {
|
||||
gonggaolist()
|
||||
} else if (current.value == 2) {
|
||||
zhidu()
|
||||
} else if (current.value == 3) {
|
||||
fagui()
|
||||
}
|
||||
}
|
||||
// onReachBottom(() => {
|
||||
// if (loading) return
|
||||
// pageNo++
|
||||
// getlist()
|
||||
// })
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
padding-top: v-bind(cusnavbarheight);
|
||||
}
|
||||
|
||||
::v-deep .uni-drawer {
|
||||
margin-top: v-bind(cusnavbarheight);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// .menu_list {
|
||||
// padding: 0 30rpx;
|
||||
// font-size: 28rpx;
|
||||
// color: #333333;
|
||||
|
||||
// view {
|
||||
// height: 110rpx;
|
||||
// border-bottom: 1px solid #EFEFEF;
|
||||
// }
|
||||
|
||||
// image {
|
||||
// width: 13rpx;
|
||||
// height: 23rpx;
|
||||
// }
|
||||
// }
|
||||
|
||||
.nav {
|
||||
width: calc(100% - 60rpx);
|
||||
padding: 0 30rpx;
|
||||
height: v-bind(cusnavbarheight);
|
||||
|
||||
font-size: 24rpx;
|
||||
color: #333333;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 99;
|
||||
background-image: url('../../static/my/navbg.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 750rpx 458rpx;
|
||||
}
|
||||
|
||||
.nav_box {
|
||||
position: absolute;
|
||||
bottom: 26rpx;
|
||||
width: calc(100% - 60rpx);
|
||||
}
|
||||
|
||||
// .menu {
|
||||
// image {
|
||||
// width: 36rpx;
|
||||
// height: 46rpx;
|
||||
// }
|
||||
// }
|
||||
|
||||
.weather_calender {
|
||||
image {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.position:not(:last-child) {
|
||||
position: relative;
|
||||
margin-right: 60rpx;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
content: ' ';
|
||||
width: 2rpx;
|
||||
height: 20rpx;
|
||||
background: #EFEFEF;
|
||||
right: -30rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.swiper {
|
||||
width: 100vw;
|
||||
height: 400rpx;
|
||||
|
||||
.swiper-item {
|
||||
image {
|
||||
width: 100vw;
|
||||
height: 400rpx;
|
||||
background-color: #a8a8a8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
padding: 0 30rpx;
|
||||
transform: translateY(-50rpx);
|
||||
|
||||
.onduty {
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
padding: 20rpx 24rpx 24rpx 24rpx;
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
background-size: 44rpx 12rpx;
|
||||
background-repeat: no-repeat;
|
||||
background-position: left bottom;
|
||||
}
|
||||
|
||||
.info {
|
||||
background: #F8F8F8;
|
||||
border-radius: 8rpx;
|
||||
text-align: center;
|
||||
width: 642rpx;
|
||||
margin-top: 23rpx;
|
||||
|
||||
.info_title {
|
||||
font-size: 24rpx;
|
||||
color: #333333;
|
||||
padding: 24rpx 0;
|
||||
border-bottom: 1px solid #EFEFEF;
|
||||
|
||||
view {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.data_box {
|
||||
font-size: 24rpx;
|
||||
padding-bottom: 24rpx;
|
||||
color: #888888;
|
||||
|
||||
.first {
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.data {
|
||||
margin-top: 23rpx;
|
||||
|
||||
view {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.more {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
text-align: right;
|
||||
|
||||
image {
|
||||
width: 10rpx;
|
||||
height: 18rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.list_wrapper {
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
padding: 26rpx 24rpx 24rpx 24rpx;
|
||||
position: relative;
|
||||
margin-top: 30rpx;
|
||||
width: 642rpx;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
top: 100rpx;
|
||||
left: 0;
|
||||
content: ' ';
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background-color: #EFEFEF;
|
||||
}
|
||||
|
||||
.zhidu {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
justify-content: flex-end;
|
||||
padding-top: 40rpx;
|
||||
|
||||
view {
|
||||
width: 120rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
text-align: center;
|
||||
|
||||
&:first-child {
|
||||
margin-right: 40rpx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.active {
|
||||
position: relative;
|
||||
color: #3179d6;
|
||||
|
||||
&::after {
|
||||
content: ' ';
|
||||
width: 120rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 60rpx;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
position: absolute;
|
||||
background-color: rgba(49, 121, 214, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list_title {
|
||||
|
||||
text-align: center;
|
||||
padding-bottom: 29rpx;
|
||||
font-size: 32rpx;
|
||||
color: #666666;
|
||||
|
||||
.active {
|
||||
position: relative;
|
||||
color: #3179d6;
|
||||
|
||||
&::after {
|
||||
content: ' ';
|
||||
width: 120rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 70rpx;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
position: absolute;
|
||||
background-color: rgba(49, 121, 214, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.list_box {
|
||||
margin-top: 24rpx;
|
||||
|
||||
.list {
|
||||
margin-bottom: 24rpx;
|
||||
padding: 30rpx 30rpx 35rpx 30rpx;
|
||||
// width: 570rpx;
|
||||
background: #F8F8F8;
|
||||
border-radius: 8rpx;
|
||||
|
||||
.topic {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.time_Box {
|
||||
font-size: 24rpx;
|
||||
color: #888888;
|
||||
margin-top: 20rpx;
|
||||
|
||||
.time {
|
||||
margin-right: 62rpx;
|
||||
}
|
||||
|
||||
.look {
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
left: -30rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
content: ' ';
|
||||
width: 2rpx;
|
||||
height: 20rpx;
|
||||
background: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
image {
|
||||
width: 28rpx;
|
||||
height: 22rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
339
pages/tab/my.vue
Normal file
@ -0,0 +1,339 @@
|
||||
<template>
|
||||
<view :class="{'gray':store.isgray==1}">
|
||||
<view class="nav">
|
||||
<view class="user f-row aic">
|
||||
<view class="avatar">
|
||||
<image @click="toProfile('/pages/useredit/useredit')" :src="imgUrl(store.userinfo.avatar)" mode="">
|
||||
</image>
|
||||
</view>
|
||||
<view class="f-row aic jcb right">
|
||||
<view class="name_job " @click="toProfile('/pages/useredit/useredit')">
|
||||
<view class="f-row aic">
|
||||
<view class="name">
|
||||
{{store.userinfo.realname}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="job">
|
||||
{{store.role}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="shezhi">
|
||||
<image @click="scan" style="width: 50rpx;height: 50rpx;margin-right: 20rpx;"
|
||||
src="../../static/tab/scan.png"></image>
|
||||
<!-- <image src="../../static/my/shezhi.png" mode="" @click="toProfile('/pages/useredit/useredit')">
|
||||
</image> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="f-col aic">
|
||||
<view class="msg f-row aic jca">
|
||||
<!-- <view class="box f-col aic" @click="jump('/pages/task/todotask')">
|
||||
<view class="num">
|
||||
{{todoNum}}
|
||||
</view>
|
||||
<text>个人办公</text>
|
||||
</view> -->
|
||||
<view class="box f-col aic">
|
||||
<view class="num">
|
||||
{{0}}
|
||||
</view>
|
||||
<text>步数</text>
|
||||
</view>
|
||||
<view class="box f-col aic" @click="jump('/pages/useredit/addressbook')">
|
||||
<view class="num">
|
||||
0
|
||||
</view>
|
||||
<text>通讯录</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="operate">
|
||||
<view class="f-row aic jcb item" v-for="item,i in arr" :key="i" @click="jump(item.path)">
|
||||
<view class="left f-row aic">
|
||||
<image :src="item.img" mode=""></image>
|
||||
<text>{{item.text}}</text>
|
||||
</view>
|
||||
<view class="right f-row aic">
|
||||
<!-- <view class="" v-show="i==0">
|
||||
<uni-icons type="right" color="#2C2C2C"></uni-icons>
|
||||
</view> -->
|
||||
<view class="switch" v-show="i==0" @click="messageSwitch=!messageSwitch">
|
||||
<image v-show="messageSwitch" src="../../static/my/open.png" mode=""></image>
|
||||
<image v-show="!messageSwitch" src="../../static/my/close.png" mode=""></image>
|
||||
</view>
|
||||
<view class="switch" v-show="i==2" @click="position">
|
||||
<image v-show="positionSwitch" src="../../static/my/open.png" mode=""></image>
|
||||
<image v-show="!positionSwitch" src="../../static/my/close.png" mode=""></image>
|
||||
</view>
|
||||
<view class="version" v-show="i==3">
|
||||
当前版本v{{currentVersion}}
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn" @click="loginout">
|
||||
退出登录
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from 'vue';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
import {
|
||||
queryRoleApi
|
||||
} from '@/api/login.js';
|
||||
import {
|
||||
onLoad,
|
||||
onShow
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
beforeJump,
|
||||
getLocation,
|
||||
toast,
|
||||
getWeather
|
||||
} from '@/utils/index.js';
|
||||
import {
|
||||
imgUrl
|
||||
} from '@/utils/index.js';
|
||||
|
||||
const store = useStore();
|
||||
// h5没法访问plus 这里进行处理 by 闵
|
||||
// #ifdef APP_PLUS
|
||||
const currentVersion = ref(plus.runtime.version)
|
||||
// #endif
|
||||
const arr = ref([
|
||||
// {
|
||||
// img: '../../static/my/biao.png',
|
||||
// text: '值班表查询',
|
||||
// path: '/pages/zhiban/index'
|
||||
// },
|
||||
// {
|
||||
// img: '../../static/my/xiaoxi.png',
|
||||
// text: '接受消息推送',
|
||||
// path: ''
|
||||
// }
|
||||
// , {
|
||||
// img: '../../static/my/dingwei.png',
|
||||
// text: '开启定位',
|
||||
// path: ''
|
||||
// }, {
|
||||
// img: '../../static/my/shengji.png',
|
||||
// text: '软件升级',
|
||||
// path: ''
|
||||
// },
|
||||
])
|
||||
const messageSwitch = ref(false)
|
||||
const positionSwitch = ref(store.positionSwitch)
|
||||
const jump = (url) => {
|
||||
if (!url) return
|
||||
beforeJump(url, () => {
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
})
|
||||
}
|
||||
/**跳转个人资料*/
|
||||
const toProfile = (url) => {
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
}
|
||||
/**定位*/
|
||||
const position = () => {
|
||||
positionSwitch.value = !positionSwitch.value
|
||||
uni.setStorageSync('positionSwitch', positionSwitch.value)
|
||||
store.setPositionSwitch(positionSwitch.value)
|
||||
if (!positionSwitch.value) {
|
||||
toast('定位已关闭')
|
||||
}
|
||||
getLocation()
|
||||
}
|
||||
/**扫码*/
|
||||
const scan = () => {
|
||||
uni.scanCode({
|
||||
success: function(res) {
|
||||
plus.runtime.openWeb(res.result)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const loginout = () => {
|
||||
uni.showModal({
|
||||
title: '退出登录',
|
||||
content: '您确认要退出登录吗?',
|
||||
success(res) {
|
||||
if (res.confirm) {
|
||||
uni.removeStorageSync('token')
|
||||
uni.removeStorageSync('user')
|
||||
uni.removeStorageSync('role')
|
||||
uni.removeStorageSync('logintime')
|
||||
uni.reLaunch({
|
||||
url: '/pages/login/login'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// onShow(() => {
|
||||
// taskList()
|
||||
// })
|
||||
// const todoNum = ref(0)
|
||||
// const taskList = () => {
|
||||
// taskListApi({
|
||||
// pageNo: 1,
|
||||
// pageSize: 4,
|
||||
// _t: new Date().getTime()
|
||||
// }).then((res) => {
|
||||
// if (res.success) {
|
||||
// todoNum.value = res.result.total
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.btn {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
color: #DB4B31;
|
||||
}
|
||||
|
||||
.operate {
|
||||
padding: 0 30rpx;
|
||||
transform: translateY(-10rpx);
|
||||
|
||||
|
||||
.item {
|
||||
height: 104rpx;
|
||||
border-bottom: 1px solid #EFEFEF;
|
||||
|
||||
.version {
|
||||
font-size: 24rpx;
|
||||
color: #888888;
|
||||
}
|
||||
}
|
||||
|
||||
.switch {
|
||||
image {
|
||||
width: 68rpx;
|
||||
height: 38rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.left {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
|
||||
image {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.msg {
|
||||
width: 690rpx;
|
||||
height: 142rpx;
|
||||
background-image: url('../../static/my/bg1.png');
|
||||
background-size: 690rpx 142rpx;
|
||||
margin-top: 30rpx;
|
||||
|
||||
.box {
|
||||
justify-content: center;
|
||||
width: 33.33%;
|
||||
|
||||
.num {
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 24rpx;
|
||||
color: #888888;
|
||||
}
|
||||
}
|
||||
|
||||
.box:not(:last-child) {
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: ' ';
|
||||
width: 1rpx;
|
||||
height: 32rpx;
|
||||
background: #D8D8D8;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav {
|
||||
height: 458rpx;
|
||||
background-image: url('../../static/my/navbg.png');
|
||||
background-size: 750rpx 458rpx;
|
||||
|
||||
.user {
|
||||
padding: 128rpx 30rpx 0 30rpx;
|
||||
|
||||
.right {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
margin-right: 24rpx;
|
||||
|
||||
image {
|
||||
width: 110rpx;
|
||||
height: 110rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.name_job {
|
||||
.name {
|
||||
font-size: 36rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.status {
|
||||
padding: 4rpx 12rpx;
|
||||
background: #55B800;
|
||||
border-radius: 8rpx;
|
||||
font-size: 20rpx;
|
||||
color: #FFFFFF;
|
||||
display: inline-block;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.job {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
margin-top: 6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.shezhi {
|
||||
image {
|
||||
width: 42rpx;
|
||||
height: 42rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
197
pages/tab/office.vue
Normal file
@ -0,0 +1,197 @@
|
||||
<template>
|
||||
<view :class="{'gray':store.isgray==1}">
|
||||
<view class="nav"></view>
|
||||
<view class="placeholder"></view>
|
||||
<!-- <view class="drag" v-if="listorder?.length"> //20240929 yzq 注释 这部分是拖拽组件
|
||||
<view class="title">
|
||||
{{ listtitle}}
|
||||
</view>
|
||||
<l-drag :list="listorder" @change="change" :column="4" gridHeight="100px">
|
||||
<template #grid="{active, content}">
|
||||
<view class="inner f-col aic" :class="{'active': active}" @click="jump(content.path)">
|
||||
<view class="img f-row aic">
|
||||
<image :src="`../../static/office/${content.meta.icon}.png`" mode=""></image>
|
||||
</view>
|
||||
<view class="text">
|
||||
{{content?.meta.title}}
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</l-drag>
|
||||
</view> -->
|
||||
<view class="title f-col aic" style="padding-top: 30rpx;" v-if="!listorder?.length&&!arr?.length">
|
||||
暂无权限,请联系管理员!
|
||||
</view>
|
||||
|
||||
<view class="content">
|
||||
<view class="list" v-if="arr?.length">
|
||||
<view class="item" v-for="item,i in arr" :key="i">
|
||||
<view class="title">
|
||||
{{item.meta.title}}
|
||||
</view>
|
||||
<view class="info_box f-row aic">
|
||||
<view class="info f-col aic" @click="jump(e.path)" v-for="e,i in item.children" :key="i">
|
||||
<view class="img f-row aic">
|
||||
<image :src="`../../static/office/${e.meta.icon}.png`"></image>
|
||||
</view>
|
||||
<view class="text">
|
||||
{{e.meta.title}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from 'vue';
|
||||
import {
|
||||
beforeJump
|
||||
} from '@/utils/index.js';
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
getUserPermissionApi
|
||||
} from '@/api/login.js';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
const store = useStore();
|
||||
|
||||
const list = new Array(7).fill(0).map((v, i) => i);
|
||||
// 拖拽后新的数据
|
||||
const newList = ref([])
|
||||
const change = v => newList.value = v
|
||||
|
||||
const res = wx.getSystemInfoSync();
|
||||
const statusHeight = res.statusBarHeight; //状态栏高度
|
||||
const cusnavbarheight = (statusHeight + 44) + "px";
|
||||
const jump = (url) => {
|
||||
beforeJump(url, () => {
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
})
|
||||
}
|
||||
onLoad(() => {
|
||||
getUserPermission()
|
||||
})
|
||||
const arr = ref([])
|
||||
const listorder = ref([]) //拖动排序传递数据
|
||||
const listtitle = ref([]) //拖动排序的title
|
||||
const getUserPermission = () => {
|
||||
getUserPermissionApi({
|
||||
token: store.token,
|
||||
type: 'mobile'
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
let data = res.result.menu
|
||||
data.map(item => item.children = item?.children.filter(e => e?.meta?.icon))
|
||||
data = data.filter(item => item?.children?.length)
|
||||
listtitle.value = data[0]?.meta?.title
|
||||
// arr.value = data.slice(1, data?.length)
|
||||
arr.value = data;
|
||||
listorder.value = data.slice(0, 1)[0]?.children
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.drag {
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
margin: 24rpx 30rpx 0 30rpx;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
padding: 30rpx 0 0 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.inner {
|
||||
image {
|
||||
width: 98rpx;
|
||||
height: 98rpx;
|
||||
background-color: #efefef;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
height: v-bind(cusnavbarheight);
|
||||
}
|
||||
|
||||
.nav {
|
||||
width: calc(100% - 60rpx);
|
||||
padding: 0 30rpx;
|
||||
height: v-bind(cusnavbarheight);
|
||||
|
||||
font-size: 24rpx;
|
||||
color: #FFFFFF;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 99;
|
||||
background-image: url('../../static/my/navbg.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 750rpx 458rpx;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0 30rpx 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.list {
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
.item {
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx 0;
|
||||
margin-top: 24rpx;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
padding-left: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
image {
|
||||
width: 98rpx;
|
||||
height: 98rpx;
|
||||
}
|
||||
|
||||
.info_box {
|
||||
flex-wrap: wrap;
|
||||
|
||||
.info {
|
||||
margin-top: 40rpx;
|
||||
width: 25%;
|
||||
|
||||
.text {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
32
pages/tab/product.vue
Normal file
@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="nav">生产经营数据</view>
|
||||
<product-data></product-data>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const res = wx.getSystemInfoSync();
|
||||
const statusHeight = res.statusBarHeight; //状态栏高度
|
||||
const cusnavbarheight = statusHeight + 44 + 'px';
|
||||
|
||||
import productData from '@/pages/views/shengchan/index.vue';
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.nav {
|
||||
width: calc(100% - 60rpx);
|
||||
padding: 0 30rpx;
|
||||
height: v-bind(cusnavbarheight);
|
||||
|
||||
font-size: 24rpx;
|
||||
color: #ffffff;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 99;
|
||||
background-image: url('../../static/my/navbg.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 750rpx 458rpx;
|
||||
}
|
||||
</style>
|
||||
120
pages/talk/conversation.vue
Normal file
@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<view :class="['content',{'gray':store.isgray==1}]">
|
||||
<view class="list">
|
||||
<view class="item" v-for="item,i in 14" :key="i">
|
||||
<view class="left f-row aic" v-show="i%2==0">
|
||||
<view class="avatar f-row aic">
|
||||
<image src="../../static/system.png" mode=""></image>
|
||||
</view>
|
||||
|
||||
<view class="content">
|
||||
你今天在干嘛呢?为什么这么久不回我信息,真的生气了
|
||||
</view>
|
||||
</view>
|
||||
<view class="right f-row aic" v-show="i%2!=0">
|
||||
<view class="content">
|
||||
请问如何退款?
|
||||
</view>
|
||||
<view class="avatar f-row aic">
|
||||
<image src="" mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="input_box f-row aic jce">
|
||||
<input type="text" placeholder="请输入内容......" placeholder-style="font-size: 28rpx;color: #999999;" />
|
||||
<view class="send">
|
||||
发送
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
const store = useStore();
|
||||
</script>
|
||||
<style>
|
||||
page {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
padding-bottom: 120rpx;
|
||||
}
|
||||
|
||||
.input_box {
|
||||
position: fixed;
|
||||
width: 750rpx;
|
||||
height: 120rpx;
|
||||
background: #FFFFFF;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
input {
|
||||
width: 467rpx;
|
||||
height: 80rpx;
|
||||
background: #F8F8F8;
|
||||
border-radius: 8rpx;
|
||||
padding: 0 30rpx;
|
||||
|
||||
}
|
||||
|
||||
.send {
|
||||
width: 133rpx;
|
||||
height: 80rpx;
|
||||
background: #01508B;
|
||||
border-radius: 8rpx;
|
||||
text-align: center;
|
||||
line-height: 80rpx;
|
||||
font-size: 28rpx;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.list {
|
||||
padding: 40rpx 30rpx;
|
||||
|
||||
.item:not(:first-child) {
|
||||
margin-top: 60rpx;
|
||||
}
|
||||
|
||||
.item {
|
||||
image {
|
||||
width: 86rpx;
|
||||
height: 86rpx;
|
||||
border-radius: 50%;
|
||||
background-color: maroon;
|
||||
}
|
||||
|
||||
.left {
|
||||
.content {
|
||||
padding: 24rpx 30rpx;
|
||||
background: #FFFFFF;
|
||||
border-radius: 0rpx 16rpx 16rpx 16rpx;
|
||||
margin-left: 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
justify-content: flex-end;
|
||||
|
||||
.content {
|
||||
margin-right: 24rpx;
|
||||
padding: 24rpx 30rpx;
|
||||
background: #01508B;
|
||||
border-radius: 16rpx 0rpx 16rpx 16rpx;
|
||||
font-size: 28rpx;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
105
pages/talk/message_list.vue
Normal file
@ -0,0 +1,105 @@
|
||||
<template>
|
||||
<view :class="{'gray':store.isgray==1}">
|
||||
<view class="list">
|
||||
<view class="item f-row aic">
|
||||
<view class="f-row aic">
|
||||
<image src="../../static/system.png" mode=""></image>
|
||||
</view>
|
||||
<view class="name_info">
|
||||
<view class="name_time f-row aic jcb">
|
||||
<view class="name">
|
||||
系统通知
|
||||
</view>
|
||||
<view class="time">
|
||||
1分钟前
|
||||
</view>
|
||||
</view>
|
||||
<view class="info">
|
||||
关于年假通知关于年假通知关于年假通知关于年假通知关于年假通知关于年假通知关于年假通知
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item f-row aic" v-for="item,i in 5" :key="i" @click="jump('/pages/talk/conversation')">
|
||||
<view class="f-row aic">
|
||||
<image src="" mode=""></image>
|
||||
</view>
|
||||
<view class="name_info">
|
||||
<view class="name_time f-row aic jcb">
|
||||
<view class="name">
|
||||
系统通知
|
||||
</view>
|
||||
<view class="time">
|
||||
1分钟前
|
||||
</view>
|
||||
</view>
|
||||
<view class="info">
|
||||
关于年假通知
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
beforeJump
|
||||
} from '@/utils/index.js';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
const store = useStore();
|
||||
const jump = (url) => {
|
||||
beforeJump(url, () => {
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.list {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.item:not(:last-child) {
|
||||
border-bottom: 1px solid #EFEFEF;
|
||||
}
|
||||
|
||||
.item {
|
||||
height: 150rpx;
|
||||
|
||||
|
||||
.name_info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.info {
|
||||
margin-top: 4rpx;
|
||||
width: 540rpx;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.time,
|
||||
.info {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #f8f8f8;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
60
pages/talk/system.vue
Normal file
@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<view :class="['content',{'gray':store.isgray==1}]">
|
||||
<view class="list">
|
||||
<view class="item" v-for="item,i in 3" :key="i">
|
||||
<view class="left f-row aic">
|
||||
<view class="avatar f-row aic">
|
||||
<image src="../../static/system.png" mode=""></image>
|
||||
</view>
|
||||
<view class="content">
|
||||
你今天在干嘛呢?为什么这么久不回我信息,真的生气了
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
const store = useStore();
|
||||
</script>
|
||||
<style>
|
||||
page {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content{
|
||||
padding-bottom: 120rpx;
|
||||
}
|
||||
.list {
|
||||
padding: 40rpx 30rpx;
|
||||
|
||||
.item:not(:first-child) {
|
||||
margin-top: 60rpx;
|
||||
}
|
||||
|
||||
.item {
|
||||
image {
|
||||
width: 86rpx;
|
||||
height: 86rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.left {
|
||||
.content {
|
||||
padding: 24rpx 30rpx;
|
||||
background: #FFFFFF;
|
||||
border-radius: 0rpx 16rpx 16rpx 16rpx;
|
||||
margin-left: 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
391
pages/task/handle.vue
Normal file
@ -0,0 +1,391 @@
|
||||
<template>
|
||||
<view :class="['content',{'gray':store.isgray==1}]">
|
||||
<customNav>
|
||||
<view class="f-row aic box">
|
||||
<view class="back" @click="back">
|
||||
<uni-icons type="left" size="20" color="#fff"></uni-icons>
|
||||
</view>
|
||||
<view class="avatar">
|
||||
<image :src="imgUrl(store.userinfo.avatar)" mode=""></image>
|
||||
</view>
|
||||
<view class="name">
|
||||
{{taskInfo.processApplyUserName}}的{{taskInfo.processDefinitionName}}
|
||||
</view>
|
||||
<view class="status" v-if="type==0">
|
||||
待审批
|
||||
</view>
|
||||
<view class="status" v-if="type==1" style="background-color: #7AC756;">
|
||||
已处理
|
||||
</view>
|
||||
</view>
|
||||
</customNav>
|
||||
<component :is="comp" :dataId="dataId"></component>
|
||||
<view v-if="ifShow" style="display: block; margin: 10px;">
|
||||
温馨提示:目前APP暂不支持电子签章审批,请登录PC端厂综合管理平台(https://10.75.166.6),在个人办公-我的任务中审批。</view>
|
||||
<view class="btn f-row aic jcb" v-if="type == 0 && !ifShow">
|
||||
<view class="refuse" @click="openpop(1)">
|
||||
拒绝
|
||||
</view>
|
||||
<view class="agree" @click="openpop(2)">
|
||||
同意
|
||||
</view>
|
||||
</view>
|
||||
<uni-popup ref="popup" type="center">
|
||||
<view class="popup">
|
||||
<view class="title">
|
||||
审批意见
|
||||
</view>
|
||||
<view class="f-col aic">
|
||||
<view class="input f-col">
|
||||
<textarea v-model="reason" name="" id="" maxlength="200" placeholder="请输入"></textarea>
|
||||
<view class="">
|
||||
{{reason.length}}/200
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="status==2" class="agree_operate f-row aic" @click="chooseNextPerson=!chooseNextPerson">
|
||||
<image v-if="chooseNextPerson" src="../../static/login/checked.png" mode=""></image>
|
||||
<image v-else src="../../static/login/nocheck.png" mode=""></image>
|
||||
<view class="">
|
||||
指定下一步操作人
|
||||
</view>
|
||||
</view>
|
||||
<view class="" v-else>
|
||||
<picker :value="currentnode" :range="stepNode" range-key="NAME_" @change="nodeChange">
|
||||
<view class="node">{{currentnode!=null?stepNode[currentnode].NAME_:'请选择驳回节点'}}</view>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="popbtn f-row aic">
|
||||
<view class="cancel" @click="closepop">
|
||||
取消
|
||||
</view>
|
||||
<view class="confirm" @click="handleProcess">
|
||||
确定
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
getCurrentInstance
|
||||
} from 'vue';
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
getProcessNodeInfoApi,
|
||||
processCompleteApi,
|
||||
getProcessTaskTransInfoApi,
|
||||
getHisProcessNodeInfoApi,
|
||||
} from '@/api/api.js';
|
||||
import {
|
||||
beforeJump
|
||||
} from '@/utils/index.js';
|
||||
import customNav from '../../bpm/customNav.vue';
|
||||
import {
|
||||
imgUrl
|
||||
} from '@/utils/index.js';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
const store = useStore()
|
||||
const {
|
||||
proxy
|
||||
} = getCurrentInstance()
|
||||
const popup = ref(null)
|
||||
const reason = ref('')
|
||||
/**拒绝(1)||同意(2)*/
|
||||
const status = ref(null)
|
||||
const openpop = (val) => {
|
||||
status.value = val
|
||||
popup.value.open()
|
||||
reason.value = val == 2 ? '同意' : ''
|
||||
}
|
||||
const closepop = () => {
|
||||
popup.value.close()
|
||||
}
|
||||
const comp = ref(null)
|
||||
const dataId = ref('')
|
||||
const ifShow = ref(false) //20250122 判断是否是签章业务 提示文字
|
||||
const getProcessNodeInfo = (taskId) => {
|
||||
getProcessNodeInfoApi({
|
||||
taskId
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
dataId.value = res.result.dataId
|
||||
comp.value = res.result.formUrlMobile
|
||||
}
|
||||
})
|
||||
}
|
||||
const back = () => {
|
||||
uni.navigateBack()
|
||||
}
|
||||
/**是否指定下一步操作人*/
|
||||
const chooseNextPerson = ref(false)
|
||||
let nextnode = null
|
||||
/**流程办理判断*/
|
||||
const handleProcess = () => {
|
||||
// if (!reason.value.trim()) return proxy.$toast('请输入审批意见')
|
||||
let params = {}
|
||||
if (status.value == 1) { // 拒绝
|
||||
if (currentnode.value == null) return proxy.$toast('请选择驳回节点')
|
||||
params.processModel = 3
|
||||
params.rejectModelNode = stepNode.value[currentnode.value].TASK_DEF_KEY_
|
||||
processComplete(params)
|
||||
} else { // 同意
|
||||
if (chooseNextPerson.value) { //去选下一步操作人
|
||||
beforeJump('/pages/userlist/index', () => {
|
||||
closepop()
|
||||
uni.navigateTo({
|
||||
url: `/pages/userlist/index?id=${taskInfo.value.id}&isradio=1&nextnode=${JSON.stringify(nextnode)}&reason=${reason.value}`
|
||||
})
|
||||
})
|
||||
} else {
|
||||
params.processModel = 1
|
||||
processComplete(params)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**流程办理接口*/
|
||||
const processComplete = (params) => {
|
||||
processCompleteApi({
|
||||
taskId: taskInfo.value.id,
|
||||
reason: reason.value,
|
||||
...params
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
proxy.$toast(res.message)
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 2000)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**审批流程节点*/
|
||||
const stepNode = ref([])
|
||||
/**当前选择的节点*/
|
||||
const currentnode = ref(null)
|
||||
/**切换节点*/
|
||||
const nodeChange = (e) => {
|
||||
currentnode.value = e.detail.value
|
||||
}
|
||||
|
||||
const getProcessTaskTransInfo = (e) => {
|
||||
getProcessTaskTransInfoApi({
|
||||
taskId: taskInfo.value.id
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
stepNode.value = res.result.histListNode
|
||||
nextnode = res.result.transitionList
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**历史任务详情*/
|
||||
const getHisProcessNodeInfo = (procInstId) => {
|
||||
getHisProcessNodeInfoApi({
|
||||
procInstId
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
dataId.value = res.result.dataId
|
||||
comp.value = res.result.formUrlMobile
|
||||
}
|
||||
})
|
||||
}
|
||||
/**判断是否是电子签章节点任务,是则显示温馨提示并隐藏审批按钮*/
|
||||
const getIfShow = () => {
|
||||
if (taskInfo.value.taskId == 'task1705482211321' || taskInfo.value.taskId == 'task1705482639673' ||
|
||||
taskInfo.value.taskId == 'task1714092890849' || taskInfo.value.taskId == 'task1714092955682' ||
|
||||
taskInfo.value.taskId == 'task1689151174324' || taskInfo.value.taskId == 'task1677809773570' ||
|
||||
taskInfo.value.taskId == 'task1689579219152')
|
||||
{ // 签章业务:非常规 承包商资质审查 招标采购 公务接待 房屋租赁
|
||||
ifShow.value = true;
|
||||
} else {
|
||||
ifShow.value = false;
|
||||
}
|
||||
}
|
||||
const taskInfo = ref(null)
|
||||
let type = null
|
||||
onLoad((options) => {
|
||||
taskInfo.value = JSON.parse(options.info)
|
||||
type = options.type
|
||||
if (type == 1 || type == 2) {
|
||||
return getHisProcessNodeInfo(taskInfo.value.processInstanceId)
|
||||
}
|
||||
getProcessNodeInfo(taskInfo.value.id)
|
||||
getProcessTaskTransInfo()
|
||||
|
||||
getIfShow()
|
||||
|
||||
})
|
||||
</script>
|
||||
<style>
|
||||
page {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.popup {
|
||||
width: 690rpx;
|
||||
background: #FFFFFF;
|
||||
border-radius: 8rpx;
|
||||
|
||||
.node {
|
||||
margin: 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.agree_operate {
|
||||
padding: 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
|
||||
image {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
color: #000000;
|
||||
text-align: center;
|
||||
padding: 40rpx 0;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 582rpx;
|
||||
height: 226rpx;
|
||||
background: #F8F8F8;
|
||||
border-radius: 8rpx;
|
||||
padding: 24rpx;
|
||||
|
||||
textarea {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
view {
|
||||
text-align: right;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
.popbtn {
|
||||
font-size: 32rpx;
|
||||
border-top: 1px solid #E5E5E5;
|
||||
margin-top: 40rpx;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
content: ' ';
|
||||
height: 100rpx;
|
||||
width: 1px;
|
||||
background-color: #E5E5E5;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
view {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
height: 100rpx;
|
||||
line-height: 100rpx;
|
||||
}
|
||||
|
||||
.cancel {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.confirm {
|
||||
color: #007FFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
|
||||
// margin-top: 88rpx;
|
||||
padding-bottom: 120rpx;
|
||||
}
|
||||
|
||||
.btn {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 690rpx;
|
||||
height: 120rpx;
|
||||
background: #FFFFFF;
|
||||
padding: 0 30rpx;
|
||||
|
||||
view {
|
||||
|
||||
width: 330rpx;
|
||||
height: 88rpx;
|
||||
font-size: 28rpx;
|
||||
border-radius: 16rpx;
|
||||
text-align: center;
|
||||
line-height: 88rpx;
|
||||
}
|
||||
|
||||
.refuse {
|
||||
box-sizing: border-box;
|
||||
background: #FFFFFF;
|
||||
border: 2rpx solid #01508B;
|
||||
color: #01508B;
|
||||
}
|
||||
|
||||
.agree {
|
||||
background: #01508B;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.box {
|
||||
position: absolute;
|
||||
bottom: 12rpx;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.back {
|
||||
padding-left: 30rpx;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
border-radius: 32rpx;
|
||||
background-color: #fff;
|
||||
margin-right: 16rpx;
|
||||
margin-left: 50rpx;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 28rpx;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.status {
|
||||
padding: 4rpx 8rpx;
|
||||
display: inline-block;
|
||||
background-color: #FE4600;
|
||||
color: #FFFFFF;
|
||||
font-size: 20rpx;
|
||||
margin-left: 8rpx;
|
||||
border-radius: 8rpx;
|
||||
|
||||
}
|
||||
</style>
|
||||
184
pages/task/index.vue
Normal file
@ -0,0 +1,184 @@
|
||||
<template>
|
||||
<view :class="{'gray':store.isgray==1}">
|
||||
<view class="nav">
|
||||
<view class="tab_box f-row aic jca">
|
||||
<view :class="{'active':i==currentIndex}" v-for="item,i in tabArr" :key="i" @click="change(i)">
|
||||
{{item.text}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="tasklist">
|
||||
<tasklistCom @jump="jump" :taskArr="taskArr" :currentIndex="currentIndex"></tasklistCom>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from 'vue';
|
||||
import tasklistCom from '../../bpm/tasklistCom.vue';
|
||||
import { toast } from '@/utils/index.js';
|
||||
import {
|
||||
taskListApi,
|
||||
taskHistoryListApi
|
||||
} from '@/api/api.js';
|
||||
import {
|
||||
onLoad,
|
||||
onShow,
|
||||
onReachBottom,
|
||||
onPullDownRefresh
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
beforeJump
|
||||
} from '@/utils/index.js';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
const store = useStore()
|
||||
let processDefinitionName = ''
|
||||
onLoad((options) => {
|
||||
currentIndex.value = +options.id
|
||||
processDefinitionName = options.title
|
||||
})
|
||||
onShow(() => {
|
||||
taskArr.value = []
|
||||
pageNo = 1
|
||||
pageSize = 10
|
||||
loading = false
|
||||
taskList()
|
||||
})
|
||||
const tabArr = ref([{
|
||||
text: '我的任务',
|
||||
id: 0
|
||||
},
|
||||
{
|
||||
text: '历史任务',
|
||||
id: 1
|
||||
}])
|
||||
const date = ref('')
|
||||
const currentIndex = ref(0)
|
||||
let pageNo = 1
|
||||
let pageSize = 10
|
||||
let loading = false
|
||||
const taskArr = ref([])
|
||||
const taskList = () => {
|
||||
loading = true
|
||||
uni.showLoading({
|
||||
title: '加载中...'
|
||||
})
|
||||
let getlist = currentIndex.value == 0 ? taskListApi : taskHistoryListApi
|
||||
getlist({
|
||||
// createTime: date.value ? date.value + ' 00:00:00' : '',
|
||||
pageNo,
|
||||
pageSize,
|
||||
_t: new Date().getTime(),
|
||||
processDefinitionName
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
if (!res.result.records.length) return toast('没有更多了~')
|
||||
taskArr.value = [...taskArr.value, ...(res?.result?.records || [])]
|
||||
loading = false
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
})
|
||||
}
|
||||
|
||||
const change = (i) => {
|
||||
taskArr.value = []
|
||||
pageNo = 1
|
||||
pageSize = 10
|
||||
loading = false
|
||||
currentIndex.value = i
|
||||
taskList()
|
||||
}
|
||||
const chooseTime = () => {
|
||||
taskArr.value = []
|
||||
taskList()
|
||||
}
|
||||
onReachBottom(() => {
|
||||
if (loading) return
|
||||
pageNo++
|
||||
taskList()
|
||||
})
|
||||
onPullDownRefresh(() => {
|
||||
pageNo = 1
|
||||
pageSize = 10
|
||||
loading = false
|
||||
taskArr.value = []
|
||||
taskList()
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
const jump = (url) => {
|
||||
beforeJump(url, () => {
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
page {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.tasklist {
|
||||
padding-top: 100rpx;
|
||||
}
|
||||
|
||||
.nav {
|
||||
background-color: #fff;
|
||||
// height: 200rpx;
|
||||
height: 100rpx;
|
||||
width: 100vw;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 99;
|
||||
|
||||
.tab_box {
|
||||
padding: 24rpx 0;
|
||||
|
||||
view {
|
||||
position: relative;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.active {
|
||||
font-size: 28rpx;
|
||||
color: #01508B;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
width: 230rpx;
|
||||
height: 2rpx;
|
||||
background: #01508B;
|
||||
content: ' ';
|
||||
bottom: -22rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.time_box {
|
||||
padding: 20rpx 0;
|
||||
|
||||
.time {
|
||||
padding: 0 30rpx;
|
||||
width: 630rpx;
|
||||
height: 72rpx;
|
||||
background: #F8F8F8;
|
||||
border-radius: 8rpx;
|
||||
|
||||
image {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
79
pages/task/self.vue
Normal file
@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<view :class="{'gray':store.isgray==1}">
|
||||
<tasklistCom @jump="jump" :taskArr="taskArr" :currentIndex="2"></tasklistCom>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
beforeJump
|
||||
} from '@/utils/index.js';
|
||||
import tasklistCom from '../../bpm/tasklistCom.vue';
|
||||
import {
|
||||
ref
|
||||
} from 'vue';
|
||||
import {
|
||||
onLoad,
|
||||
onReachBottom
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
import {
|
||||
myApplyProcessListApi
|
||||
} from '@/api/api.js';
|
||||
import { toast } from '@/utils/index.js';
|
||||
const store = useStore()
|
||||
const taskArr = ref([])
|
||||
let processName = ''
|
||||
onLoad((options) => {
|
||||
processName = options.title
|
||||
getmyApply()
|
||||
})
|
||||
let pageNo = 1
|
||||
let pageSize = 10
|
||||
let loading = false
|
||||
const getmyApply = () => {
|
||||
loading = true
|
||||
uni.showLoading({
|
||||
title:'加载中...'
|
||||
})
|
||||
myApplyProcessListApi({
|
||||
pageNo,
|
||||
pageSize,
|
||||
_t: new Date().getTime(),
|
||||
processName
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
if(!res.result.records.length)return toast('没有更多了~')
|
||||
let arr = res.result.records
|
||||
arr.map((item) => {
|
||||
item['processApplyUserName'] = item['startUserName']
|
||||
item['processDefinitionName'] = item['prcocessDefinitionName']
|
||||
item['taskBeginTime'] = item['startTime']
|
||||
})
|
||||
taskArr.value = [...taskArr.value, ...arr]
|
||||
loading = false
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
})
|
||||
|
||||
}
|
||||
const jump = (url) => {
|
||||
beforeJump(url, () => {
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
})
|
||||
}
|
||||
onReachBottom(() => {
|
||||
if (loading) return
|
||||
pageNo++
|
||||
getmyApply()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
264
pages/task/todotask.vue
Normal file
@ -0,0 +1,264 @@
|
||||
<template>
|
||||
<view :class="[{'gray':store.isgray==1}]">
|
||||
<view class="nav"></view>
|
||||
<view class="placeholder"></view>
|
||||
<view class="content">
|
||||
<extendCom title="我的任务" img="process" :list="todoArr" :total="todoTotal" type="0"></extendCom>
|
||||
<extendCom title="历史任务" img="done" :list="doneArr" :total="doneTotal" type="1"></extendCom>
|
||||
<extendCom title="本人发起" img="self" :list="selfArr" :total="selfTotal" type="2"></extendCom>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const res = wx.getSystemInfoSync();
|
||||
const statusHeight = res.statusBarHeight; //状态栏高度
|
||||
const cusnavbarheight = (statusHeight + 44) + "px";
|
||||
import extendCom from '../../bpm/extendCom.vue';
|
||||
import {
|
||||
ref
|
||||
} from 'vue';
|
||||
import {
|
||||
taskListApi,
|
||||
myApplyProcessListApi,
|
||||
taskHistoryListApi
|
||||
} from '@/api/api.js';
|
||||
import {
|
||||
onShow,
|
||||
onReachBottom,
|
||||
onPullDownRefresh
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store'
|
||||
const store = useStore()
|
||||
onShow(() => {
|
||||
initArr()
|
||||
taskList()
|
||||
taskHistoryList()
|
||||
myApplyProcessList()
|
||||
uni.removeTabBarBadge({ // 移除角标
|
||||
index: '1',
|
||||
});
|
||||
})
|
||||
const todoArr = ref([])
|
||||
const todoTotal = ref(0)
|
||||
/**待办事项*/
|
||||
const taskList = () => {
|
||||
taskListApi({
|
||||
pageNo: 1,
|
||||
pageSize: 4,
|
||||
_t: new Date().getTime()
|
||||
}).then((res) => {
|
||||
if (res?.success) {
|
||||
if (res?.result?.total > 4) {
|
||||
taskListApi({
|
||||
pageNo: 1,
|
||||
pageSize: res?.result?.total,
|
||||
_t: new Date().getTime()
|
||||
}).then((res1) => {
|
||||
console.log('---', res1)
|
||||
if (res1?.success) {
|
||||
todoArr.value = [...todoArr.value, ...handleData(res1?.result?.records)]
|
||||
todoTotal.value = res1?.result?.total
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log('err', err);
|
||||
})
|
||||
|
||||
} else {
|
||||
todoArr.value = [...todoArr.value, ...handleData(res?.result?.records)]
|
||||
todoTotal.value = res?.result?.total
|
||||
}
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
})
|
||||
|
||||
}
|
||||
const doneArr = ref([])
|
||||
const doneTotal = ref(0)
|
||||
/**已办事项*/
|
||||
const taskHistoryList = () => {
|
||||
taskHistoryListApi().then((res) => {
|
||||
if (res.success) {
|
||||
if (res.result.total > 4) {
|
||||
taskHistoryListApi({
|
||||
pageNo: 1,
|
||||
pageSize: res.result.total,
|
||||
_t: new Date().getTime()
|
||||
}).then((res1) => {
|
||||
if (res1.success) {
|
||||
doneArr.value = [...doneArr.value, ...handleData(res1.result.records)]
|
||||
doneTotal.value = res1.result.total
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
})
|
||||
|
||||
} else {
|
||||
doneArr.value = [...doneArr.value, ...handleData(res.result.records)]
|
||||
doneTotal.value = res.result.total
|
||||
}
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
})
|
||||
}
|
||||
const selfArr = ref([])
|
||||
const selfTotal = ref(0)
|
||||
/**本人发起*/
|
||||
const myApplyProcessList = () => {
|
||||
myApplyProcessListApi().then((res) => {
|
||||
if (res.success) {
|
||||
if (res.result.total > 4) {
|
||||
myApplyProcessListApi({
|
||||
pageNo: 1,
|
||||
pageSize: res.result.total,
|
||||
_t: new Date().getTime()
|
||||
}).then((res1) => {
|
||||
if (res1.success) {
|
||||
selfArr.value = [...selfArr.value, ...handleData(res1.result.records)]
|
||||
selfTotal.value = res1.result.total
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
})
|
||||
|
||||
} else {
|
||||
|
||||
selfArr.value = [...selfArr.value, ...handleData(res.result.records)]
|
||||
selfTotal.value = res.result.total
|
||||
}
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
})
|
||||
}
|
||||
const handleData = (titlearr) => {
|
||||
let titleArr = titlearr.length ? titlearr.map(item => item.processDefinitionName || item
|
||||
.prcocessDefinitionName) : []
|
||||
let res = titleArr.reduce((obj, title) => {
|
||||
if (title in obj) {
|
||||
obj[title]++
|
||||
} else {
|
||||
obj[title] = 1
|
||||
}
|
||||
return obj
|
||||
}, {})
|
||||
return Object.entries(res).map(([k, v]) => ({
|
||||
title: k,
|
||||
num: v
|
||||
}))
|
||||
}
|
||||
|
||||
const initArr = () => {
|
||||
todoArr.value = []
|
||||
selfArr.value = []
|
||||
doneArr.value = []
|
||||
todoTotal.value = 0
|
||||
doneTotal.value = 0
|
||||
selfTotal.value = 0
|
||||
}
|
||||
|
||||
let loading = false
|
||||
onPullDownRefresh(() => {
|
||||
loading = false
|
||||
initArr()
|
||||
taskList()
|
||||
taskHistoryList()
|
||||
myApplyProcessList()
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.drag {
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
margin: 24rpx 30rpx 0 30rpx;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
padding: 30rpx 0 0 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.inner {
|
||||
image {
|
||||
width: 98rpx;
|
||||
height: 98rpx;
|
||||
background-color: #efefef;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
height: v-bind(cusnavbarheight);
|
||||
}
|
||||
|
||||
.nav {
|
||||
width: calc(100% - 60rpx);
|
||||
padding: 0 30rpx;
|
||||
height: v-bind(cusnavbarheight);
|
||||
|
||||
font-size: 24rpx;
|
||||
color: #FFFFFF;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 99;
|
||||
background-image: url('../../static/my/navbg.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 750rpx 458rpx;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0 30rpx 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.list {
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
.item {
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx 0;
|
||||
margin-top: 24rpx;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
padding-left: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
image {
|
||||
width: 98rpx;
|
||||
height: 98rpx;
|
||||
}
|
||||
|
||||
.info_box {
|
||||
flex-wrap: wrap;
|
||||
|
||||
.info {
|
||||
margin-top: 40rpx;
|
||||
width: 25%;
|
||||
|
||||
.text {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
106
pages/useredit/add_address.vue
Normal file
@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<view :class="['content',{'gray':store.isgray==1}]">
|
||||
<view class="area f-row jcb">
|
||||
<view class="title topic">
|
||||
所在地区
|
||||
</view>
|
||||
<input type="text" placeholder="省、市、区、街道" />
|
||||
</view>
|
||||
<view class="area f-row jcb">
|
||||
<view class="title topic">
|
||||
详细地址
|
||||
</view>
|
||||
<textarea placeholder="小区楼栋/乡村名称"></textarea>
|
||||
</view>
|
||||
<view class="area f-row jcb">
|
||||
<view class="title">
|
||||
设为默认地址
|
||||
</view>
|
||||
<image src="../../static/login/checked.png" mode=""></image>
|
||||
<!-- <image src="../../static/login/nocheck.png" mode=""></image> -->
|
||||
</view>
|
||||
<view class="btn f-col aic">
|
||||
<view class="">
|
||||
保存
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
useStore
|
||||
} from '@/store'
|
||||
const store = useStore()
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page {
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
padding: 30rpx 30rpx 120rpx 30rpx;
|
||||
}
|
||||
|
||||
.area:not(:first-child) {
|
||||
margin-top: 40rpx;
|
||||
}
|
||||
|
||||
.area {
|
||||
|
||||
image {
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
}
|
||||
|
||||
|
||||
.topic {
|
||||
margin-top: 28rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
|
||||
}
|
||||
|
||||
input {
|
||||
width: 472rpx;
|
||||
height: 96rpx;
|
||||
background: #F6F6F6;
|
||||
border-radius: 16rpx;
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 472rpx;
|
||||
height: 104rpx;
|
||||
background: #F6F6F6;
|
||||
border-radius: 16rpx;
|
||||
padding: 28rpx 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 750rpx;
|
||||
height: 120rpx;
|
||||
background: #FFFFFF;
|
||||
justify-content: center;
|
||||
left: 0;
|
||||
|
||||
view {
|
||||
width: 690rpx;
|
||||
height: 88rpx;
|
||||
background: #01508B;
|
||||
border-radius: 8rpx;
|
||||
font-size: 32rpx;
|
||||
color: #FFFFFF;
|
||||
text-align: center;
|
||||
line-height: 88rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
143
pages/useredit/address.vue
Normal file
@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<view :class="['content',{'gray':store.isgray==1}]">
|
||||
<view class="list">
|
||||
<view class="item" v-for="item,i in 2" :key="i">
|
||||
<view class="province f-row aic">
|
||||
<view class="">
|
||||
浙江省,杭州市
|
||||
</view>
|
||||
<image src="../../static/my/default.png" mode=""></image>
|
||||
</view>
|
||||
<view class="address f-row jcb">
|
||||
<view class="">
|
||||
重庆 重庆市 渝北区 龙溪街道花卉园东路黄金
|
||||
宝高级住宅小区
|
||||
</view>
|
||||
<image src="../../static/my/edit.png" mode=""></image>
|
||||
</view>
|
||||
<view class="set f-row aic jcb">
|
||||
<view class="f-row aic">
|
||||
<!-- <image src="../../static/login/checked.png" mode=""></image> -->
|
||||
<image src="../../static/login/nocheck.png" mode=""></image>
|
||||
设为默认地址
|
||||
</view>
|
||||
<view class="">
|
||||
删除
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn f-col aic">
|
||||
<view class="" @click="jump('/pages/useredit/add_address')">
|
||||
+添加收货地址
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
beforeJump
|
||||
} from '@/utils/index.js';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store'
|
||||
const store = useStore()
|
||||
const jump = (url) => {
|
||||
beforeJump(url, () => {
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
padding-bottom: 120rpx;
|
||||
}
|
||||
|
||||
.list {
|
||||
padding: 30rpx;
|
||||
|
||||
.item:not(:first-child) {
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
|
||||
.item {
|
||||
|
||||
padding: 30rpx;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
|
||||
.province {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
margin-bottom: 10rpx;
|
||||
|
||||
image {
|
||||
width: 56rpx;
|
||||
height: 36rpx;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.address {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
padding-bottom: 30rpx;
|
||||
border-bottom: 1px solid #EFEFEF;
|
||||
|
||||
view {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 28rpx;
|
||||
height: 30rpx;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.set {
|
||||
margin-top: 30rpx;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
|
||||
image {
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 750rpx;
|
||||
height: 120rpx;
|
||||
background: #FFFFFF;
|
||||
justify-content: center;
|
||||
|
||||
view {
|
||||
width: 690rpx;
|
||||
height: 88rpx;
|
||||
background: #01508B;
|
||||
border-radius: 8rpx;
|
||||
font-size: 32rpx;
|
||||
color: #FFFFFF;
|
||||
text-align: center;
|
||||
line-height: 88rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
65
pages/useredit/addressbook.vue
Normal file
@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<view :class="{'gray':store.isgray==1}">
|
||||
<view class="list">
|
||||
<view class="item f-row aic jcb" v-for="item,i in 4" :key="i">
|
||||
<view class="user f-row aic">
|
||||
<image src="" mode=""></image>
|
||||
<view class="name_job">
|
||||
<view class="name">
|
||||
我是晴天
|
||||
</view>
|
||||
<view class="job">
|
||||
销售部-销售总监
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn">
|
||||
电话联系
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
useStore
|
||||
} from '@/store'
|
||||
const store = useStore()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.list{
|
||||
padding: 0 30rpx;
|
||||
.item{
|
||||
padding: 30rpx 0;
|
||||
border-bottom: 1px solid #EFEFEF;
|
||||
image{
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50rpx;
|
||||
background-color: #EFEFEF;
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
.name{
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
}
|
||||
.job{
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
.btn{
|
||||
width: 132rpx;
|
||||
height: 60rpx;
|
||||
background: #01508B;
|
||||
border-radius: 8rpx;
|
||||
text-align: center;
|
||||
line-height: 60rpx;
|
||||
font-size: 24rpx;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
182
pages/useredit/useredit.vue
Normal file
@ -0,0 +1,182 @@
|
||||
<template>
|
||||
<view :class="['content',{'gray':store.isgray==1}]">
|
||||
<view class="box">
|
||||
<view>头像</view>
|
||||
<view style="display: flex;align-items: center;">
|
||||
<button class="head-btn" @click="chooseAvatar">
|
||||
<image class="head-img" v-if="!form.avatar" :src="imgUrl(store.userinfo.avatar)" mode="">
|
||||
</image>
|
||||
<image class="head-img" v-else :src="imgUrl(form.avatar)"></image>
|
||||
</button>
|
||||
<uni-icons type="right" size="24"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="box" style="padding-top: 30rpx;padding-bottom: 30rpx;">
|
||||
<view>姓名</view>
|
||||
<input disabled style="text-align: right;" type="nickname"
|
||||
placeholder-style="font-size: 32rpx;color: #999999;" v-model="store.userinfo.realname"
|
||||
placeholder="请输入姓名" />
|
||||
</view>
|
||||
<view class="box" style="padding-top: 30rpx;padding-bottom: 30rpx;">
|
||||
<view>手机号</view>
|
||||
<input style="text-align: right;" type="nickname" v-model="store.userinfo.phone"
|
||||
placeholder="请输入手机号" placeholder-style="font-size: 32rpx;color: #999999;" />
|
||||
</view>
|
||||
<view class="box" style="padding-top: 30rpx;padding-bottom: 30rpx;">
|
||||
<view>劳动合同号</view>
|
||||
<input style="text-align: right;" type="nickname" disabled v-model="store.userinfo.workNo"
|
||||
placeholder="请输入劳动合同号" placeholder-style="font-size: 32rpx;color: #999999;" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="line">
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
reactive,
|
||||
ref
|
||||
} from "vue";
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
userEditApi,
|
||||
} from '@/api/api.js';
|
||||
import {
|
||||
beforeJump,
|
||||
imgUrl
|
||||
} from '@/utils/index.js';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
const baseUrl = import.meta.env.VITE_REQUEST_BASE_URL + '/jeecg-boot/sys/common/upload'
|
||||
const store = useStore()
|
||||
|
||||
const jump = (url) => {
|
||||
beforeJump(url, () => {
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
})
|
||||
}
|
||||
const chooseAvatar = () => {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
success: (chooseImageRes) => {
|
||||
const tempFilePaths = chooseImageRes.tempFilePaths;
|
||||
const photoPath = '用户头像/' + store.userinfo.realname
|
||||
uni.uploadFile({
|
||||
url: baseUrl, //仅为示例,非真实的接口地址
|
||||
filePath: tempFilePaths[0],
|
||||
name: 'file',
|
||||
formData: {
|
||||
appPath: photoPath
|
||||
},
|
||||
success: (res) => {
|
||||
uni.showLoading({
|
||||
title: '上传中...'
|
||||
})
|
||||
form.avatar = JSON.parse(res.data).message
|
||||
userEditApi({
|
||||
avatar: form.avatar,
|
||||
id: store.userinfo.id
|
||||
}).then((res) => {
|
||||
if (res) {
|
||||
uni.showToast({
|
||||
title: res,
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
})
|
||||
},
|
||||
fail(err) {
|
||||
console.log('图片上传出错', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
const form = reactive({
|
||||
avatar: '',
|
||||
realname: '',
|
||||
phone: ''
|
||||
})
|
||||
onLoad(() => {
|
||||
uni.setNavigationBarColor({
|
||||
frontColor: "#ffffff",
|
||||
backgroundColor: '#bebebe'
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.choose {
|
||||
font-size: 32rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.choosed {
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
button::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 30rpx 30rpx 0 30rpx;
|
||||
|
||||
.box:not(:last-child) {
|
||||
border-bottom: 1rpx solid #EFEFEF;
|
||||
}
|
||||
|
||||
.box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
|
||||
button {
|
||||
background-color: #fff;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
|
||||
image {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
.out_login {
|
||||
color: #ED361D;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
margin-top: 60rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.line {
|
||||
height: 10rpx;
|
||||
background: #F8F8F8;
|
||||
}
|
||||
|
||||
</style>
|
||||
337
pages/userlist/index.vue
Normal file
@ -0,0 +1,337 @@
|
||||
<template>
|
||||
<view :class="['content',{'gray':store.isgray==1}]">
|
||||
<uni-data-picker @popupclosed="popclose($event)" :step-searh="false" :map="{text:'departName',value:'id'}"
|
||||
:localdata="departList" popup-title="请选择部门" placeholder="请选择部门" @nodeclick="onnodeclick">
|
||||
</uni-data-picker>
|
||||
<view class="search_box">
|
||||
<view class="username f-row aic">
|
||||
用户姓名:<input v-model="realname" type="text" placeholder="请输入姓名"
|
||||
placeholder-style="color: grey;font-size: 28rpx;">
|
||||
</view>
|
||||
<view class="username f-row aic">
|
||||
用户账号:<input v-model="username" type="text" placeholder="请输入账号"
|
||||
placeholder-style="color: grey;font-size: 28rpx;">
|
||||
</view>
|
||||
<view class="btn f-row aic jca">
|
||||
<view class="f-row aic" @click="search">
|
||||
<uni-icons type="search" size="15" color="#fff"></uni-icons>
|
||||
查询
|
||||
</view>
|
||||
<view class="f-row aic" @click="refresh">
|
||||
<uni-icons type="refreshempty" size="15" color="#fff"></uni-icons>
|
||||
重置
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="list">
|
||||
<view class="title f-row aic box">
|
||||
<view class="">
|
||||
|
||||
</view>
|
||||
<view class="">
|
||||
序号
|
||||
</view>
|
||||
<view class="username">
|
||||
用户账号
|
||||
</view>
|
||||
<view class="">
|
||||
用户姓名
|
||||
</view>
|
||||
</view>
|
||||
<view class="item f-row aic box" v-for="item,i in userlist" :key="i">
|
||||
<view class="f-row aic img" @click="choose(item.id)">
|
||||
<image v-if="chooseArr.includes(item.id)" src="../../static/login/checked.png" mode=""></image>
|
||||
<image v-else src="../../static/login/nocheck.png" mode=""></image>
|
||||
</view>
|
||||
<view class="order">
|
||||
{{i+1}}
|
||||
</view>
|
||||
<view class="username f-col aic">
|
||||
<view class="">
|
||||
{{item.username}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="realname">
|
||||
<view class="">
|
||||
{{item.realname}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="confirm f-col aic">
|
||||
<view class="" @click="handleprocess">
|
||||
确认
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
ref,
|
||||
getCurrentInstance
|
||||
} from 'vue';
|
||||
import {
|
||||
queryMyDeptTreeListApi,
|
||||
queryUserByDepIdApi,
|
||||
taskEntrustApi,
|
||||
processCompleteApi
|
||||
} from '@/api/api.js';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
const store = useStore()
|
||||
const {
|
||||
proxy
|
||||
} = getCurrentInstance()
|
||||
const departList = ref([])
|
||||
/**部门列表*/
|
||||
const queryMyDeptTreeList = () => {
|
||||
queryMyDeptTreeListApi().then((res) => {
|
||||
departList.value = res.result
|
||||
currentId = res.result[0].id
|
||||
queryUserByDepId(res.result[0].id)
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
})
|
||||
}
|
||||
const userlist = ref([])
|
||||
/**根据部门查询人员*/
|
||||
const queryUserByDepId = (id, username, realname) => {
|
||||
queryUserByDepIdApi({
|
||||
id,
|
||||
username: username || '',
|
||||
realname: realname || ''
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
userlist.value = res.result
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
})
|
||||
}
|
||||
let currentId = null
|
||||
let departArr = []
|
||||
const onnodeclick = (e) => {
|
||||
queryUserByDepId(e.id)
|
||||
currentId = e.id
|
||||
if (departArr.indexOf(e.title) != -1) {
|
||||
departArr.splice(departArr.indexOf(e.title), 1, e.title)
|
||||
} else {
|
||||
departArr.push(e.title)
|
||||
|
||||
}
|
||||
}
|
||||
const popclose = (e) => {
|
||||
}
|
||||
const chooseArr = ref([])
|
||||
const choose = (id) => {
|
||||
if (isradio) { //单选
|
||||
if (chooseArr.value.indexOf(id) != -1) return
|
||||
chooseArr.value.splice(chooseArr.value.indexOf(id), 1, id)
|
||||
} else { //多选
|
||||
if (chooseArr.value.indexOf(id) != -1) {
|
||||
chooseArr.value.splice(chooseArr.value.indexOf(id), 1)
|
||||
} else {
|
||||
chooseArr.value.push(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
/**0为多选,1单选*/
|
||||
let isradio = 0
|
||||
/**任务id*/
|
||||
let taskId = null
|
||||
/**nextnode*/
|
||||
let nextnode = null
|
||||
/**reason*/
|
||||
let reason = null
|
||||
onLoad((options) => {
|
||||
isradio = options.isradio
|
||||
taskId = options.id
|
||||
reason = options.reason
|
||||
if (options.nextnode) {
|
||||
nextnode = JSON.parse(options.nextnode)
|
||||
}
|
||||
queryMyDeptTreeList()
|
||||
|
||||
})
|
||||
const username = ref('')
|
||||
const realname = ref('')
|
||||
const search = () => {
|
||||
if (username.value.trim() || realname.value.trim()) {
|
||||
userlist.value = []
|
||||
queryUserByDepId(currentId, username.value, realname.value)
|
||||
}
|
||||
}
|
||||
const refresh = () => {
|
||||
username.value = ''
|
||||
realname.value = ''
|
||||
userlist.value = []
|
||||
queryUserByDepId(currentId, username.value, realname.value)
|
||||
}
|
||||
/**委托*/
|
||||
const taskEntrust = () => {
|
||||
if (!chooseArr.value.length) return proxy.$toast('请选择被委托人')
|
||||
taskEntrustApi({
|
||||
taskAssignee: userlist.value.filter(item => item.id == chooseArr.value[0])[0].username,
|
||||
taskId
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
proxy.$toast(res.message)
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 2000)
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleprocess = () => {
|
||||
if (nextnode) {
|
||||
processComplete()
|
||||
} else {
|
||||
taskEntrust()
|
||||
}
|
||||
}
|
||||
/**流程办理接口*/
|
||||
const processComplete = () => {
|
||||
processCompleteApi({
|
||||
taskId,
|
||||
reason,
|
||||
processModel: 1,
|
||||
nextnode: nextnode[0].nextnode,
|
||||
nextUserName: userlist.value.filter(item => item.id == chooseArr.value[0])[0].realname,
|
||||
nextUserId: chooseArr.value[0],
|
||||
}).then((res) => {
|
||||
proxy.$toast(res.message)
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 2000)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
padding-bottom: 130rpx;
|
||||
}
|
||||
|
||||
.confirm {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background-color: #fff;
|
||||
border-top: 1px solid #efefef;
|
||||
width: 100%;
|
||||
padding: 20rpx 0;
|
||||
|
||||
view {
|
||||
width: 630rpx;
|
||||
height: 88rpx;
|
||||
background: #01508B;
|
||||
border-radius: 44rpx;
|
||||
font-size: 32rpx;
|
||||
color: #FFFFFF;
|
||||
text-align: center;
|
||||
line-height: 88rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.search_box {
|
||||
|
||||
font-size: 28rpx;
|
||||
|
||||
.username {
|
||||
padding: 0 20rpx;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
height: 100rpx;
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
color: #fff;
|
||||
padding: 20rpx 0;
|
||||
|
||||
view {
|
||||
width: 178rpx;
|
||||
height: 80rpx;
|
||||
background-color: #01508B;
|
||||
border-radius: 40rpx;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list {
|
||||
word-break: break-all;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
|
||||
.box {
|
||||
view:first-child {
|
||||
flex: 0.3;
|
||||
}
|
||||
|
||||
view:nth-child(2) {
|
||||
flex: 0.3;
|
||||
}
|
||||
|
||||
view:nth-child(3) {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
view:nth-child(4) {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
background-color: #f8f8f8;
|
||||
height: 100rpx;
|
||||
}
|
||||
|
||||
.item {
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
|
||||
.order {
|
||||
border-right: 1px solid #e5e5e5;
|
||||
height: 100rpx;
|
||||
line-height: 100rpx;
|
||||
}
|
||||
|
||||
.username {
|
||||
border-right: 1px solid #e5e5e5;
|
||||
height: 100rpx;
|
||||
justify-content: center;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.realname {
|
||||
height: 100rpx;
|
||||
line-height: 100rpx;
|
||||
overflow-y: auto;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.img {
|
||||
border-right: 1px solid #e5e5e5;
|
||||
height: 100rpx;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
386
pages/views/renliziyuan/qingjiaxinxi/application.vue
Normal file
@ -0,0 +1,386 @@
|
||||
<template>
|
||||
<view :class="{'gray':store.isgray==1}">
|
||||
<view class="form">
|
||||
<view class="f-row aic jcb input_box">
|
||||
<view class="title">
|
||||
职工姓名:
|
||||
</view>
|
||||
<input v-model="realname" disabled />
|
||||
</view>
|
||||
<view class="f-row aic jcb input_box">
|
||||
<view class="title">
|
||||
工作单位:
|
||||
</view>
|
||||
<input v-model="depart" disabled />
|
||||
</view>
|
||||
<view class="f-row aic jcb input_box">
|
||||
<view class="title">
|
||||
联系方式:
|
||||
</view>
|
||||
<input v-model="phone" />
|
||||
</view>
|
||||
<view class="f-row aic jcb input_box">
|
||||
<view class="title">
|
||||
请假类型:
|
||||
</view>
|
||||
<tree-select :dataSource="dataSource" v-model="type" dataValue="name" />
|
||||
</view>
|
||||
<picker mode="date" fields="day" @change="chooseStart" :value="beginTime" :start="startDate" :end="endTime">
|
||||
<view class="f-row aic jcb box">
|
||||
<view class="title">
|
||||
开始时间:
|
||||
</view>
|
||||
<view class="f-row aic">
|
||||
<view :class="[{'choose':!beginTime},{'choosed':beginTime}]">
|
||||
{{beginTime?beginTime:'请选择'}}
|
||||
</view>
|
||||
<uni-icons type="bottom" color="#333333"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</picker>
|
||||
<picker mode="date" fields="day" @change="chooseEnd" :value="endTime" :start="beginTime">
|
||||
<view class="f-row aic jcb box">
|
||||
<view class="title">
|
||||
截止时间:
|
||||
</view>
|
||||
<view class="f-row aic">
|
||||
<view :class="[{'choose':!endTime},{'choosed':endTime}]">
|
||||
{{endTime?endTime:'请选择'}}
|
||||
</view>
|
||||
<uni-icons type="bottom" color="#333333"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</picker>
|
||||
<picker @change="bindType" :value="typeIndex" :range="typeArr" range-key="realname">
|
||||
<view class="f-row aic jcb box">
|
||||
<view class="title">
|
||||
{{examineleader}}:
|
||||
</view>
|
||||
<view class="f-row aic">
|
||||
<view :class="[{'choose':typeIndex==null},{'choosed':typeIndex!=null}]">
|
||||
{{typeIndex!=null?typeArr[typeIndex].realname:'请选择'}}
|
||||
</view>
|
||||
<uni-icons type="bottom" color="#333333"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</picker>
|
||||
<view class="f-row aic jcb input_box">
|
||||
<view class="title">
|
||||
出发地:
|
||||
</view>
|
||||
<input v-model="departure" placeholder="请输入" nplaceholder-style="font-size: 28rpx;color: #999999;" />
|
||||
</view>
|
||||
<view class="f-row aic jcb input_box">
|
||||
<view class="title">
|
||||
目的地:
|
||||
</view>
|
||||
<input v-model="destination" placeholder="请输入" nplaceholder-style="font-size: 28rpx;color: #999999;" />
|
||||
</view>
|
||||
<view class="f-row aic jcb input_box">
|
||||
<view class="title">
|
||||
请假事由:
|
||||
</view>
|
||||
<input v-model="reason" placeholder="请输入" placeholder-style="font-size: 28rpx;color: #999999;" />
|
||||
</view>
|
||||
<view class="f-row aic jcb input_box">
|
||||
<view class="title">
|
||||
上传附件:
|
||||
</view>
|
||||
<uni-file-picker @select="select" :image-styles="imageStyles" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="btn f-col aic">
|
||||
<view @click="qjAdd">
|
||||
提交
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
getCurrentInstance
|
||||
} from 'vue';
|
||||
import {
|
||||
startMutilProcessApi,
|
||||
getCategoryItemsApi,
|
||||
} from '@/api/api.js';
|
||||
import {
|
||||
qjAddApi,
|
||||
queryZwmcAndExaApi,
|
||||
queryHisDateApi
|
||||
} from '@/api/leaveApi.js';
|
||||
import {
|
||||
queryDepByCode,
|
||||
queryZbDepByLdhth
|
||||
} from '@/api/depart.js'
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app'
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
import treeSelect from "@/components/treeSelect/treeSelect.vue"
|
||||
|
||||
const store = useStore()
|
||||
const {
|
||||
proxy
|
||||
} = getCurrentInstance()
|
||||
|
||||
/**职工姓名*/
|
||||
const realname = ref(store.userinfo.realname)
|
||||
/**工作单位*/
|
||||
const depart = ref('')
|
||||
/**工作单位*/
|
||||
const orgCode = ref('')
|
||||
/**联系方式*/
|
||||
const phone = ref(store.userinfo.phone)
|
||||
/**请假类型*/
|
||||
const type = ref('')
|
||||
const dataSource = ref([])
|
||||
/**开始时间*/
|
||||
const beginTime = ref('')
|
||||
const chooseStart = (e) => {
|
||||
beginTime.value = e.detail.value
|
||||
}
|
||||
/**请假开始时间 绑定start*/
|
||||
const startDate = ref('')
|
||||
/**结束时间*/
|
||||
const endTime = ref('')
|
||||
const chooseEnd = (e) => {
|
||||
endTime.value = e.detail.value
|
||||
}
|
||||
/**审批领导*/
|
||||
const typeArr = ref([])
|
||||
const typeIndex = ref(null)
|
||||
/**判断显示审批 / 分管 领导*/
|
||||
const examineleader = ref(true)
|
||||
/**职位层级*/
|
||||
const zwcj = ref('')
|
||||
/**出发地*/
|
||||
const departure = ref('')
|
||||
/**目的地*/
|
||||
const destination = ref('')
|
||||
/**请假事由*/
|
||||
const reason = ref('')
|
||||
/**附件路径*/
|
||||
const path = ref([])
|
||||
const baseUrl = import.meta.env.VITE_REQUEST_BASE_URL + '/jeecg-boot/sys/common/upload/'
|
||||
const imageStyles = {
|
||||
width: 64,
|
||||
height: 64,
|
||||
border: {
|
||||
color: "#dce7e1",
|
||||
width: 2,
|
||||
style: 'dashed',
|
||||
radius: '2px'
|
||||
}
|
||||
}
|
||||
onLoad(() => {
|
||||
loadData()
|
||||
})
|
||||
|
||||
const select = (e) => {
|
||||
const tempFilePaths = e.tempFilePaths
|
||||
for (let i = 0; i < e.tempFilePaths.length; i++) {
|
||||
let photoPath = '职工请假/' + depart.value + '/' + store.userinfo.realname
|
||||
uni.uploadFile({
|
||||
url: baseUrl,
|
||||
filePath: e.tempFilePaths[i],
|
||||
name: 'file',
|
||||
formData: {
|
||||
appPath: photoPath
|
||||
},
|
||||
success: (res) => {
|
||||
path.value.push(JSON.parse(res.data).message)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const qjAdd = () => {
|
||||
if (!phone.value.trim()) return proxy.$toast('请输入联系方式')
|
||||
if (!type.value) return proxy.$toast('请选择请假类型')
|
||||
if (!beginTime.value) return proxy.$toast('请选择开始时间')
|
||||
if (!endTime.value) return proxy.$toast('请选择结束时间')
|
||||
if (typeIndex.value == null) { //副职、员工需要选择审批领导
|
||||
return proxy.$toast('请选择' + examineleader.value)
|
||||
}
|
||||
if (!departure.value.trim()) return proxy.$toast('请输入出发地')
|
||||
if (!destination.value.trim()) return proxy.$toast('请输入目的地')
|
||||
if (!reason.value.trim()) return proxy.$toast('请输入请假事由')
|
||||
|
||||
qjAddApi({
|
||||
sysOrgCode: orgCode.value,
|
||||
username: store.userinfo.username,
|
||||
phone: phone.value,
|
||||
type: type.value,
|
||||
begintime: beginTime.value,
|
||||
endtime: endTime.value,
|
||||
examineleader: typeArr.value[typeIndex.value] ? typeArr.value[typeIndex.value].username : '',
|
||||
departure: departure.value,
|
||||
destination: destination.value,
|
||||
reason: reason.value,
|
||||
zwmc: zwcj.value,
|
||||
path: path.value.toString()
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
startMutilProcess(res.message)
|
||||
} else {
|
||||
proxy.$toast(res.message);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const startMutilProcess = (id) => {
|
||||
startMutilProcessApi({
|
||||
flowCode: "dev_cxc_qxj",
|
||||
id,
|
||||
formUrl: "modules/qxj/modules/CxcQxjBpmModel",
|
||||
formUrlMobile: "leaveApplication" //对应main.js里全局注册createApp()里的 app.component('leaveApplication',index)
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
proxy.$toast(res.message)
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 2000)
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
})
|
||||
}
|
||||
const loadData = () => {
|
||||
getCategoryItemsApi('1838487445813645313').then((res) => { //请假类型
|
||||
if (res.success) {
|
||||
dataSource.value = res.result
|
||||
}
|
||||
})
|
||||
|
||||
queryZbDepByLdhth(store.userinfo.workNo).then((res) => { //获取工作单位
|
||||
depart.value = res.departName
|
||||
orgCode.value = res.orgCode
|
||||
})
|
||||
|
||||
queryZwmcAndExaApi(store.userinfo.username).then((res) => { //本人职位及审批领导列表
|
||||
if (res.success) {
|
||||
typeArr.value = res.result.list
|
||||
zwcj.value = res.result.zwmc
|
||||
if (zwcj.value == '单位专家' || zwcj.value == '基层正职' || zwcj.value == '高级主管') {
|
||||
examineleader.value = '分管领导';
|
||||
}else{
|
||||
examineleader.value = '审批领导';
|
||||
}
|
||||
} else {
|
||||
proxy.$toast(res.message);
|
||||
}
|
||||
})
|
||||
|
||||
queryHisDateApi(store.userinfo.username).then((res) => { // 最新请假结束日期
|
||||
if (res) {
|
||||
getTomorrowDate(res);
|
||||
startDate.value = beginTime.value; // 如果有最新请假日期,设置startDate为该日期
|
||||
} else {
|
||||
getTomorrowDate();
|
||||
startDate.value = '1900-01-01';
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const bindType = (e) => {
|
||||
typeIndex.value = e.detail.value
|
||||
}
|
||||
|
||||
const getTomorrowDate = (e) => {
|
||||
let tomorrow;
|
||||
if (e) {
|
||||
// 将传入的日期字符串转换为Date对象
|
||||
const dateParts = e.split('-').map(Number);
|
||||
tomorrow = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);
|
||||
} else {
|
||||
// 如果没有提供日期,则使用当前日期
|
||||
tomorrow = new Date();
|
||||
}
|
||||
// 设置为明天的日期
|
||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||
// 格式化日期
|
||||
const year = tomorrow.getFullYear();
|
||||
const month = (tomorrow.getMonth() + 1).toString().padStart(2, '0');
|
||||
const day = tomorrow.getDate().toString().padStart(2, '0');
|
||||
beginTime.value = `${year}-${month}-${day}`;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page {
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.btn {
|
||||
border-top: 1px solid #EFEFEF;
|
||||
height: 120rpx;
|
||||
justify-content: center;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100vw;
|
||||
|
||||
view {
|
||||
width: 690rpx;
|
||||
height: 88rpx;
|
||||
background: #01508B;
|
||||
border-radius: 16rpx;
|
||||
font-size: 28rpx;
|
||||
color: #FFFFFF;
|
||||
text-align: center;
|
||||
line-height: 88rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.input_box {
|
||||
height: 100rpx;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
text-align: right;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.form {
|
||||
padding: 0 30rpx;
|
||||
background-color: #fff;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.box {
|
||||
height: 100rpx;
|
||||
}
|
||||
|
||||
.box:not(:last-child) {
|
||||
border-bottom: 1px solid #EFEFEF;
|
||||
|
||||
}
|
||||
|
||||
.choose {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.choosed {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
174
pages/views/renliziyuan/qingjiaxinxi/detail.vue
Normal file
@ -0,0 +1,174 @@
|
||||
<template>
|
||||
<view class="f-col aic">
|
||||
<view class="info_box">
|
||||
<view class="title">
|
||||
申请信息
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
请假职工:
|
||||
</view>
|
||||
<text>{{info.username_dictText}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
所属单位:
|
||||
</view>
|
||||
<text>{{info.sysOrgCode_dictText}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
联系方式:
|
||||
</view>
|
||||
<text>{{info.phone}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
请假类型:
|
||||
</view>
|
||||
<text>{{info.type}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
请假开始时间:
|
||||
</view>
|
||||
<text>{{info.begintime}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
请假结束时间:
|
||||
</view>
|
||||
<text>{{info.endtime}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
请假天数:
|
||||
</view>
|
||||
<text>{{info.days}}天</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
审批人:
|
||||
</view>
|
||||
<text>{{info.examineleader_dictText}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
出发地:
|
||||
</view>
|
||||
<text>{{info.departure}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
目的地:
|
||||
</view>
|
||||
<text>{{info.destination}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb">
|
||||
<view>
|
||||
请假原因:
|
||||
</view>
|
||||
<text>{{info.reason}}</text>
|
||||
</view>
|
||||
<view class="info f-row aic jcb" v-if="ifShowFj">
|
||||
<view>
|
||||
附件:
|
||||
</view>
|
||||
<uni-file-picker v-model="imageValue" :image-styles="imageStyles" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
processHistoryListApi
|
||||
} from '@/api/api.js';
|
||||
import {
|
||||
qjQueryByIdApi
|
||||
} from '@/api/leaveApi.js';
|
||||
import {
|
||||
ref,
|
||||
onMounted
|
||||
} from 'vue'
|
||||
import {
|
||||
imgUrl
|
||||
} from '@/utils/index.js';
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
const imageValue = ref([])
|
||||
const ifShowFj = ref(false)
|
||||
const imageStyles = {
|
||||
width: 64,
|
||||
height: 64,
|
||||
border: {
|
||||
color: "#dce7e1",
|
||||
width: 2,
|
||||
style: 'dashed',
|
||||
radius: '2px'
|
||||
}
|
||||
}
|
||||
const info = ref({})
|
||||
// 申请信息
|
||||
const qjQueryById = (e) => {
|
||||
qjQueryByIdApi({
|
||||
id: e
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
info.value = res.result.records[0]
|
||||
// 构造 imageValue 数组
|
||||
if (info.value.path) {
|
||||
ifShowFj.value = true;
|
||||
imageValue.value = info.value.path.split(',').map(path => {
|
||||
const name = path.split('/').pop(); // 获取文件名
|
||||
const extname = name.split('.').pop(); // 获取文件扩展名并转换为大写
|
||||
return {
|
||||
name,
|
||||
extname,
|
||||
url: imgUrl(path)
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
onLoad((options) => {
|
||||
qjQueryById(options.id)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.info_box {
|
||||
padding: 40rpx 30rpx 16rpx 30rpx;
|
||||
width: 630rpx;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
margin-top: 30rpx;
|
||||
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
background-image: url(../../static/index/line.png);
|
||||
background-size: 44rpx 12rpx;
|
||||
background-repeat: no-repeat;
|
||||
background-position: left bottom;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.info {
|
||||
font-size: 28rpx;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
view {
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
text {
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
284
pages/views/renliziyuan/qingjiaxinxi/index.vue
Normal file
@ -0,0 +1,284 @@
|
||||
<template>
|
||||
<view :class="['content',{'gray':store.isgray==1}]">
|
||||
<uni-card>
|
||||
<view>
|
||||
<uni-row v-show="!username">
|
||||
<uni-col :span="12"><uni-title title="所属单位" align="left" type="h5"></uni-title></uni-col>
|
||||
<uni-col :span="12"><uni-title title="重置" align="right" type="h5" color="#666666"
|
||||
@click="reset"></uni-title></uni-col>
|
||||
</uni-row>
|
||||
<uni-row v-show="!username">
|
||||
<uni-col :span="24">
|
||||
<trq-depart-select v-model="orgCode" returnCodeOrID="orgCode"
|
||||
@change="departChange"></trq-depart-select>
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
<uni-row v-show="!username">
|
||||
<uni-col :span="12"><uni-title title="姓名" align="left" type="h5"></uni-title></uni-col>
|
||||
<uni-col :span="12"><uni-title title="劳动合同号" align="left" type="h5"></uni-title></uni-col>
|
||||
</uni-row>
|
||||
<uni-row v-show="!username">
|
||||
<uni-col :span="12">
|
||||
<uni-easyinput v-model="realname" placeholder="姓名模糊查询" @change="Search" @clear="Search"/>
|
||||
</uni-col>
|
||||
<uni-col :span="12">
|
||||
<uni-easyinput v-model="contractNumber" placeholder="劳动合同号查询" @change="Search" @clear="Search"/>
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
<uni-row>
|
||||
<uni-col :span="24"><uni-title title="请假时间" align="left" type="h5"></uni-title></uni-col>
|
||||
</uni-row>
|
||||
<uni-row>
|
||||
<uni-col :span="24">
|
||||
<uni-datetime-picker v-model="range" type="daterange" rangeSeparator="至" @input="handleInput" />
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
<!-- ECharts图表 -->
|
||||
<view class="chart-container">
|
||||
<l-echart ref="chart" />
|
||||
</view>
|
||||
</view>
|
||||
</uni-card>
|
||||
<view class="list">
|
||||
<view class="item" v-for="item,i in list" :key="i"
|
||||
@click="jump(`/pages/views/renliziyuan/qingjiaxinxi/detail?id=${item.id}`)">
|
||||
<view class="title">
|
||||
{{item.username_dictText}}的{{item.type}}申请
|
||||
</view>
|
||||
<view class="time_box f-row aic">
|
||||
<view class="time">
|
||||
{{item.sysOrgCode_dictText}}
|
||||
</view>
|
||||
<view class="f-row aic no-wrap-right">
|
||||
{{item.begintime}}至{{item.endtime}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from 'vue';
|
||||
import {
|
||||
onReachBottom,
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
queryLeaveListApi,
|
||||
countByOrgApi
|
||||
} from '@/api/leaveApi.js';
|
||||
import {
|
||||
getCategoryItemsApi
|
||||
} from '@/api/api.js';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
|
||||
import * as echarts from 'echarts';
|
||||
const chart = ref(null);
|
||||
const chartOption = ref({});
|
||||
const orgCode = ref('') //部门树选中的orgCode
|
||||
const range = ref('') //日期查询
|
||||
const type = ref('') //图表点击事件
|
||||
const username = ref('') //用户名
|
||||
const realname = ref('') //姓名查询
|
||||
const contractNumber = ref('') //劳动合同号查询
|
||||
const timeout = ref(null)
|
||||
const store = useStore();
|
||||
const list = ref([])
|
||||
let pageNo = 1
|
||||
let pageSize = 15
|
||||
let loading = false
|
||||
|
||||
onLoad((options) => {
|
||||
if (options.username) {
|
||||
username.value = options.username
|
||||
}
|
||||
})
|
||||
|
||||
function departChange(e) {
|
||||
orgCode.value = e
|
||||
queryLeave()
|
||||
}
|
||||
|
||||
function reset() {
|
||||
orgCode.value = null
|
||||
range.value = []
|
||||
type.value = ''
|
||||
username.value = ''
|
||||
realname.value = ''
|
||||
contractNumber.value = ''
|
||||
queryLeave()
|
||||
}
|
||||
|
||||
function handleInput(e) {
|
||||
queryLeave()
|
||||
}
|
||||
|
||||
function Search() {
|
||||
if (timeout.value) {
|
||||
clearTimeout(timeout.value);
|
||||
}
|
||||
timeout.value = setTimeout(() => {
|
||||
queryLeave()
|
||||
}, 300); // 300ms 防抖时间
|
||||
}
|
||||
|
||||
function clearSearch() {
|
||||
console.log('-----',realname.value)
|
||||
console.log('-----',contractNumber.value)
|
||||
|
||||
}
|
||||
|
||||
const queryLeave = (e) => {
|
||||
let param = {
|
||||
sysOrgCode: orgCode.value,
|
||||
begin: range.value[0],
|
||||
end: range.value[1],
|
||||
type: type.value,
|
||||
username: username.value,
|
||||
realname: realname.value,
|
||||
contractNumbers: contractNumber.value
|
||||
}
|
||||
if (e == 1) { // 下拉刷新时,pageNo++
|
||||
pageNo++;
|
||||
} else { // list置空,pageNo置1
|
||||
list.value = [];
|
||||
pageNo = 1;
|
||||
if (e != 2) {
|
||||
// 如果不是图表点击事件,更新图表
|
||||
setChartOption(param);
|
||||
}
|
||||
}
|
||||
// 更新数据
|
||||
queryLeaveList(param);
|
||||
}
|
||||
|
||||
const queryLeaveList = (params = {}) => {
|
||||
loading = true
|
||||
queryLeaveListApi({
|
||||
...params,
|
||||
pageNo,
|
||||
pageSize
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
list.value = [...list.value, ...res.result.records]
|
||||
}
|
||||
|
||||
loading = false
|
||||
}).catch((err) => {})
|
||||
}
|
||||
|
||||
// 初始化图表
|
||||
const initChart = () => {
|
||||
setTimeout(async () => {
|
||||
if (!chart.value) return;
|
||||
const myChart = await chart.value.init(echarts);
|
||||
myChart.setOption(chartOption.value);
|
||||
myChart.on('click', (params) => {
|
||||
// 根据 params 处理点击事件
|
||||
type.value = params.name
|
||||
queryLeave(2);
|
||||
});
|
||||
}, 300);
|
||||
};
|
||||
|
||||
const setChartOption = (e) => {
|
||||
countByOrgApi(e).then(res => {
|
||||
chartOption.value = {
|
||||
tooltip: {
|
||||
trigger: 'item'
|
||||
},
|
||||
series: [{
|
||||
type: 'pie',
|
||||
radius: '50%',
|
||||
data: res.result
|
||||
}]
|
||||
}
|
||||
initChart()
|
||||
})
|
||||
}
|
||||
|
||||
const jump = (url) => {
|
||||
uni.navigateTo({
|
||||
url: url
|
||||
});
|
||||
}
|
||||
|
||||
const back = () => {
|
||||
uni.navigateBack()
|
||||
}
|
||||
|
||||
onReachBottom(() => {
|
||||
if (loading) return
|
||||
queryLeave(1); //下拉刷新传1
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.content {
|
||||
padding-top: v-bind(cusnavbarheight);
|
||||
padding-bottom: 24rpx;
|
||||
|
||||
}
|
||||
|
||||
.list {
|
||||
padding: 0 30rpx;
|
||||
|
||||
.item {
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-top: 24rpx;
|
||||
position: relative;
|
||||
|
||||
.dot {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
background: #ED361D;
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
left: 9rpx;
|
||||
top: 44rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-bottom: 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.time_box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
/* 均匀分布子元素 */
|
||||
font-size: 24rpx;
|
||||
color: #888888;
|
||||
|
||||
.time {
|
||||
margin-right: 62rpx;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.no-wrap-right {
|
||||
white-space: nowrap;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.back {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
</style>
|
||||
608
pages/views/renliziyuan/renyuanxinxi/detail.vue
Normal file
@ -0,0 +1,608 @@
|
||||
<template>
|
||||
<view>
|
||||
<scroll-view :scroll-x="true" :scroll-y="true">
|
||||
<view style="padding: 10px 10px 10px 10px">
|
||||
<uni-title title="基本信息" type="h1" color="blue"></uni-title>
|
||||
<uni-row>
|
||||
<uni-col :span="18"><yjly-row-cell :cellData="cellData" :rowDataCount="2"></yjly-row-cell></uni-col>
|
||||
<uni-col :span="6">
|
||||
<view class="img">
|
||||
<image mode="aspectFit" :src="'https://36.112.48.190/jeecg-boot/sys/common/static/' + imgUrl"></image>
|
||||
</view>
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
|
||||
<yjly-row-cell :cellData="cellData1" :rowDataCount="3"></yjly-row-cell>
|
||||
<view v-if="roleDetail">
|
||||
<uni-title title="年度绩效考核" type="h1" color="blue"></uni-title>
|
||||
<uni-row>
|
||||
<uni-col :span="4">
|
||||
<view class="titleStyle">序号</view>
|
||||
</uni-col>
|
||||
<uni-col :span="10">
|
||||
<view class="titleStyle">绩效考核年份</view>
|
||||
</uni-col>
|
||||
<uni-col :span="10">
|
||||
<view class="titleStyle">绩效考核成绩</view>
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
<uni-row>
|
||||
<view v-for="(item, index) in jxkhxxList">
|
||||
<uni-col :span="4">
|
||||
<view class="dataStyle1">
|
||||
{{ index + 1 }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="10">
|
||||
<view class="dataStyle1">
|
||||
{{ item.nf }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="10">
|
||||
<view class="dataStyle1">
|
||||
{{ item.khcj + '---' + item.khcj_dictText }}
|
||||
</view>
|
||||
</uni-col>
|
||||
</view>
|
||||
</uni-row>
|
||||
</view>
|
||||
<uni-title title="工作简历" type="h1" color="blue"></uni-title>
|
||||
<uni-row>
|
||||
<uni-col :span="4">
|
||||
<view class="titleStyle">起始时间</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="titleStyle">终止时间</view>
|
||||
</uni-col>
|
||||
<uni-col :span="11">
|
||||
<view class="titleStyle">工作职务</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="titleStyle">岗位职务</view>
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
<uni-row>
|
||||
<view v-for="(item, index) in gzjlList">
|
||||
<uni-col :span="4">
|
||||
<view class="dataStyle2">
|
||||
{{ item.kssj }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="dataStyle2">
|
||||
{{ item.jssj }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="11">
|
||||
<view class="dataStyle2" ref="dataView">
|
||||
{{ item.jlms }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="dataStyle1">
|
||||
{{ item.jlms2 }}
|
||||
</view>
|
||||
</uni-col>
|
||||
</view>
|
||||
</uni-row>
|
||||
<!-- <uni-segmented-control></uni-segmented-control> -->
|
||||
<view>
|
||||
<uni-title title="学历信息" type="h1" color="blue"></uni-title>
|
||||
<uni-row>
|
||||
<uni-col :span="4">
|
||||
<view class="titleStyle">类别</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="titleStyle">毕业院校</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="titleStyle">所学专业</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="titleStyle">学历</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="titleStyle">学位</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="titleStyle">毕业时间</view>
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
<uni-row>
|
||||
<view v-for="(item, index) in xlxxList">
|
||||
<uni-col :span="4">
|
||||
<view class="dataStyle1">
|
||||
{{ item.xllb }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="dataStyle2">
|
||||
{{ item.byyx }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="dataStyle2" ref="dataView">
|
||||
{{ item.sxzy }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="dataStyle2">
|
||||
{{ item.qdxl }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="dataStyle2">
|
||||
{{ item.qdxw }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="dataStyle2">
|
||||
{{ item.bytime }}
|
||||
</view>
|
||||
</uni-col>
|
||||
</view>
|
||||
</uni-row>
|
||||
</view>
|
||||
<uni-title title="取证信息" type="h1" color="blue"></uni-title>
|
||||
<uni-row>
|
||||
<uni-col :span="6">
|
||||
<view class="titleStyle">证书名称</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="titleStyle">证书等级</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="titleStyle">取证时间</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="titleStyle">复审时间</view>
|
||||
</uni-col>
|
||||
<uni-col :span="3">
|
||||
<view class="titleStyle">备注</view>
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
<uni-row>
|
||||
<view v-for="(item, index) in zjtzList">
|
||||
<uni-col :span="6">
|
||||
<view class="dataStyle2" ref="dataView">
|
||||
{{ item.zjmc }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="dataStyle1">
|
||||
{{ item.zsdj }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="dataStyle1">
|
||||
{{ item.fzrq }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="dataStyle1">
|
||||
{{ item.fssj }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="3">
|
||||
<view class="dataStyle1">
|
||||
{{ item.bz }}
|
||||
</view>
|
||||
</uni-col>
|
||||
</view>
|
||||
</uni-row>
|
||||
<view v-if="roleDetail">
|
||||
<uni-title title="家庭信息" type="h1" color="blue"></uni-title>
|
||||
<uni-row>
|
||||
<uni-col :span="4">
|
||||
<view class="titleStyle">称谓</view>
|
||||
</uni-col>
|
||||
<uni-col :span="3">
|
||||
<view class="titleStyle">姓名</view>
|
||||
</uni-col>
|
||||
<uni-col :span="6">
|
||||
<view class="titleStyle">出生年月</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="titleStyle">政治面貌</view>
|
||||
</uni-col>
|
||||
<uni-col :span="7">
|
||||
<view class="titleStyle">工作单位及职务</view>
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
<uni-row>
|
||||
<view v-for="(item, index) in zyjtcyList">
|
||||
<uni-col :span="4">
|
||||
<view class="dataStyle2">
|
||||
{{ item.ybrgx }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="3">
|
||||
<view class="dataStyle1">
|
||||
{{ item.gxname }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="6">
|
||||
<view class="dataStyle1">
|
||||
{{ item.cstime }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="dataStyle1">
|
||||
{{ item.cyzzmm }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="7">
|
||||
<view class="dataStyle2" ref="dataView">
|
||||
{{ item.cygzdw }}
|
||||
</view>
|
||||
</uni-col>
|
||||
</view>
|
||||
</uni-row>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onReady, onLoad } from '@dcloudio/uni-app';
|
||||
import { reactive, ref, onMounted } from 'vue';
|
||||
import { queryGzjlByRyLdhth, queryQzqkByRyLdhth, queryJtzycyByRyLdhth, queryXlxxByRyLdhth, queryGbxxByRyLdhth, queryZyzgdjByRyLdhth, queryJxkhByRyLdhth } from '@/api/renyuan.js';
|
||||
import { useStore } from '@/store';
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const tempCellData = ref({
|
||||
title: '',
|
||||
value: '',
|
||||
titleSpan: 4,
|
||||
valueSpan: 4
|
||||
});
|
||||
|
||||
const roleDetail = ref(store.userinfo.realname === '廖德云' || store.userinfo.realname === '马敬朝');
|
||||
|
||||
const ldhth = ref('');
|
||||
const imgUrl = ref('');
|
||||
const renyuanData = ref({});
|
||||
const cellData = ref([]);
|
||||
const cellData1 = ref([]);
|
||||
|
||||
const gzjlList = ref([]); // 人员其他子表信息-工作经历
|
||||
const zjtzList = ref([]); // 人员其他子表信息-证件台账
|
||||
const zyjtcyList = ref([]); // 人员其他子表信息-主要家庭成员
|
||||
const xlxxList = ref([]); // 人员其他子表信息-学历证书
|
||||
const gbxxList = ref([]); // 人员其他子表信息-干部信息
|
||||
const zyzgdjList = ref([]); // 人员其他子表信息-职业资格等级
|
||||
const jxkhxxList = ref([]); // 人员其他子表信息-绩效考核信息
|
||||
|
||||
function getChildTable() {
|
||||
console.log(ldhth.value);
|
||||
|
||||
queryJxkhByRyLdhth({
|
||||
ldhth: ldhth.value
|
||||
})
|
||||
.then((res) => {
|
||||
// console.log(res);
|
||||
jxkhxxList.value = res.result.records;
|
||||
// console.log(jxkhxxList.value)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
|
||||
queryGbxxByRyLdhth({
|
||||
ldhth: ldhth.value
|
||||
})
|
||||
.then((res) => {
|
||||
// console.log(res);
|
||||
gbxxList.value = res;
|
||||
// console.log(gbxxList.value)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
queryZyzgdjByRyLdhth({
|
||||
ldhth: ldhth.value
|
||||
})
|
||||
.then((res) => {
|
||||
// console.log(res);
|
||||
zyzgdjList.value = res;
|
||||
// console.log(zyzgdjList.value)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
queryGzjlByRyLdhth({
|
||||
ldhth: ldhth.value
|
||||
})
|
||||
.then((res) => {
|
||||
// console.log(res);
|
||||
if (res.length > 0) {
|
||||
gzjlList.value = res;
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
queryQzqkByRyLdhth({
|
||||
ldhth: ldhth.value
|
||||
})
|
||||
.then((res) => {
|
||||
// console.log(res);
|
||||
if (res.length > 0) {
|
||||
zjtzList.value = res;
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
queryJtzycyByRyLdhth({
|
||||
ldhth: ldhth.value
|
||||
})
|
||||
.then((res) => {
|
||||
// console.log(res);
|
||||
if (res.length > 0) {
|
||||
zyjtcyList.value = res;
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
queryXlxxByRyLdhth({
|
||||
ldhth: ldhth.value
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
xlxxList.value = [];
|
||||
if (res.result.records.length > 0) {
|
||||
var rress = res.result.records;
|
||||
// console.log(rress);
|
||||
for (let i = 0; i < rress.length; i++) {
|
||||
if ((rress[i].onexl == 1) & (rress[i].zgxl == 1)) {
|
||||
rress[i].xllb = '第一学历';
|
||||
xlxxList.value.push(JSON.parse(JSON.stringify(rress[i])));
|
||||
// console.log(xlxxList.value)
|
||||
rress[i].xllb = '最高学历';
|
||||
xlxxList.value.push(JSON.parse(JSON.stringify(rress[i])));
|
||||
// console.log(xlxxList.value)
|
||||
}
|
||||
if ((rress[i].onexl == 1) & (rress[i].zgxl != 1)) {
|
||||
rress[i].xllb = '第一学历';
|
||||
xlxxList.value.push(rress[i]);
|
||||
}
|
||||
if ((rress[i].onexl != 1) & (rress[i].zgxl == 1)) {
|
||||
rress[i].xllb = '最高学历';
|
||||
xlxxList.value.push(rress[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// adjustFontSize()
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
function getJbxx() {
|
||||
cellData.value.push({
|
||||
title: '姓名',
|
||||
value: renyuanData.value.xm,
|
||||
titleSpan: 6,
|
||||
valueSpan: 6,
|
||||
class: 'dataStyle'
|
||||
});
|
||||
cellData.value.push({
|
||||
title: '性别',
|
||||
value: renyuanData.value.xb_dictText,
|
||||
titleSpan: 6,
|
||||
valueSpan: 6,
|
||||
class: 'dataStyle'
|
||||
});
|
||||
|
||||
cellData.value.push({
|
||||
title: '出生年月',
|
||||
value: renyuanData.value.cssj,
|
||||
titleSpan: 6,
|
||||
valueSpan: 6,
|
||||
class: 'dataStyle'
|
||||
});
|
||||
cellData.value.push({
|
||||
title: '民族',
|
||||
value: renyuanData.value.mz,
|
||||
titleSpan: 6,
|
||||
valueSpan: 6,
|
||||
class: 'dataStyle'
|
||||
});
|
||||
cellData.value.push({
|
||||
title: '籍贯',
|
||||
value: renyuanData.value.jg,
|
||||
titleSpan: 6,
|
||||
valueSpan: 6,
|
||||
class: 'dataStyle'
|
||||
});
|
||||
cellData.value.push({
|
||||
title: '出生地',
|
||||
value: renyuanData.value.csd,
|
||||
titleSpan: 6,
|
||||
valueSpan: 6,
|
||||
class: 'dataStyle'
|
||||
});
|
||||
cellData.value.push({
|
||||
title: '工作时间',
|
||||
value: renyuanData.value.cjgzsj,
|
||||
titleSpan: 6,
|
||||
valueSpan: 6,
|
||||
class: 'dataStyle'
|
||||
});
|
||||
|
||||
cellData.value.push({
|
||||
title: '现专业',
|
||||
value: '',
|
||||
titleSpan: 6,
|
||||
valueSpan: 6,
|
||||
class: 'dataStyle1'
|
||||
});
|
||||
cellData.value.push({
|
||||
title: '政治面貌',
|
||||
value: renyuanData.value.zzmm === '群众' ? renyuanData.value.zzmm : renyuanData.value.zzmm + renyuanData.value.jrsj,
|
||||
titleSpan: 5,
|
||||
valueSpan: 7,
|
||||
class: 'dataStyle1'
|
||||
});
|
||||
cellData.value.push({
|
||||
title: '用工形式',
|
||||
value: renyuanData.value.rylb1_dictText,
|
||||
titleSpan: 5,
|
||||
valueSpan: 7,
|
||||
class: 'dataStyle1'
|
||||
});
|
||||
|
||||
cellData1.value.push({
|
||||
title: '所在单位',
|
||||
value: renyuanData.value.orgCode_dictText,
|
||||
titleSpan: 5,
|
||||
valueSpan: 7,
|
||||
class: 'dataStyle1'
|
||||
});
|
||||
cellData1.value.push({
|
||||
title: '专业技术资格',
|
||||
value: gbxxList.value.zc === 0 ? '/' : gbxxList.value.zc + gbxxList.value.zcsj,
|
||||
titleSpan: 5,
|
||||
valueSpan: 7,
|
||||
class: 'dataStyle1'
|
||||
});
|
||||
cellData1.value.push({
|
||||
title: '',
|
||||
value: '',
|
||||
titleSpan: 0,
|
||||
valueSpan: 0,
|
||||
class: 'dataStyle'
|
||||
});
|
||||
|
||||
cellData1.value.push({
|
||||
title: '职业资格等级',
|
||||
value: zyzgdjList.value.ztgz === '0' ? '/' : zyzgdjList.value.ztgz + zyzgdjList.value.ztgzdj,
|
||||
titleSpan: 4,
|
||||
valueSpan: 4,
|
||||
class: 'dataStyle1'
|
||||
});
|
||||
cellData1.value.push({
|
||||
title: '职务(岗位)',
|
||||
value: gbxxList.value.zw,
|
||||
titleSpan: 4,
|
||||
valueSpan: 4,
|
||||
class: 'dataStyle1'
|
||||
});
|
||||
|
||||
cellData1.value.push({
|
||||
title: '职位级别',
|
||||
value: gbxxList.value.zwcj,
|
||||
titleSpan: 4,
|
||||
valueSpan: 4,
|
||||
class: 'dataStyle'
|
||||
});
|
||||
}
|
||||
|
||||
onLoad((e) => {
|
||||
console.log(store.userinfo);
|
||||
renyuanData.value = JSON.parse(decodeURIComponent(e.data));
|
||||
imgUrl.value = renyuanData.value.zplj;
|
||||
console.log(imgUrl.value, renyuanData.value);
|
||||
ldhth.value = renyuanData.value.ldhth;
|
||||
getChildTable();
|
||||
setTimeout(function () {
|
||||
getJbxx();
|
||||
}, 500);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.renyuanInfo {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 98vh;
|
||||
width: 900px;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
font-size: 18px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.titleStyle {
|
||||
font-size: 12px;
|
||||
color: #747474;
|
||||
line-height: 35px;
|
||||
height: 35px;
|
||||
background: #f2f9fc;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border-left: 1px solid #919191;
|
||||
border-bottom: 1px solid #919191;
|
||||
}
|
||||
|
||||
/* 内容样式 */
|
||||
.dataStyle {
|
||||
font-size: 14px;
|
||||
color: #00007f;
|
||||
line-height: 25px;
|
||||
height: 50px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border-bottom: 1px solid #919191;
|
||||
border-left: 1px solid #919191;
|
||||
text-align: center;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
/* 内容样式 */
|
||||
.dataStyle1 {
|
||||
font-size: 14px;
|
||||
color: #00007f;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border-bottom: 1px solid #919191;
|
||||
border-left: 1px solid #919191;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
/* 内容样式 */
|
||||
.dataStyle2 {
|
||||
font-size: 12px;
|
||||
color: #00007f;
|
||||
line-height: 15px;
|
||||
height: 30px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border-bottom: 1px solid #919191;
|
||||
border-left: 1px solid #919191;
|
||||
text-align: center;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.img {
|
||||
height: 154px;
|
||||
border: 1px solid #ccc;
|
||||
/* 仅用于展示容器范围,可根据需要移除 */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
/* 水平居中 */
|
||||
align-items: center;
|
||||
/* 垂直居中 */
|
||||
overflow: hidden;
|
||||
/* 防止图片溢出容器 */
|
||||
}
|
||||
</style>
|
||||
42
pages/views/renliziyuan/renyuanxinxi/index.vue
Normal file
@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<view>
|
||||
<uni-card :is-shadow="false">
|
||||
<uni-section title="台账信息" type="line">
|
||||
<uni-card :is-shadow="false">
|
||||
<button type="primary" @click="toTaizhang">人员台账</button>
|
||||
</uni-card>
|
||||
</uni-section>
|
||||
<uni-section title="统计信息" type="line">
|
||||
<uni-card :is-shadow="false">
|
||||
<button type="primary" @click="toTongji">年龄段统计</button>
|
||||
</uni-card>
|
||||
|
||||
<uni-card :is-shadow="false">
|
||||
<button type="primary" @click="toQtTongji">通用字段统计</button>
|
||||
</uni-card>
|
||||
</uni-section>
|
||||
</uni-card>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
function toTaizhang() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/views/renliziyuan/renyuanxinxi/taizhang'
|
||||
});
|
||||
}
|
||||
|
||||
function toTongji() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/views/renliziyuan/renyuanxinxi/tongji'
|
||||
});
|
||||
}
|
||||
|
||||
function toQtTongji() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/views/renliziyuan/renyuanxinxi/qttongji'
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
985
pages/views/renliziyuan/renyuanxinxi/qttongji.vue
Normal file
@ -0,0 +1,985 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="container" id="top1">
|
||||
<uni-row style="margin-bottom: 10px">
|
||||
<uni-col :span="5"><uni-title :title="'选择单位'" align="left" type="h4"></uni-title></uni-col>
|
||||
<uni-col :span="19">
|
||||
<trq-depart-select v-model="selectedOrgCode" returnCodeOrID="orgCode"
|
||||
@change="onOrgCodeChange"></trq-depart-select>
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
<uni-row style="margin-bottom: 10px">
|
||||
<uni-col :span="5"><uni-title :title="'选择字段'" align="left" type="h4"></uni-title></uni-col>
|
||||
<uni-col :span="12">
|
||||
<uni-data-select v-model="selectedField" :localdata="fieldList"
|
||||
@change="onFieldChange"></uni-data-select>
|
||||
</uni-col>
|
||||
<uni-col style="margin-left:5px" :span="6" v-if="selectedField==='zjmc'"><button type="primary"
|
||||
size="mini" @click="showPopup=!showPopup">筛选</button></uni-col>
|
||||
</uni-row>
|
||||
|
||||
</view>
|
||||
<!-- ECharts图表 -->
|
||||
<view class="chart-container">
|
||||
<l-echart ref="chart" @finished="initChart" />
|
||||
</view>
|
||||
<!-- 翻页按钮 -->
|
||||
<view style="display: flex; justify-content: center; margin-top: 10px">
|
||||
<button @click="prevPage" :disabled="currentPage === 1" size="mini">上一页</button>
|
||||
<button @click="nextPage" :disabled="currentPage * pageSize >= chartDataCount.value"
|
||||
size="mini">下一页</button>
|
||||
</view>
|
||||
<!-- 数据表格 -->
|
||||
<uni-row style="margin-top: 10px; margin-left: 20px; margin-right: 20px" v-if="personnelList.length > 0">
|
||||
<uni-col :span="2">
|
||||
<view class="titleStyle">序号</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="titleStyle">姓名</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="titleStyle">基层单位</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5" v-if="selectedField.value !== 'zjmc'">
|
||||
<view class="titleStyle">基层班组</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5" v-else>
|
||||
<view class="titleStyle">岗位</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="titleStyle">年龄</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="titleStyle">操作</view>
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
<scroll-view scroll-y :style="{ height: bottomHeight + 'px' }">
|
||||
<uni-row style="margin-bottom: 10px; margin-left: 20px; margin-right: 20px; font-size: 12px">
|
||||
<view v-for="(item, index) in personnelList">
|
||||
<uni-col :span="2">
|
||||
<view class="dataStyle">
|
||||
{{ index + 1 }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="dataStyle">
|
||||
{{ item.xm }}
|
||||
</view>
|
||||
</uni-col>
|
||||
|
||||
<uni-col :span="5">
|
||||
<view class="dataStyle1">
|
||||
{{ item.jcdw }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5" v-if="selectedField.value != 'zjmc'">
|
||||
<view class="dataStyle1">
|
||||
{{ item.jcxd }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4" v-else>
|
||||
<view class="dataStyle">
|
||||
{{ item.sdgw }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="dataStyle">
|
||||
{{ item.nl }}
|
||||
</view>
|
||||
</uni-col>
|
||||
|
||||
<uni-col :span="4">
|
||||
<view class="dataStyle">
|
||||
<span @click="detail(item)" style="color: red;">详情</span>
|
||||
<!-- <button size="mini" type="primary" @click="detail(item)">详情</button> -->
|
||||
</view>
|
||||
</uni-col>
|
||||
</view>
|
||||
</uni-row>
|
||||
</scroll-view>
|
||||
<uni-popup ref="showPopup" type="bottom" border-radius="10px 10px 0 0">
|
||||
<uni-card>
|
||||
<uni-title :title="'已选证书:'" align="left" type="h4"></uni-title>
|
||||
<view style="color: red;font-weight: 300;margin-bottom: 10px;">{{dictData}}</view>
|
||||
<scroll-view scroll-y style="height: 40vh;">
|
||||
<view>
|
||||
<cxc-szcx-dictSelect :dictCode="dictCode" @change="dictChange"></cxc-szcx-dictSelect>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</uni-card>
|
||||
</uni-popup>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
onMounted,
|
||||
computed
|
||||
} from 'vue';
|
||||
import * as echarts from 'echarts/dist/echarts.min'; // 引入ECharts的H5版本
|
||||
import {
|
||||
cxcRyDatAstatistics,
|
||||
cxcRyDatAstatisticsCertificate,
|
||||
cxcRyDatAstatisticsDetails
|
||||
} from '@/api/renyuan.js';
|
||||
|
||||
// 存储下方组件的高度 tableData
|
||||
const bottomHeight = ref(0);
|
||||
// 新增加载状态
|
||||
const chart = ref(null);
|
||||
const chartDataCount = ref(0);
|
||||
const fieldList = ref([{
|
||||
text: '取证情况',
|
||||
value: 'zjmc',
|
||||
isDict: false,
|
||||
dictCode: 'gzrlzy',
|
||||
},
|
||||
{
|
||||
text: '岗位类别',
|
||||
value: 'gwlb',
|
||||
isDict: false,
|
||||
dictCode: ''
|
||||
},
|
||||
{
|
||||
text: '性别',
|
||||
value: 'xb',
|
||||
isDict: true,
|
||||
dictCode: 'sex'
|
||||
},
|
||||
{
|
||||
text: '政治面貌',
|
||||
value: 'zzmm',
|
||||
isDict: true,
|
||||
dictCode: 'zzmm'
|
||||
},
|
||||
{
|
||||
text: '民族',
|
||||
value: 'mz',
|
||||
isDict: true,
|
||||
dictCode: 'mz'
|
||||
}
|
||||
]); // 字段列表
|
||||
|
||||
const dictCode = ref('');
|
||||
const dictData = ref('');
|
||||
const showPopup = ref(null);
|
||||
const fieldisDict = ref(true);
|
||||
|
||||
const selectedOrgCode = ref(''); // 当前选择的单位 orgCode
|
||||
const selectedOrgCodeLabel = ref('请选择单位'); // 当前选择的单位名称
|
||||
const selectedField = ref(''); // 当前选择的字段
|
||||
const selectedFieldLabel = ref('请选择字段'); // 当前选择的字段名称
|
||||
const orgCodeGroupData = ref([]); //按照orgcode进行分组的数据 含劳动合同号
|
||||
const chartData = ref({}); // 图表数据
|
||||
const personnelList = ref([]); // 人员列表 initChart
|
||||
const fieldValues = ref([]); //字段值
|
||||
const fieldTexts = ref([]); //字段值
|
||||
const chartOption = ref({});
|
||||
const orgType = ref(''); //记录单位层级 by 闵
|
||||
|
||||
const chartTitle = computed(() => {
|
||||
return selectedOrgCodeLabel.value + '人员(' + selectedFieldLabel.value + ')分组统计';
|
||||
});
|
||||
|
||||
//图标翻页
|
||||
const pageSize = ref(3); // 每页显示的项目数量
|
||||
const currentPage = ref(1); // 当前页码
|
||||
|
||||
function detail(record) {
|
||||
// console.log(record)
|
||||
uni.navigateTo({
|
||||
url: '/pages/views/renliziyuan/renyuanxinxi/detail?data=' + encodeURIComponent(JSON.stringify(record))
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
getHeight();
|
||||
|
||||
});
|
||||
|
||||
const dictChange = (e) => {
|
||||
console.log(e)
|
||||
dictData.value = e
|
||||
fetchStatisticsData()
|
||||
}
|
||||
|
||||
const getHeight = () => {
|
||||
// 获取屏幕高度
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
const screenHeight = systemInfo.screenHeight;
|
||||
// 创建选择器查询对象
|
||||
const query = uni.createSelectorQuery();
|
||||
// 获取上方组件的高度
|
||||
query
|
||||
.select('#top1')
|
||||
.boundingClientRect((rect1) => {
|
||||
// 计算上方组件高度总和
|
||||
const topComponentsHeight = rect1.height;
|
||||
// 计算下方组件的高度
|
||||
bottomHeight.value = screenHeight - topComponentsHeight - 415;
|
||||
})
|
||||
.exec();
|
||||
};
|
||||
|
||||
|
||||
// 初始化 ECharts length departChange
|
||||
// 初始化图表
|
||||
const initChart = () => {
|
||||
setTimeout(async () => {
|
||||
if (!chart.value) return;
|
||||
const myChart = await chart.value.init(echarts);
|
||||
myChart.setOption(chartOption.value);
|
||||
}, 300);
|
||||
};
|
||||
|
||||
const prevPage = () => {
|
||||
if (currentPage.value > 1) {
|
||||
currentPage.value--;
|
||||
}
|
||||
updateChart(chartData.value);
|
||||
};
|
||||
|
||||
const nextPage = () => {
|
||||
if (currentPage.value * pageSize.value < chartDataCount.value) {
|
||||
currentPage.value++;
|
||||
// 计算当前页数据的起始和结束索引
|
||||
const startIndex = (currentPage.value - 1) * pageSize.value;
|
||||
const endIndex = startIndex + pageSize.value;
|
||||
updateChart(chartData.value);
|
||||
// const tempChartData = temp.slice(startIndex, endIndex);
|
||||
}
|
||||
};
|
||||
// 更具数据生成图标的option
|
||||
const getChartOption = (ChartData) => {
|
||||
// let temp = JSON.parse(JSON.stringify(tempchartData[0].children));
|
||||
// chartDataCount.value = temp.length;
|
||||
// 计算当前页数据的起始和结束索引
|
||||
|
||||
const startIndex = (currentPage.value - 1) * pageSize.value;
|
||||
const endIndex = startIndex + pageSize.value;
|
||||
// 截取当前页的数据
|
||||
const tempChartData = ChartData.slice(startIndex, endIndex);
|
||||
try {
|
||||
let xData = [];
|
||||
let seriesData = [];
|
||||
console.log(1, tempChartData);
|
||||
//当前机构下的数据 transformDataForEcharts
|
||||
|
||||
let legendData = [];
|
||||
for (let i = 0; i < fieldValues.value.length; i++) {
|
||||
legendData.push(fieldValues.value[i].fieldText);
|
||||
}
|
||||
|
||||
tempChartData.forEach((item) => {
|
||||
xData.push(item.name);
|
||||
});
|
||||
|
||||
for (let i = 0; i < fieldValues.value.length; i++) {
|
||||
let tempData = [];
|
||||
tempChartData.forEach((item) => {
|
||||
// console.log(item);
|
||||
if (item.data[i]) {
|
||||
tempData.push(item.data[i]);
|
||||
} else {
|
||||
tempData.push(0);
|
||||
}
|
||||
});
|
||||
seriesData.push({
|
||||
name: fieldValues.value[i].fieldText,
|
||||
type: 'bar',
|
||||
label: {
|
||||
show: true, // 显示数值标签
|
||||
position: 'top' // 数值标签位置
|
||||
},
|
||||
data: tempData
|
||||
});
|
||||
}
|
||||
console.log(2, legendData, xData, seriesData);
|
||||
|
||||
let tempOption = {
|
||||
title: {
|
||||
text: chartTitle.value,
|
||||
padding: [0, 0, 0, 30]
|
||||
},
|
||||
toolbox: {
|
||||
padding: [0, 30, 0, 0],
|
||||
show: true,
|
||||
feature: {
|
||||
//工具配置项
|
||||
|
||||
restore: {
|
||||
show: true //是否显示该工具
|
||||
},
|
||||
saveAsImage: {
|
||||
show: true //是否显示该工具
|
||||
}
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xData,
|
||||
axisLabel: {
|
||||
color: '#7F84B5',
|
||||
fontWeight: 300,
|
||||
interval: 0,
|
||||
rotate: 0
|
||||
},
|
||||
padding: [0, 10, 0, 10],
|
||||
axisTick: {
|
||||
show: false //刻度线
|
||||
},
|
||||
axisLine: {
|
||||
show: false //不显示坐标轴线
|
||||
}
|
||||
},
|
||||
yAxis: [{
|
||||
show: true,
|
||||
boundaryGap: false, //解决数据与线不对应问题
|
||||
type: 'value',
|
||||
// name: 'Budget (million USD)',
|
||||
// data: this.yList,
|
||||
minInterval: 1,
|
||||
axisLabel: {
|
||||
interval: 0
|
||||
},
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
//背景网格线
|
||||
type: 'dashed'
|
||||
}
|
||||
},
|
||||
|
||||
axisTick: {
|
||||
show: true //刻度线
|
||||
},
|
||||
axisLine: {
|
||||
show: false //不显示坐标轴线
|
||||
}
|
||||
}],
|
||||
series: seriesData,
|
||||
|
||||
legend: {
|
||||
data: legendData,
|
||||
itemGap: 1,
|
||||
padding: [0, 0, 0, 0],
|
||||
y: 'bottom',
|
||||
itemHeight: 8, //高
|
||||
itemWidth: 18, //宽
|
||||
type: 'scroll'
|
||||
}
|
||||
};
|
||||
return tempOption;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
|
||||
// 更新图表
|
||||
const updateChart = (tempchartData) => {
|
||||
// 初始化图表
|
||||
setTimeout(async () => {
|
||||
if (!chart.value) return;
|
||||
const myChart = await chart.value.init(echarts);
|
||||
console.log(tempchartData);
|
||||
let tempOption = getChartOption(tempchartData);
|
||||
|
||||
myChart.setOption(tempOption);
|
||||
// 点击钻取事件
|
||||
myChart.on('click', (params) => {
|
||||
console.log(params.name, params.seriesIndex, params.dataIndex);
|
||||
console.log(orgCodeGroupData.value);
|
||||
|
||||
let updateData = findRyByOrgCode(orgCodeGroupData.value.children, params.name);
|
||||
console.log(updateData);
|
||||
|
||||
const ldhth = updateData.fieldValues[params.seriesIndex].ldhth;
|
||||
|
||||
console.log(ldhth);
|
||||
|
||||
if (ldhth && ldhth.length > 0) {
|
||||
fetchPersonnelList(ldhth);
|
||||
}
|
||||
// updateChart(updateData);
|
||||
});
|
||||
}, 300);
|
||||
};
|
||||
//根据一个键值查找数据
|
||||
//查找人员劳动合同号
|
||||
function findRyByOrgCode(treeData, targetOrgCode) {
|
||||
// console.log(treeData, targetOrgCode);
|
||||
for (const node of treeData) {
|
||||
// 如果当前节点匹配,直接返回该节点及其子节点
|
||||
if (node.orgText === targetOrgCode) {
|
||||
return node;
|
||||
}
|
||||
// 递归检查子节点
|
||||
if (node.children && node.children.length > 0) {
|
||||
const found = findNodeByOrgCode(node.children, targetOrgCode);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从echart图标的树状数据中根据 orgCode 获取节点及其子节点数据
|
||||
* @param {Array} treeData 树状数据
|
||||
* @param {string} targetOrgCode 目标 orgCode
|
||||
* @returns {Object|null} 匹配的节点及其子节点数据,未找到返回 null
|
||||
*/
|
||||
function findNodeByOrgCode(treeData, targetOrgCode) {
|
||||
// console.log(treeData, targetOrgCode);
|
||||
for (const node of treeData) {
|
||||
// 如果当前节点匹配,直接返回该节点及其子节点
|
||||
if (node.name === targetOrgCode) {
|
||||
return node;
|
||||
}
|
||||
// 递归检查子节点
|
||||
if (node.children && node.children.length > 0) {
|
||||
const found = findNodeByOrgCode(node.children, targetOrgCode);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//获取所有的fieldValue
|
||||
function collectUniqueKeyFieldValues(tree) {
|
||||
const uniqueMap = new Map();
|
||||
tree.forEach((item) => {
|
||||
const {
|
||||
fieldValue,
|
||||
fieldText
|
||||
} = item;
|
||||
const key = `${fieldValue}-${fieldText}`;
|
||||
|
||||
if (!uniqueMap.has(key)) {
|
||||
uniqueMap.set(key, {
|
||||
fieldValue,
|
||||
fieldText
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const result = Array.from(uniqueMap.values());
|
||||
return result;
|
||||
}
|
||||
|
||||
// 封装一个类来管理组织代码和组织名称的映射
|
||||
class OrgCodeMapper {
|
||||
constructor(data) {
|
||||
// 初始化一个空对象用于存储映射关系
|
||||
this.orgCodeToOrgTextMap = {};
|
||||
// 遍历传入的数据数组
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const item = data[i];
|
||||
// 将 orgCode 作为键,orgText 作为值存入映射对象
|
||||
this.orgCodeToOrgTextMap[item.orgCode] = item.orgText;
|
||||
}
|
||||
}
|
||||
|
||||
// 查找指定 orgCode 对应的 orgText 的方法
|
||||
findOrgText(orgCode) {
|
||||
return this.orgCodeToOrgTextMap[orgCode];
|
||||
}
|
||||
}
|
||||
|
||||
// 示例用法
|
||||
// const result = findNodeByOrgCode(echartData, "A01A01A01A01");
|
||||
// console.log(result);
|
||||
/**
|
||||
* 转换数据为支持钻取的ECharts格式
|
||||
* @param {Array} data 原始数据
|
||||
* @param {string} selectOrgCode 当前选择的组织编码
|
||||
* @returns {Object} 包含当前层级数据和子节点信息的对象 符合echart的格式
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
function transformData(selectOrgCode, data) {
|
||||
const nodes = new Map();
|
||||
//获取所有的fieldValue 用于图例和钻取和data[]中的数据顺序保持一致 动态建立fieldValue的数据
|
||||
fieldValues.value = collectUniqueKeyFieldValues(data);
|
||||
// console.log(fieldValues.value);
|
||||
const orgMapper = new OrgCodeMapper(data); //用于快速查找orgtext
|
||||
// console.log(orgMapper.findOrgText('A01A01A01A01'));
|
||||
// 获取orgCode的所有层级
|
||||
function getHierarchy(orgCode) {
|
||||
const hierarchy = [];
|
||||
for (let i = selectOrgCode.length; i <= orgCode.length; i += 3) {
|
||||
hierarchy.push(orgCode.substring(0, i));
|
||||
}
|
||||
// console.log('hierarchy', hierarchy);
|
||||
return hierarchy;
|
||||
}
|
||||
// 获取父级orgCode
|
||||
function getParentCode(code) {
|
||||
if (code.length <= 3) return null;
|
||||
return code.substring(0, code.length - 3);
|
||||
}
|
||||
// 动态赋值series的数据长度
|
||||
let tempArrayValue = new Array(fieldValues.value.length).fill(0);
|
||||
// 创建所有节点并建立父子关系
|
||||
data.forEach((entry) => {
|
||||
const hierarchy = getHierarchy(entry.orgCode);
|
||||
// console.log(entry);
|
||||
hierarchy.forEach((code) => {
|
||||
// console.log(code);
|
||||
let tempOrgText = orgMapper.findOrgText(code) === undefined ? '' : orgMapper.findOrgText(
|
||||
code);
|
||||
// console.log(tempOrgText);
|
||||
if (!nodes.has(code)) {
|
||||
nodes.set(code, {
|
||||
orgCode: code,
|
||||
name: tempOrgText,
|
||||
type: 'bar',
|
||||
data: JSON.parse(JSON.stringify(tempArrayValue)), // 初始化data为[0, 0] 动态
|
||||
children: []
|
||||
});
|
||||
}
|
||||
});
|
||||
// console.log(nodes);
|
||||
// console.log('fieldValues', fieldValues.value, fieldValues.value.length, hierarchy);
|
||||
|
||||
// 更新当前节点的data
|
||||
const node = nodes.get(entry.orgCode);
|
||||
const fieldValue = entry.fieldValue;
|
||||
|
||||
for (let i = 0; i < fieldValues.value.length; i++) {
|
||||
if (fieldValue === fieldValues.value[i].fieldValue) {
|
||||
// console.log(555, i, fieldValue, fieldValues.value[i], entry.number);
|
||||
node.data[i] += entry.number;
|
||||
}
|
||||
}
|
||||
|
||||
// console.log(11, node);
|
||||
|
||||
// 建立父子关系
|
||||
for (let i = 0; i < hierarchy.length - 1; i++) {
|
||||
const parentCode = hierarchy[i];
|
||||
const childCode = hierarchy[i + 1];
|
||||
const parentNode = nodes.get(parentCode);
|
||||
const childNode = nodes.get(childCode);
|
||||
if (!parentNode.children.some((c) => c.orgCode === childCode)) {
|
||||
parentNode.children.push(childNode);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 计算非叶子节点的data(子节点之和)
|
||||
function computeData(node) {
|
||||
if (node.children.length === 0) return;
|
||||
node.data = JSON.parse(JSON.stringify(tempArrayValue));
|
||||
node.children.forEach((child) => {
|
||||
computeData(child);
|
||||
for (let i = 0; i < fieldValues.value.length; i++) {
|
||||
// console.log(666, i, node.data[i], child.data[i]);
|
||||
node.data[i] += child.data[i];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 获取所有根节点(没有父节点或父节点不存在)
|
||||
const rootNodes = [];
|
||||
nodes.forEach((node, code) => {
|
||||
const parentCode = getParentCode(code);
|
||||
// console.log(parentCode);
|
||||
if (!parentCode || !nodes.has(parentCode)) {
|
||||
rootNodes.push(node);
|
||||
}
|
||||
});
|
||||
|
||||
// 递归计算每个根节点的data
|
||||
rootNodes.forEach((root) => computeData(root));
|
||||
|
||||
console.log(rootNodes)
|
||||
return rootNodes;
|
||||
// console.log('rootNodes', rootNodes);
|
||||
// // 转换为目标格式
|
||||
// function formatTree(node) {
|
||||
// // console.log(node);
|
||||
// return {
|
||||
// orgCode: node.orgCode,
|
||||
// name: node.name,
|
||||
// type: 'bar',
|
||||
// data: node.data,
|
||||
// children: node.children.map((child) => formatTree(child))
|
||||
// };
|
||||
// }
|
||||
|
||||
// return rootNodes.map((root) => {
|
||||
// console.log(root);
|
||||
// formatTree(root);
|
||||
// });
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
|
||||
//根据 orgCode 的分级格式,递归地汇总本级及其所有下级的数据,并将下级数据放在本级的 children 属性中。 deepseek
|
||||
|
||||
const groupByOrgCode = (orgCode, data) => {
|
||||
// 过滤出本级和所有下级的数据
|
||||
console.log("aaaa")
|
||||
const filteredData = data.filter((item) => item.orgCode.startsWith(orgCode));
|
||||
const orgMapper = new OrgCodeMapper(data);
|
||||
// 如果过滤后的数据为空,返回 null
|
||||
if (filteredData.length === 0) {
|
||||
uni.showToast({
|
||||
title: '过滤后数据为空',
|
||||
duration: 1000
|
||||
});
|
||||
return null;
|
||||
}
|
||||
// console.log(0, filteredData);
|
||||
// 按照 fieldValue 分组
|
||||
const groupedByFieldValue = {};
|
||||
try {
|
||||
filteredData.forEach((item) => {
|
||||
// console.log(item);
|
||||
if (!groupedByFieldValue[item.fieldValue]) {
|
||||
groupedByFieldValue[item.fieldValue] = {
|
||||
orgCode: item.orgCode,
|
||||
orgText: item.orgText,
|
||||
fieldText: item.fieldText,
|
||||
number: 0,
|
||||
ldhth: []
|
||||
};
|
||||
}
|
||||
// console.log(item.orgCode, 22, groupedByFieldValue[item.fieldValue]);
|
||||
groupedByFieldValue[item.fieldValue].number += item.number;
|
||||
groupedByFieldValue[item.fieldValue].ldhth.push(...item.ldhth.split(','));
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
// console.log(1, orgMapper.findOrgText(orgCode));
|
||||
// 构建本级结果
|
||||
console.log("aaaa")
|
||||
const result = {
|
||||
orgCode: orgCode,
|
||||
orgText: orgMapper.findOrgText(orgCode),
|
||||
fieldValues: Object.keys(groupedByFieldValue).map((fieldValue) => {
|
||||
const {
|
||||
fieldText,
|
||||
orgCode,
|
||||
orgText
|
||||
} = groupedByFieldValue[fieldValue] || {};
|
||||
return {
|
||||
fieldValue: fieldValue,
|
||||
fieldText: fieldText,
|
||||
orgCode: orgCode,
|
||||
orgText: orgText,
|
||||
number: groupedByFieldValue[fieldValue].number,
|
||||
ldhth: [...new Set(groupedByFieldValue[fieldValue].ldhth)] // 去重
|
||||
};
|
||||
}),
|
||||
children: []
|
||||
};
|
||||
|
||||
// console.log('本级', result);
|
||||
|
||||
// 获取所有下一级的 orgCode
|
||||
const nextLevelOrgCodes = new Set();
|
||||
try {
|
||||
filteredData.forEach((item) => {
|
||||
if (item.orgCode !== orgCode && item.orgCode.startsWith(orgCode)) {
|
||||
const nextLevelOrgCode = item.orgCode.substring(0, orgCode.length + 3);
|
||||
nextLevelOrgCodes.add(nextLevelOrgCode);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
// 递归处理下一级数据
|
||||
try {
|
||||
nextLevelOrgCodes.forEach((nextLevelOrgCode) => {
|
||||
const child = groupByOrgCode(nextLevelOrgCode, data);
|
||||
if (child) {
|
||||
result.children.push(child);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
console.log('全部', result);
|
||||
|
||||
return result;
|
||||
};
|
||||
// 获取统计数据 then filter
|
||||
const fetchStatisticsData = async () => {
|
||||
console.log(selectedOrgCode)
|
||||
if (!selectedOrgCode.value || !selectedField.value) return;
|
||||
let res = [];
|
||||
chartData.value = [];
|
||||
try {
|
||||
//这里添加一个层级字段,并避免 厂机关A01A01A01 orgType by 闵
|
||||
var tempOrgType = '1';
|
||||
if(selectedOrgCode.value.includes('A01A01A01')){
|
||||
tempOrgType = '1';
|
||||
}else{
|
||||
tempOrgType = orgType
|
||||
}
|
||||
if (selectedField.value === 'zjmc') {
|
||||
console.log(dictCode.value);
|
||||
console.log(dictData.value);
|
||||
res = await cxcRyDatAstatisticsCertificate({
|
||||
orgCode: selectedOrgCode.value,
|
||||
field: selectedField.value,
|
||||
dictCode: dictCode.value,
|
||||
fieldisDict: fieldisDict.value,
|
||||
typeOfWorkList: dictData.value,
|
||||
orgType: tempOrgType.value
|
||||
});
|
||||
} else {
|
||||
res = await cxcRyDatAstatistics({
|
||||
orgCode: selectedOrgCode.value,
|
||||
field: selectedField.value,
|
||||
dictCode: dictCode.value,
|
||||
fieldisDict: fieldisDict.value,
|
||||
orgType: tempOrgType.value
|
||||
});
|
||||
}
|
||||
|
||||
// console.log(res); //deepseek
|
||||
if (res.success) {
|
||||
console.log(selectedOrgCode.value, res);
|
||||
if (res.result.length < 1) {
|
||||
uni.showToast({
|
||||
title: '查询数据为空'
|
||||
});
|
||||
return;
|
||||
}
|
||||
//按单位进行分组
|
||||
orgCodeGroupData.value = groupByOrgCode(selectedOrgCode.value, res.result);
|
||||
console.log(orgCodeGroupData.value);
|
||||
//将数据转换成echart格式
|
||||
const temp = transformData(selectedOrgCode.value, res.result);
|
||||
|
||||
if (temp[0].children.length > 0) {
|
||||
chartData.value = JSON.parse(JSON.stringify(temp[0].children));
|
||||
|
||||
chartDataCount.value = chartData.value.length;
|
||||
console.log(chartData.value);
|
||||
// updateChart(chartData.value);
|
||||
} else {
|
||||
var tempArr = [];
|
||||
tempArr.push(temp[0])
|
||||
chartData.value =tempArr;
|
||||
}
|
||||
updateChart(chartData.value);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取统计数据失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 获取人员列表 delimiter
|
||||
const fetchPersonnelList = async (ldhthList) => {
|
||||
personnelList.value = [];
|
||||
try {
|
||||
const res = await cxcRyDatAstatisticsDetails({
|
||||
ldhth: ldhthList
|
||||
});
|
||||
console.log(res);
|
||||
if (res.success) {
|
||||
personnelList.value = res.result;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取人员列表失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 事件处理
|
||||
const onOrgCodeChange = (e, data) => {
|
||||
personnelList.value = [];
|
||||
selectedOrgCode.value = e;
|
||||
console.log(e)
|
||||
console.log(data);
|
||||
orgType.value = data.value.orgType; //赋值层级 by 闵
|
||||
selectedOrgCodeLabel.value = data.value.title;
|
||||
fetchStatisticsData();
|
||||
};
|
||||
|
||||
const onFieldChange = (e) => {
|
||||
|
||||
personnelList.value = [];
|
||||
// console.log(e);
|
||||
try {
|
||||
selectedField.value = e;
|
||||
for (var index = 0; index < fieldList.value.length; index++) {
|
||||
var element = fieldList.value[index];
|
||||
// console.log(element);
|
||||
if (element.value === e) {
|
||||
selectedFieldLabel.value = element.text;
|
||||
dictCode.value = element.dictCode;
|
||||
fieldisDict.value = element.isDict;
|
||||
}
|
||||
|
||||
}
|
||||
if (selectedField.value === 'zjmc') {
|
||||
showPopup.value.open()
|
||||
} else {
|
||||
fetchStatisticsData();
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
//TODO handle the exception
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
|
||||
const onChartClick = (e) => {
|
||||
personnelList.value = [];
|
||||
const {
|
||||
ldhth
|
||||
} = chartData.value;
|
||||
if (ldhth && ldhth.length > 0) {
|
||||
fetchPersonnelList(ldhth);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
/* 颜色变量 */
|
||||
:root {
|
||||
--primary-blue: #409eff;
|
||||
--deep-blue: #2c7be5;
|
||||
--light-blue: #ecf5ff;
|
||||
--gradient-start: #6b8cff;
|
||||
--gradient-end: #4364f7;
|
||||
--hover-blue: #66b1ff;
|
||||
}
|
||||
|
||||
/* 全局容器 */
|
||||
.container {
|
||||
margin: 10px 10px;
|
||||
padding: 10px;
|
||||
background: linear-gradient(145deg, #f5f9ff, var(--light-blue));
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.15);
|
||||
border: 1px solid rgba(64, 158, 255, 0.1);
|
||||
}
|
||||
|
||||
/* 图表容器 */
|
||||
.chart-container {
|
||||
height: 250px;
|
||||
margin: 10px 0;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 4px 16px rgba(64, 158, 255, 0.12);
|
||||
border: 1px solid rgba(64, 158, 255, 0.08);
|
||||
}
|
||||
|
||||
/* 表格标题行 */
|
||||
|
||||
.titleStyle {
|
||||
font-size: 10px;
|
||||
color: #747474;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
background: #f2f9fc;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border-left: 1px solid #919191;
|
||||
border-bottom: 1px solid #919191;
|
||||
}
|
||||
|
||||
/* 内容样式 */
|
||||
.dataStyle {
|
||||
font-size: 10px;
|
||||
color: #00007f;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border-bottom: 1px solid #919191;
|
||||
border-left: 1px solid #919191;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* 内容样式 */
|
||||
.dataStyle1 {
|
||||
font-size: 8px;
|
||||
color: #00007f;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border-bottom: 1px solid #919191;
|
||||
border-left: 1px solid #919191;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* 滚动区域 */
|
||||
scroll-view {
|
||||
background: #ffffff;
|
||||
border-radius: 0 0 8px 8px;
|
||||
box-shadow: 0 4px 12px rgba(0, 35, 111, 0.08);
|
||||
}
|
||||
|
||||
/* 输入框聚焦效果 */
|
||||
.trq-depart-select:focus-within {
|
||||
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
|
||||
border-color: var(--primary-blue);
|
||||
}
|
||||
|
||||
/* 加载动画优化 */
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.container>* {
|
||||
animation: fadeIn 0.6s cubic-bezier(0.23, 1, 0.32, 1);
|
||||
}
|
||||
|
||||
/* 自定义滚动条美化 */
|
||||
::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
background: rgba(64, 158, 255, 0.05);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: linear-gradient(45deg, var(--primary-blue), var(--deep-blue));
|
||||
border-radius: 6px;
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
||||
/* 筛选行间距优化 */
|
||||
.filter-row {
|
||||
margin: 15px 0;
|
||||
padding: 10px 0;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* 响应式调整优化 */
|
||||
@media (max-width: 768px) {
|
||||
.chart-container {
|
||||
height: 250px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 数据行高亮效果 */
|
||||
.data-row:nth-child(even) {
|
||||
background: rgba(236, 245, 255, 0.3);
|
||||
}
|
||||
|
||||
.data-row:hover {
|
||||
box-shadow: 0 4rpx 12rpx rgba(64, 158, 255, 0.1);
|
||||
}
|
||||
</style>
|
||||
317
pages/views/renliziyuan/renyuanxinxi/taizhang.vue
Normal file
@ -0,0 +1,317 @@
|
||||
<template>
|
||||
<view class="container" id="top1">
|
||||
<uni-card>
|
||||
<view>
|
||||
<uni-row>
|
||||
<uni-col :span="11"><uni-title title="姓名 " align="left" type="h5"></uni-title></uni-col>
|
||||
<uni-col :span="11" :push="2"><uni-title title="劳动合同号" align="left" type="h5"></uni-title></uni-col>
|
||||
</uni-row>
|
||||
<uni-row>
|
||||
<uni-col :span="11"><uni-easyinput v-model="xm" suffixIcon="search" clearable placeholder="姓名模糊查询"
|
||||
@change="Search" @iconClick="Search" /></uni-col>
|
||||
<uni-col :span="11" :push="2">
|
||||
<uni-easyinput v-model="ldhth" suffixIcon="search" clearable placeholder="劳动合同号模糊查询"
|
||||
@change="Search" @iconClick="Search" />
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
</view>
|
||||
<view style="margin-bottom: 10rpx">
|
||||
<uni-row>
|
||||
<uni-col :span="24"><uni-title title="所属单位" align="left" type="h5"></uni-title></uni-col>
|
||||
</uni-row>
|
||||
<uni-row>
|
||||
<uni-col :span="24">
|
||||
<trq-depart-select v-model="departID" returnCodeOrID="orgCode"
|
||||
@change="departChange"></trq-depart-select>
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
</view>
|
||||
</uni-card>
|
||||
</view>
|
||||
<uni-card>
|
||||
<!-- 数据表格 -->
|
||||
|
||||
<uni-row>
|
||||
<uni-col :span="3">
|
||||
<view class="titleStyle">序号</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="titleStyle">姓名</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="titleStyle">性别</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="titleStyle">年龄</view>
|
||||
</uni-col>
|
||||
<uni-col :span="6">
|
||||
<view class="titleStyle">操作</view>
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
|
||||
<scroll-view scroll-y :style="{ height: bottomHeight + 'px' }">
|
||||
<uni-row v-if="ryDataList.length > 0">
|
||||
<view v-for="(item, index) in ryDataList">
|
||||
<uni-col :span="3">
|
||||
<view class="dataStyle">
|
||||
{{ index + 1 }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="dataStyle">
|
||||
{{ item.xm }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="dataStyle">
|
||||
{{ item.xb_dictText }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="dataStyle">
|
||||
{{ item.nl }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="6">
|
||||
<view class="dataStyle">
|
||||
<span @click="detail(item)" style="color: red;">详情</span>
|
||||
<!-- <button size="mini" type="primary" @click="detail(item)">详情</button> -->
|
||||
</view>
|
||||
</uni-col>
|
||||
</view>
|
||||
</uni-row>
|
||||
|
||||
<view class="pagination">
|
||||
<uni-pagination :current="current" :pagerCount="5" :total="total" prev-text="前一页" next-text="后一页"
|
||||
:show-icon="false" @change="pagechange" />
|
||||
</view>
|
||||
</scroll-view>
|
||||
</uni-card>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
onReady,
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
reactive,
|
||||
ref,
|
||||
onMounted
|
||||
} from 'vue';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
import {
|
||||
queryDepByCode,
|
||||
queryZbDepByLdhth
|
||||
} from '@/api/depart.js';
|
||||
import {
|
||||
queryRenyuanByDepartID
|
||||
} from '@/api/renyuan.js';
|
||||
let xm = ref('');
|
||||
let ldhth = ref('');
|
||||
let departID = ref(''); //部门树选中的ID
|
||||
const ryDataList = ref([]);
|
||||
|
||||
const bottomHeight = ref(0);
|
||||
let status = ref('');
|
||||
let contentText = reactive({
|
||||
contentdown: '点击查看更多',
|
||||
contentrefresh: '加载中',
|
||||
contentnomore: '没有更多'
|
||||
});
|
||||
|
||||
let pageNo = ref(1);
|
||||
let pageSize = ref(10);
|
||||
let total = ref(0);
|
||||
let pages = ref(0);
|
||||
let current = ref(0);
|
||||
let params = reactive({
|
||||
pageNo: pageNo,
|
||||
pageSize: pageSize
|
||||
});
|
||||
|
||||
onLoad((e) => {});
|
||||
onMounted((e) => {
|
||||
|
||||
getHeight();
|
||||
departID.value = '';
|
||||
getRenyuanByDepID();
|
||||
});
|
||||
const getHeight = () => {
|
||||
// 获取屏幕高度
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
const screenHeight = systemInfo.screenHeight;
|
||||
// 创建选择器查询对象
|
||||
const query = uni.createSelectorQuery();
|
||||
// 获取上方组件的高度
|
||||
query
|
||||
.select('#top1')
|
||||
.boundingClientRect((rect1) => {
|
||||
// 计算上方组件高度总和
|
||||
const topComponentsHeight = rect1.height;
|
||||
// 计算下方组件的高度
|
||||
bottomHeight.value = screenHeight - topComponentsHeight;
|
||||
})
|
||||
.exec();
|
||||
};
|
||||
|
||||
|
||||
function detail(record) {
|
||||
// console.log(record)
|
||||
uni.navigateTo({
|
||||
url: '/pages/views/renliziyuan/renyuanxinxi/detail?data=' + encodeURIComponent(JSON.stringify(record))
|
||||
});
|
||||
}
|
||||
|
||||
function pagechange(e) {
|
||||
current.value = e.current;
|
||||
pageNo.value = e.current;
|
||||
let params = {
|
||||
pageNo: pageNo.value,
|
||||
pageSize: pageSize.value,
|
||||
current: current.value
|
||||
};
|
||||
if (departID.value.length <= 9) {
|
||||
params.orgCode = departID.value;
|
||||
} else {
|
||||
params.jcxd_code = departID.value;
|
||||
}
|
||||
|
||||
getRenyuanByDepID(params);
|
||||
}
|
||||
|
||||
function departChange(e, data) {
|
||||
departID.value = e;
|
||||
let params = {
|
||||
pageNo: pageNo.value,
|
||||
pageSize: pageSize.value,
|
||||
current: current.value
|
||||
};
|
||||
console.log(e);
|
||||
if (e.length <= 9) {
|
||||
params.orgCode = departID.value;
|
||||
} else {
|
||||
params.jcxd_code = departID.value;
|
||||
}
|
||||
|
||||
getRenyuanByDepID(params);
|
||||
|
||||
}
|
||||
|
||||
function getRenyuanByDepID(queryParm) {
|
||||
// ryDataList.value = [];
|
||||
console.log(queryParm);
|
||||
if (departID.value.length <= 6) {
|
||||
console.log(123242353);
|
||||
uni.showToast({
|
||||
title: '全厂数据较多,请选 下一层级...',
|
||||
icon: 'none',
|
||||
duration: 1000
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
if (queryParm) {
|
||||
queryRenyuanByDepartID(queryParm)
|
||||
.then((res) => {
|
||||
console.log(res);
|
||||
if (res.success) {
|
||||
ryDataList.value = res.result.records;
|
||||
total.value = res.result.total;
|
||||
pages.value = res.result.pages;
|
||||
current.value = res.result.current;
|
||||
}
|
||||
getHeight();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function Search() {
|
||||
ryDataList.value = [];
|
||||
let queryParm = {
|
||||
pageNo: pageNo.value,
|
||||
pageSize: pageSize.value
|
||||
};
|
||||
if ((ldhth.value == '') & (xm.value == '')) {
|
||||
return;
|
||||
}
|
||||
if (xm.value !== '') {
|
||||
queryParm.xm = '*' + xm.value + '*';
|
||||
}
|
||||
if (ldhth.value !== '') {
|
||||
queryParm.ldhth = '*' + ldhth.value + '*';
|
||||
}
|
||||
console.log(queryParm);
|
||||
queryRenyuanByDepartID(queryParm)
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
ryDataList.value = res.result.records;
|
||||
total.value = res.result.total;
|
||||
pages.value = res.result.pages;
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 全局容器 */
|
||||
.container {
|
||||
/* margin: 10rpx 10rpx; */
|
||||
/* padding: 10rpx; */
|
||||
background: linear-gradient(145deg, #ffaaff, var(--light-blue));
|
||||
border-radius: 24rpx;
|
||||
box-shadow: 0 8rpx 24rpx rgba(64, 158, 255, 0.15);
|
||||
border: 2rpx solid rgba(64, 158, 255, 0.1);
|
||||
}
|
||||
|
||||
.uni-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.titleStyle {
|
||||
font-size: 12px;
|
||||
color: #747474;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
background: #f2f9fc;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border-left: 1px solid #919191;
|
||||
border-bottom: 1px solid #919191;
|
||||
}
|
||||
|
||||
/* 内容样式 */
|
||||
.dataStyle {
|
||||
font-size: 12px;
|
||||
color: #00007f;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border-bottom: 1px solid #919191;
|
||||
border-left: 1px solid #919191;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* 内容样式 */
|
||||
.pagination {
|
||||
font-size: 16px;
|
||||
color: #00007f;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
</style>
|
||||
535
pages/views/renliziyuan/renyuanxinxi/tongji.vue
Normal file
@ -0,0 +1,535 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="container" id="top1">
|
||||
<uni-row style="margin-bottom: 10rpx; margin-left: 30rpx; margin-right: 30rpx">
|
||||
<uni-col :span="24"><uni-title :title="'所选单位'" align="left" type="h4"></uni-title></uni-col>
|
||||
</uni-row>
|
||||
<uni-row style="margin-bottom: 20rpx; margin-left: 30rpx; margin-right: 30rpx">
|
||||
<uni-col :span="24">
|
||||
<trq-depart-select v-model="orgCode" returnCodeOrID="orgCode" @change="departChange"></trq-depart-select>
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
<!-- 概览统计 -->
|
||||
<view class="stats-box" v-if="summary.total">
|
||||
<view class="stat-item">
|
||||
<text class="label">总人数</text>
|
||||
<text class="value">{{ summary.total }}</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<text class="label">平均年龄</text>
|
||||
<text class="value">{{ summary.avgAge.toFixed(1) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- ECharts图表 -->
|
||||
<view class="chart-container">
|
||||
<l-echart ref="chart" @finished="initChart" />
|
||||
</view>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
|
||||
<uni-row style="margin-top: 10px; margin-left: 30rpx; margin-right: 30rpx" v-if="tableData.length > 0">
|
||||
<uni-col :span="3">
|
||||
<view class="titleStyle">序号</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="titleStyle">姓名</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="titleStyle">性别</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="titleStyle">年龄</view>
|
||||
</uni-col>
|
||||
<uni-col :span="6">
|
||||
<view class="titleStyle">操作</view>
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
|
||||
<scroll-view scroll-y :style="{ height: bottomHeight + 'px' }">
|
||||
<uni-row style="margin-bottom: 10rpx; margin-left: 30rpx; margin-right: 30rpx">
|
||||
<view v-for="(item, index) in tableData">
|
||||
<uni-col :span="3">
|
||||
<view class="dataStyle">
|
||||
{{ index + 1 }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="dataStyle">
|
||||
{{ item.xm }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="dataStyle">
|
||||
{{ item.xb_dictText }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="5">
|
||||
<view class="dataStyle">
|
||||
{{ item.nl }}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="6">
|
||||
<view class="dataStyle">
|
||||
<span @click="detail(item)" style="color: red">详情</span>
|
||||
<!-- <button size="mini" type="primary" @click="detail(item)">详情</button> -->
|
||||
</view>
|
||||
</uni-col>
|
||||
</view>
|
||||
</uni-row>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
import { queryRenyuanByDepartID } from '@/api/renyuan.js';
|
||||
|
||||
// 存储下方组件的高度
|
||||
const bottomHeight = ref(0);
|
||||
// 新增加载状态
|
||||
const isLoading = ref(false);
|
||||
const orgCode = ref('');
|
||||
const rawData = ref([]);
|
||||
const tableData = ref([]);
|
||||
const summary = reactive({
|
||||
total: 0,
|
||||
avgAge: 0
|
||||
});
|
||||
const chart = ref(null);
|
||||
const chartOption = ref({});
|
||||
const drillPopup = ref(null);
|
||||
const drillList = ref([]);
|
||||
const drillTitle = ref('');
|
||||
|
||||
function detail(record) {
|
||||
// console.log(record)
|
||||
uni.navigateTo({
|
||||
url: '/pages/views/renliziyuan/renyuanxinxi/detail?data=' + encodeURIComponent(JSON.stringify(record))
|
||||
});
|
||||
}
|
||||
// 计算年龄
|
||||
const calculateAge = (birthDate) => {
|
||||
const today = new Date();
|
||||
const birth = new Date(birthDate);
|
||||
let age = today.getFullYear() - birth.getFullYear();
|
||||
const monthDiff = today.getMonth() - birth.getMonth();
|
||||
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) {
|
||||
age--;
|
||||
}
|
||||
return age;
|
||||
};
|
||||
// 加载数据
|
||||
const departChange = async (e, data) => {
|
||||
tableData.value = [];
|
||||
console.log(e);
|
||||
orgCode.value = e;
|
||||
try {
|
||||
// 显示加载状态
|
||||
|
||||
isLoading.value = true;
|
||||
if (orgCode.value.length <= 6) {
|
||||
console.log(123242353);
|
||||
uni.showToast({
|
||||
title: '全厂数据较多,请选 下一层级...',
|
||||
icon: 'none',
|
||||
duration: 1000
|
||||
});
|
||||
isLoading.value = false;
|
||||
return;
|
||||
} else {
|
||||
uni.showLoading({
|
||||
title: '数据加载中...',
|
||||
mask: true
|
||||
});
|
||||
}
|
||||
|
||||
let params = {
|
||||
pageSize: 3000,
|
||||
fields: ['xm', 'nl', 'xb', 'xb_dictText', 'orgCode', 'jcdw', 'jcxd', 'jcxdCode']
|
||||
};
|
||||
if (orgCode.value.length <= 9) {
|
||||
params.orgCode = orgCode.value;
|
||||
} else {
|
||||
params.jcxd_code = orgCode.value;
|
||||
}
|
||||
queryRenyuanByDepartID(params)
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
processData(res.result.records);
|
||||
|
||||
// 隐藏加载状态
|
||||
isLoading.value = false;
|
||||
uni.hideLoading();
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
uni.showToast({
|
||||
title: '数据加载失败',
|
||||
icon: 'none',
|
||||
duration: 1000
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
uni.showToast({
|
||||
title: '数据加载失败',
|
||||
icon: 'none',
|
||||
duration: 1000
|
||||
});
|
||||
} finally {
|
||||
// 隐藏加载状态
|
||||
isLoading.value = false;
|
||||
uni.hideLoading();
|
||||
}
|
||||
};
|
||||
|
||||
// 数据处理
|
||||
const processData = (data) => {
|
||||
// 添加年龄字段并过滤有效数据
|
||||
const validData = data
|
||||
.map((item) => ({
|
||||
...item,
|
||||
nl: calculateAge(item.cssj)
|
||||
}))
|
||||
.filter((item) => item.nl >= 21 && item.nl <= 64);
|
||||
// 计算概览数据
|
||||
summary.total = validData.length;
|
||||
summary.avgAge = validData.reduce((sum, cur) => sum + cur.nl, 0) / summary.total || 0;
|
||||
// 生成表格数据
|
||||
// tableData.value = validData;
|
||||
|
||||
groupsData(validData);
|
||||
// 生成图表数据
|
||||
generateChartData(validData);
|
||||
};
|
||||
|
||||
// 计算统计信息...
|
||||
const subOrgStaffs = ref({}); // 按下级单位存储所有人员
|
||||
const ageGroupStaffs = ref({}); // 按年龄段存储所有人员
|
||||
|
||||
const groupsData = (data) => {
|
||||
// 清空旧数据
|
||||
subOrgStaffs.value = {};
|
||||
ageGroupStaffs.value = {};
|
||||
data.reduce((acc, cur) => {
|
||||
// console.log(cur)
|
||||
let subOrg = '';
|
||||
let ageRange = getAgeRange(cur.nl);
|
||||
// console.log(cur.orgCode, cur.jcxdCode)
|
||||
if (cur.orgCode <= 6) {
|
||||
subOrg = cur.orgCode;
|
||||
} else {
|
||||
subOrg = cur.jcxdCode;
|
||||
}
|
||||
|
||||
// 存储到subOrgStaffs
|
||||
if (!subOrgStaffs.value[subOrg]) {
|
||||
subOrgStaffs.value[subOrg] = [];
|
||||
}
|
||||
subOrgStaffs.value[subOrg].push(cur);
|
||||
|
||||
// 存储到ageGroupStaffs
|
||||
if (!ageGroupStaffs.value[ageRange]) {
|
||||
ageGroupStaffs.value[ageRange] = [];
|
||||
}
|
||||
ageGroupStaffs.value[ageRange].push(cur);
|
||||
});
|
||||
};
|
||||
|
||||
// 新增年龄范围计算方法
|
||||
const getAgeRange = (age) => {
|
||||
const ranges = ['21-30岁', '31-40岁', '41-50岁', '51-60岁', '61-64岁'];
|
||||
const index = Math.floor((age - 21) / 10);
|
||||
return ranges[index] || '其他';
|
||||
};
|
||||
|
||||
// 修改后的显示人员列表方法
|
||||
const showStaffList = (subOrg, ageRange) => {
|
||||
// 从结构化数据中直接获取
|
||||
const targetStaffs = subOrgStaffs.value[subOrg].filter((staff) => getAgeRange(staff.nl) === ageRange);
|
||||
|
||||
staffList.value = targetStaffs;
|
||||
popupTitle.value = `${subOrg} ${ageRange}人员列表(共${targetStaffs.length}人)`;
|
||||
popup.value.open();
|
||||
};
|
||||
|
||||
// 新增获取指定单位人员的方法
|
||||
const getSubOrgStaffs = (subOrgCode) => {
|
||||
return subOrgStaffs.value[subOrgCode] || [];
|
||||
};
|
||||
|
||||
// 新增获取指定年龄段人员的方法
|
||||
const getAgeGroupStaffs = (ageRange) => {
|
||||
return ageGroupStaffs.value[ageRange] || [];
|
||||
};
|
||||
|
||||
// 生成图表数据(修改部分)
|
||||
const generateChartData = (data) => {
|
||||
// 按基层单位分组
|
||||
const ageRanges = ['21-30岁', '31-40岁', '41-50岁', '51-60岁', '61-64岁'];
|
||||
const jcdwGroups = data.reduce((acc, cur) => {
|
||||
if (!acc[cur.jcdw]) {
|
||||
acc[cur.jcdw] = {
|
||||
ageGroups: [0, 0, 0, 0, 0] // 21-30,31-40,41-50,51-60,61-64
|
||||
};
|
||||
}
|
||||
const ageGroup = Math.floor((cur.nl - 21) / 10);
|
||||
// console.log(ageGroup, cur.jcdw)
|
||||
if (ageGroup >= 0 && ageGroup <= 4) {
|
||||
acc[cur.jcdw].ageGroups[ageGroup]++;
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
// 生成分组柱状图配置
|
||||
const xData = Object.keys(jcdwGroups);
|
||||
|
||||
const seriesData = ageRanges.map((range, index) => ({
|
||||
name: range,
|
||||
type: 'bar',
|
||||
data: xData.map((jcdw) => jcdwGroups[jcdw].ageGroups[index] || 0),
|
||||
itemStyle: {
|
||||
color: ['#5470C6', '#91CC75', '#FAC858', '#EE6666', '#73C0DE'][index]
|
||||
},
|
||||
// 显示数值标签
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top'
|
||||
}
|
||||
// 设置柱宽为 20 像素
|
||||
// barWidth: 20
|
||||
}));
|
||||
chartOption.value = {
|
||||
title: {
|
||||
text: '人员年龄分组统计',
|
||||
padding: [0, 0, 0, 30]
|
||||
},
|
||||
toolbox: {
|
||||
padding: [0, 30, 0, 0],
|
||||
show: true,
|
||||
feature: {
|
||||
//工具配置项
|
||||
|
||||
restore: {
|
||||
show: true //是否显示该工具
|
||||
},
|
||||
saveAsImage: {
|
||||
show: true //是否显示该工具
|
||||
}
|
||||
}
|
||||
},
|
||||
// tooltip: {
|
||||
// trigger: 'axis',
|
||||
// axisPointer: {
|
||||
// type: 'shadow',
|
||||
// label: {
|
||||
// show: false
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
grid: {
|
||||
top: '15%',
|
||||
left: '4%',
|
||||
right: '4%',
|
||||
bottom: '10%',
|
||||
containLabel: true
|
||||
},
|
||||
legend: {
|
||||
data: ageRanges,
|
||||
itemGap: 5,
|
||||
padding: [0, 15, 0, 15],
|
||||
y: 'bottom',
|
||||
itemHeight: 8, //高
|
||||
itemWidth: 8, //宽
|
||||
type: 'scroll'
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xData,
|
||||
axisLabel: {
|
||||
color: '#7F84B5',
|
||||
fontWeight: 300,
|
||||
interval: 0,
|
||||
rotate: 0
|
||||
},
|
||||
padding: [0, 10, 0, 10],
|
||||
axisTick: {
|
||||
show: false //刻度线
|
||||
},
|
||||
axisLine: {
|
||||
show: false //不显示坐标轴线
|
||||
}
|
||||
},
|
||||
yAxis: [
|
||||
{
|
||||
show: true,
|
||||
boundaryGap: false, //解决数据与线不对应问题
|
||||
type: 'value',
|
||||
// name: 'Budget (million USD)',
|
||||
// data: this.yList,
|
||||
minInterval: 1,
|
||||
axisLabel: {
|
||||
interval: 0
|
||||
},
|
||||
splitLine: {
|
||||
show: true,
|
||||
lineStyle: {
|
||||
//背景网格线
|
||||
type: 'dashed'
|
||||
}
|
||||
},
|
||||
|
||||
axisTick: {
|
||||
show: true //刻度线
|
||||
},
|
||||
axisLine: {
|
||||
show: false //不显示坐标轴线
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
series: seriesData
|
||||
};
|
||||
|
||||
// 初始化图表
|
||||
setTimeout(async () => {
|
||||
if (!chart.value) return;
|
||||
const myChart = await chart.value.init(echarts);
|
||||
myChart.setOption(chartOption.value);
|
||||
myChart.on('click', (params) => {
|
||||
console.log(params.seriesName);
|
||||
tableData.value = getAgeGroupStaffs(params.seriesName);
|
||||
});
|
||||
}, 300);
|
||||
|
||||
// #ifdef APP
|
||||
getHeight();
|
||||
// #endif
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// #ifdef APP
|
||||
getHeight();
|
||||
// #endif
|
||||
});
|
||||
// #ifdef APP
|
||||
|
||||
const getHeight = () => {
|
||||
// 获取屏幕高度
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
const screenHeight = systemInfo.screenHeight;
|
||||
// 创建选择器查询对象
|
||||
const query = uni.createSelectorQuery();
|
||||
// 获取上方组件的高度
|
||||
query
|
||||
.select('#top1')
|
||||
.boundingClientRect((rect1) => {
|
||||
// 计算上方组件高度总和
|
||||
const topComponentsHeight = rect1.height;
|
||||
// 计算下方组件的高度
|
||||
bottomHeight.value = screenHeight - topComponentsHeight - 415;
|
||||
})
|
||||
.exec();
|
||||
};
|
||||
|
||||
// #endif
|
||||
// 初始化图表
|
||||
const initChart = () => {
|
||||
setTimeout(async () => {
|
||||
if (!chart.value) return;
|
||||
const myChart = await chart.value.init(echarts);
|
||||
myChart.setOption(chartOption.value);
|
||||
}, 300);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
margin: 20, 20, 20, 20rpx;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
border: 1rpx solid #ddd;
|
||||
padding: 15rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.query-btn {
|
||||
background: #007aff;
|
||||
color: white;
|
||||
padding: 0 40rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.stats-box {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin: 30rpx 0;
|
||||
padding: 20rpx;
|
||||
background: #f8f8f8;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #0000ff;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
height: 400rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.titleStyle {
|
||||
font-size: 12px;
|
||||
color: #747474;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
background: #f2f9fc;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border-left: 1px solid #919191;
|
||||
border-bottom: 1px solid #919191;
|
||||
}
|
||||
|
||||
/* 内容样式 */
|
||||
.dataStyle {
|
||||
max-font-size: 14px;
|
||||
/* 最大字体限制 */
|
||||
min-font-size: 10px;
|
||||
/* 最小字体限制 */
|
||||
font-size: 12px;
|
||||
color: #00007f;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border-bottom: 1px solid #919191;
|
||||
border-left: 1px solid #919191;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
</style>
|
||||
61
pages/views/shengchan/index.vue
Normal file
@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="nav"></view>
|
||||
<view class="placeholder"></view>
|
||||
<view style="width: 100%; display: grid; place-items: center">
|
||||
<uni-title :title="dateDate + ':生产经营情况'" type="h1" color="blue" />
|
||||
</view>
|
||||
|
||||
<trq-data></trq-data>
|
||||
<yy-data></yy-data>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { formatDate, getDateAfterDays } from '@/utils/dateTime.js';
|
||||
|
||||
import { ref, onMounted, computed, nextTick, watchEffect } from 'vue';
|
||||
|
||||
const res = wx.getSystemInfoSync();
|
||||
const statusHeight = res.statusBarHeight; //状态栏高度
|
||||
const cusnavbarheight = statusHeight + 44 + 'px';
|
||||
|
||||
const dateDate = ref('');
|
||||
|
||||
import trqData from './ribaoshuju/trqRbsj.vue';
|
||||
import yyData from './ribaoshuju/yyRbsj.vue';
|
||||
|
||||
const strDate = () => {
|
||||
const now = new Date();
|
||||
if (now.getHours() < 11) {
|
||||
return formatDate(getDateAfterDays(now, -1)); //11点之前 头一天的数据
|
||||
} else {
|
||||
return formatDate(now);
|
||||
}
|
||||
};
|
||||
onMounted(() => {
|
||||
dateDate.value = strDate();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.nav {
|
||||
width: calc(100% - 60rpx);
|
||||
padding: 0 30rpx;
|
||||
height: v-bind(cusnavbarheight);
|
||||
|
||||
font-size: 24rpx;
|
||||
color: #ffffff;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 99;
|
||||
background-image: url('../../static/my/navbg.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 750rpx 458rpx;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
height: v-bind(cusnavbarheight);
|
||||
}
|
||||
</style>
|
||||
348
pages/views/shengchan/ribaoshuju/rbsjLsxq.vue
Normal file
@ -0,0 +1,348 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="stats-container">
|
||||
<uni-title v-if="type === 'trq'" :title="name.unit + '天然气---单位(万方)'" color="blue" type="h2"></uni-title>
|
||||
<uni-title v-if="type === 'yy'" :title="name.dw + '原油---单位(吨)'" color="blue" type="h2"></uni-title>
|
||||
</view>
|
||||
<view class="dateSelect">
|
||||
<cxc-szcx-dateRangeSelect :mode="'range'" v-model="dateRange"></cxc-szcx-dateRangeSelect>
|
||||
</view>
|
||||
<cxc-szcx-lineChart v-if="type === 'trq'" :dataList="dataList" x-field="rqDate" y-field="rq" legend-field="unit" :reference-value="0"></cxc-szcx-lineChart>
|
||||
|
||||
<cxc-szcx-lineChart v-if="type === 'yy'" :dataList="dataList" x-field="scrq" y-field="rcwy" legend-field="dw" :reference-value="0"></cxc-szcx-lineChart>
|
||||
<view style="margin: 0 15px">
|
||||
<view class="stats-container">
|
||||
<view class="stats-item">最大值: {{ dataStats.max }}</view>
|
||||
<view class="stats-item">最小值: {{ dataStats.min }}</view>
|
||||
<view class="stats-item">平均值: {{ dataStats.average }}</view>
|
||||
</view>
|
||||
|
||||
<view v-if="type === 'trq'" class="table-container">
|
||||
<!-- 表头 -->
|
||||
<view class="tr header">
|
||||
<view class="th1">序号</view>
|
||||
<view class="th">名称</view>
|
||||
<view class="th">日期</view>
|
||||
<view class="th">日气量</view>
|
||||
</view>
|
||||
<scroll-view scroll-Y="true" class="scroll-wrapper">
|
||||
<!-- 表格内容 -->
|
||||
<view class="tr" v-for="(item, index) in dataList" :key="index" :class="{ even: index % 2 === 0 }">
|
||||
<view class="td1">{{ index + 1 }}</view>
|
||||
<view class="td">{{ item.unit }}</view>
|
||||
<view class="td">{{ item.rqDate }}</view>
|
||||
<view class="td" :class="{ negative: item.rq < 0 }">
|
||||
{{ item.rq }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空数据提示 -->
|
||||
<view v-if="!dataList.length" class="empty">暂无相关数据</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<view v-if="type === 'yy'" class="table-container">
|
||||
<!-- 表头 -->
|
||||
<view class="tr header">
|
||||
<view class="th1">序号</view>
|
||||
<view class="th">名称</view>
|
||||
<view class="th">日期</view>
|
||||
<view class="th">日油量</view>
|
||||
</view>
|
||||
<scroll-view scroll-Y="true" class="scroll-wrapper">
|
||||
<!-- 表格内容 -->
|
||||
<view class="tr" v-for="(item, index) in dataList" :key="index" :class="{ even: index % 2 === 0 }">
|
||||
<view class="td1">{{ index + 1 }}</view>
|
||||
<view class="td">{{ item.dw }}</view>
|
||||
<view class="td">{{ item.scrq }}</view>
|
||||
<view class="td" :class="{ negative: item.rcwy < 0 }">
|
||||
{{ item.rcwy }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空数据提示 -->
|
||||
<view v-if="!dataList.length" class="empty">暂无相关数据</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, computed, nextTick, watchEffect, warn, watch } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { queryJinriShengchansj, queryJinriYuanyouShengchansj } from '@/api/shengchan.js';
|
||||
import { formatDate, getDateAfterDays, getDateAfterMonths } from '@/utils/dateTime.js';
|
||||
const name = ref({});
|
||||
const type = ref('');
|
||||
const dateRange = ref([]);
|
||||
const dataList = ref([]);
|
||||
const endDate = ref('');
|
||||
const startDate = ref('');
|
||||
const dataStats = ref({
|
||||
min: 0,
|
||||
max: 0,
|
||||
avg: 0
|
||||
});
|
||||
const getJinriShengchansj = (tempDateRange) => {
|
||||
// console.log(tempDateRange);
|
||||
// 添加日期有效性检查
|
||||
if (!tempDateRange || tempDateRange.some((date) => !convertToDate(date))) {
|
||||
console.error('收到无效日期范围:', tempDateRange);
|
||||
return;
|
||||
}
|
||||
let queryParms = {};
|
||||
dataList.value = [];
|
||||
queryParms.gas = name.value.gas;
|
||||
queryParms.unit = name.value.unit;
|
||||
queryParms.rqDate_begin = formatDate(tempDateRange[0]);
|
||||
queryParms.rqDate_end = formatDate(tempDateRange[1]);
|
||||
queryParms.pageSize = 500;
|
||||
|
||||
// 添加参数有效性检查
|
||||
if (!queryParms.rqDate_begin || !queryParms.rqDate_end) {
|
||||
console.error('参数格式化失败:', queryParms);
|
||||
return;
|
||||
}
|
||||
// console.log(queryParms);
|
||||
queryJinriShengchansj(queryParms).then((res) => {
|
||||
if (res.success) {
|
||||
// console.log(res);
|
||||
dataList.value = res.result.records;
|
||||
dataStats.value = calculateStats(dataList.value, 'rq');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const getJinriYuanyouShengchansj = (tempDateRange) => {
|
||||
console.log(tempDateRange);
|
||||
// 添加日期有效性检查
|
||||
if (!tempDateRange || tempDateRange.some((date) => !convertToDate(date))) {
|
||||
console.error('收到无效日期范围:', tempDateRange);
|
||||
return;
|
||||
}
|
||||
let queryParms = {};
|
||||
dataList.value = [];
|
||||
queryParms.dw = name.value.dw;
|
||||
queryParms.scrq_begin = formatDate(tempDateRange[0]);
|
||||
queryParms.scrq_end = formatDate(tempDateRange[1]);
|
||||
queryParms.pageSize = 500;
|
||||
|
||||
// 添加参数有效性检查
|
||||
if (!queryParms.scrq_begin || !queryParms.scrq_end) {
|
||||
console.error('参数格式化失败:', queryParms);
|
||||
return;
|
||||
}
|
||||
console.log(queryParms);
|
||||
queryJinriYuanyouShengchansj(queryParms).then((res) => {
|
||||
if (res.success) {
|
||||
console.log(res);
|
||||
dataList.value = res.result.records;
|
||||
dataStats.value = calculateStats(dataList.value, 'rcwy').reverse();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function calculateStats(data, field) {
|
||||
// 过滤掉 field 字段值为 null 或 undefined 的数据
|
||||
const validData = data.filter((item) => item[field] !== null && item[field] !== undefined);
|
||||
if (validData.length === 0) {
|
||||
return {
|
||||
max: null,
|
||||
min: null,
|
||||
average: null
|
||||
};
|
||||
}
|
||||
// 初始化最大值、最小值和总和
|
||||
let max = validData[0][field];
|
||||
let min = validData[0][field];
|
||||
let sum = 0;
|
||||
|
||||
// 遍历有效数据
|
||||
for (let i = 0; i < validData.length; i++) {
|
||||
const value = validData[i][field];
|
||||
// 更新最大值
|
||||
if (value > max) {
|
||||
max = value;
|
||||
}
|
||||
// 更新最小值
|
||||
if (value < min) {
|
||||
min = value;
|
||||
}
|
||||
// 累加值到总和
|
||||
sum += value;
|
||||
}
|
||||
// 计算平均值
|
||||
const average = (sum / validData.length).toFixed(4);
|
||||
|
||||
return {
|
||||
max: max,
|
||||
min: min,
|
||||
average: average
|
||||
};
|
||||
}
|
||||
|
||||
function convertToDate(str) {
|
||||
try {
|
||||
const date = new Date(str);
|
||||
// 判断日期是否有效
|
||||
if (isNaN(date.getTime())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} catch (error) {
|
||||
return false;
|
||||
//TODO handle the exception
|
||||
}
|
||||
}
|
||||
// 修改后(正确)
|
||||
watch(
|
||||
[() => type.value, dateRange], // 监听 type 和 dateRange
|
||||
([newType, newDateRange]) => {
|
||||
if (!newDateRange || !convertToDate(newDateRange[0]) || !convertToDate(newDateRange[1])) {
|
||||
// console.error('无效的日期范围:', newDateRange);
|
||||
return;
|
||||
}
|
||||
// console.log(newType, newDateRange);
|
||||
|
||||
switch (
|
||||
newType // 直接使用 newType
|
||||
) {
|
||||
case 'trq':
|
||||
getJinriShengchansj(newDateRange);
|
||||
break;
|
||||
case 'yy':
|
||||
getJinriYuanyouShengchansj(newDateRange);
|
||||
break;
|
||||
default:
|
||||
console.warn('未知类型:', newType);
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
);
|
||||
onMounted(() => {
|
||||
// nextTick();
|
||||
// getJinriShengchansj(dateRange.value);
|
||||
});
|
||||
|
||||
onLoad((options) => {
|
||||
name.value = JSON.parse(options.data);
|
||||
type.value = options.type;
|
||||
// console.log(name.value, type.value);
|
||||
const now = new Date();
|
||||
|
||||
if (now.getHours() < 11) {
|
||||
endDate.value = getDateAfterDays(now, -1); //11点之前 头一天的数据
|
||||
startDate.value = getDateAfterMonths(endDate.value, -1); //11点之前 头一天的数据
|
||||
} else {
|
||||
endDate.value = now;
|
||||
startDate.value = getDateAfterMonths(endDate.value, -1); //11点之前 头一天的数据
|
||||
}
|
||||
dateRange.value = [startDate.value, endDate.value];
|
||||
// console.log(1111, dateRange.value);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.table-container {
|
||||
width: 100%;
|
||||
height: 40vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.scroll-wrapper {
|
||||
width: 100%;
|
||||
height: 35vh;
|
||||
}
|
||||
|
||||
.tr {
|
||||
display: flex;
|
||||
min-height: 14px;
|
||||
font-size: 12px;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
}
|
||||
|
||||
.th,
|
||||
.td {
|
||||
flex: 1;
|
||||
min-width: 80px;
|
||||
padding: 10px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
height: 18px;
|
||||
vertical-align: middle;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.th1,
|
||||
.td1 {
|
||||
flex: 1;
|
||||
max-width: 40px;
|
||||
padding: 10px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
height: 14px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.th {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.td.negative {
|
||||
color: #ff4444;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.empty {
|
||||
padding: 40px;
|
||||
text-align: center;
|
||||
color: #888;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.stats-container {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
padding: 10px;
|
||||
margin: 15 15px;
|
||||
}
|
||||
|
||||
.dateSelect {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
padding: 5px;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.stats-item {
|
||||
font-size: 12px;
|
||||
color: #00aa00;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.stats-item + .stats-item {
|
||||
border-left: 1px solid #ccc;
|
||||
padding-left: 16px;
|
||||
}
|
||||
</style>
|
||||
646
pages/views/shengchan/ribaoshuju/trqRbsj.vue
Normal file
@ -0,0 +1,646 @@
|
||||
<template>
|
||||
<view :class="{ gray: store.isgray == 1 }">
|
||||
<view style="padding: 0 10px">
|
||||
<view class="progress-bartime">
|
||||
<!-- 动态设置宽度和颜色 -->
|
||||
<view class="progressTime" :style="{ width: `${timePercent}%`, 'background-color': '#00aaff' }"></view>
|
||||
<!-- 显示带符号的百分比 -->
|
||||
<text class="progress-text">全年时间进度:{{ timePercent }}%</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="content">
|
||||
<!-- 标题行 -->
|
||||
<view class="header-row">
|
||||
<view class="title">天然气产量</view>
|
||||
<view class="more" @click="selectMore">更多 →</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="container">
|
||||
<view v-for="(item, index) in shishiArrSelect" :key="index" class="card-item" @click="handleCardClick(item.gas)">
|
||||
<view class="card">
|
||||
<text class="title">{{ item.gas }}</text>
|
||||
<view class="content">
|
||||
<text class="label">气量</text>
|
||||
<text class="value">{{ formatNumber(item.dailyVolume) || '-' }}</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<text class="label">年累计</text>
|
||||
<text class="value">{{ formatNumber(item.yearVolume) || '-' }}</text>
|
||||
</view>
|
||||
<view class="progress-bar">
|
||||
<!-- 动态设置宽度和颜色 -->
|
||||
<view class="progress" :style="{ width: `${Math.abs(item.yearPerCent)}%`, 'background-color': item.yearPerCent < 0 ? '#ff4444' : '#007aff' }"></view>
|
||||
<!-- 显示带符号的百分比 -->
|
||||
<text v-if="!(item.yearPlan === '' || item.yearPlan === '0')" class="progress-text">{{ item.yearPerCent }}%</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<uni-popup ref="popupSelect" type="top" background-color="#fff">
|
||||
<view style="margin-top: 50px">
|
||||
<view class="titlepopup">选择显示更多生产数据</view>
|
||||
<uni-data-checkbox
|
||||
style="font-size: 14px"
|
||||
@change="onselectionchange"
|
||||
:localdata="shishiArr"
|
||||
v-model="shishiArrDisplay"
|
||||
multiple
|
||||
:map="{ value: 'gas', text: 'gas' }"
|
||||
></uni-data-checkbox>
|
||||
</view>
|
||||
</uni-popup>
|
||||
<!-- 数据弹窗 -->
|
||||
<uni-popup ref="popup" type="bottom" background-color="#fff">
|
||||
<view class="popup-content">
|
||||
<view class="popup-header">
|
||||
<text class="title">{{ selectedGas }}数据详情 单位(万立方米)</text>
|
||||
<uni-icons type="closeempty" size="24" color="#666" @click="closePopup"></uni-icons>
|
||||
</view>
|
||||
|
||||
<view class="table">
|
||||
<!-- 表头 -->
|
||||
<view class="tr header">
|
||||
<view class="th1">序号</view>
|
||||
<view class="th">名称</view>
|
||||
<view class="th">日气量</view>
|
||||
<view class="th">年累计</view>
|
||||
<view class="th1">操作</view>
|
||||
</view>
|
||||
<scroll-view scroll-X="true" scroll-Y="true" class="table-container">
|
||||
<!-- 表格内容 -->
|
||||
<view class="tr" v-for="(item, index) in filteredData" :key="index" :class="{ even: index % 2 === 0 }">
|
||||
<view class="td1">{{ index + 1 }}</view>
|
||||
<view class="td">{{ item.unit }}</view>
|
||||
<view class="td" :class="{ negative: item.rq < 0 }">
|
||||
{{ formatNumber(item.rq) }}
|
||||
</view>
|
||||
<view class="td" :class="{ negative: item.yearVolume < 0 }">
|
||||
{{ formatNumber(item.yearVolume) }}
|
||||
</view>
|
||||
<view class="td1" style="color: red" @click="goHistory(item)">历史</view>
|
||||
</view>
|
||||
|
||||
<!-- 空数据提示 -->
|
||||
<view v-if="!filteredData.length" class="empty">暂无相关数据</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, computed, nextTick, watchEffect } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { queryJinriShengchansj, queryYearShengchansj, queryJinriTrqShengchansj } from '@/api/shengchan.js';
|
||||
import { formatDate, getDateAfterDays } from '@/utils/dateTime.js';
|
||||
import { beforeJump } from '@/utils/index.js';
|
||||
import { useStore } from '@/store';
|
||||
import { getYearProgress } from '@/utils/dateTime.js';
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const shishiArr = ref([]);
|
||||
const shishiArrSelect = ref([]);
|
||||
const shishiArrDisplay = ref(['气井气', '站线综合输差']);
|
||||
const dataJinriUnit = ref([]);
|
||||
const selectedGas = ref('');
|
||||
const filteredData = ref([]);
|
||||
const popup = ref(null);
|
||||
const popupSelect = ref(null);
|
||||
const strDate = ref('');
|
||||
const timePercent = ref(0);
|
||||
|
||||
const dataJinri = ref([]);
|
||||
const dataJinriSum = ref([]);
|
||||
const dataJinriSumUnit = ref([]);
|
||||
|
||||
// 点击卡片处理
|
||||
// const handleCardClick = (gas) => {
|
||||
// selectedGas.value = gas;
|
||||
// let queryParms = {};
|
||||
// filteredData.value = [];
|
||||
// queryParms.day = strDate.value;
|
||||
// queryParms.gas = gas;
|
||||
// queryParms.unit = '文23气田,户部寨气田';
|
||||
// console.log(queryParms);
|
||||
// queryJinriTrqShengchansj(queryParms).then((res) => {
|
||||
// if (res.success) {
|
||||
// console.log(res);
|
||||
// filteredData.value = res.result;
|
||||
// }
|
||||
// });
|
||||
|
||||
// popup.value.open();
|
||||
// };
|
||||
function selectMore() {
|
||||
popupSelect.value.open();
|
||||
}
|
||||
const onselectionchange = () => {
|
||||
shishiArrSelect.value = [];
|
||||
shishiArrDisplay.value.forEach((item) => {
|
||||
shishiArrSelect.value.push(shishiArr.value.filter((item1) => item1.gas === item)[0]);
|
||||
});
|
||||
};
|
||||
|
||||
const handleCardClick = (gas) => {
|
||||
selectedGas.value = gas;
|
||||
filteredData.value = dataJinriSumUnit.value.filter((item) => item.gas === gas);
|
||||
popup.value.open();
|
||||
};
|
||||
|
||||
// 关闭弹窗
|
||||
const closePopup = () => {
|
||||
popup.value.close();
|
||||
};
|
||||
onMounted(() => {
|
||||
getJinriTrqShengchansj();
|
||||
timePercent.value = getYearProgress();
|
||||
getJinriShengchansj();
|
||||
});
|
||||
|
||||
// 数字格式化
|
||||
const formatNumber = (num) => {
|
||||
let temp = 0;
|
||||
try {
|
||||
temp = parseFloat(num);
|
||||
} catch (error) {
|
||||
//TODO handle the exception
|
||||
}
|
||||
|
||||
return temp.toFixed(4).replace(/\.?0+$/, '');
|
||||
};
|
||||
|
||||
// 自动计算综合输差
|
||||
function calcZhsc(tempArray) {
|
||||
let totalJinqi = {
|
||||
gas: '总进气',
|
||||
dailyVolume: 0,
|
||||
yearVolume: 0,
|
||||
yearPlan: '100',
|
||||
yearPerCent: 0
|
||||
};
|
||||
let totalChuqi = {
|
||||
gas: '总出气',
|
||||
dailyVolume: 0,
|
||||
yearVolume: 0,
|
||||
yearPlan: '100',
|
||||
yearPerCent: 0
|
||||
};
|
||||
const compositeZx = {
|
||||
gas: '站线综合输差',
|
||||
dailyVolume: 0,
|
||||
yearVolume: 0,
|
||||
yearPlan: '100',
|
||||
yearPerCent: 0
|
||||
}; // 综合输差
|
||||
const compositeJc = {
|
||||
gas: '进出综合输差',
|
||||
dailyVolume: 0,
|
||||
yearVolume: 0,
|
||||
yearPlan: '100',
|
||||
yearPerCent: 0
|
||||
}; // 综合输差
|
||||
tempArray.forEach((item) => {
|
||||
if (item.gas === '站输差' || item.gas === '线输差') {
|
||||
compositeZx.dailyVolume += parseFloat(item.dailyVolume) || 0;
|
||||
compositeZx.yearVolume += parseFloat(item.yearVolume) || 0;
|
||||
}
|
||||
if (item.gas === '气井气' || item.gas === '外部气' || item.gas === '返回气') {
|
||||
totalJinqi.dailyVolume += parseFloat(item.dailyVolume) || 0;
|
||||
totalJinqi.yearVolume += parseFloat(item.yearVolume) || 0;
|
||||
}
|
||||
if (item.gas === '自耗气' || item.gas === '用户气' || item.gas === '返采油厂干气') {
|
||||
totalChuqi.dailyVolume += parseFloat(item.dailyVolume) || 0;
|
||||
totalChuqi.yearVolume += parseFloat(item.yearVolume) || 0;
|
||||
}
|
||||
});
|
||||
|
||||
compositeZx.yearPerCent = calcPercent(compositeZx.yearPlan, compositeZx.yearVolume);
|
||||
|
||||
compositeJc.dailyVolume = (-totalJinqi.dailyVolume + totalChuqi.dailyVolume).toFixed(4);
|
||||
compositeJc.yearVolume = (-totalJinqi.yearVolume + totalChuqi.yearVolume).toFixed(4);
|
||||
compositeJc.yearPerCent = calcPercent(compositeJc.yearPlan, compositeJc.yearVolume);
|
||||
|
||||
tempArray.push(compositeZx);
|
||||
// tempArray.push(compositeJc);
|
||||
|
||||
return tempArray;
|
||||
|
||||
// console.log(composite);
|
||||
}
|
||||
|
||||
const getJinriTrqShengchansj = () => {
|
||||
const now = new Date();
|
||||
if (now.getHours() < 11) {
|
||||
strDate.value = formatDate(getDateAfterDays(now, -1)).toString(); //11点之前 头一天的数据
|
||||
} else {
|
||||
strDate.value = formatDate(now).toString();
|
||||
}
|
||||
let queryParms = {};
|
||||
shishiArr.value = [];
|
||||
|
||||
queryParms.day = strDate.value;
|
||||
// // console.log(queryParms);
|
||||
queryJinriTrqShengchansj(queryParms).then((res) => {
|
||||
if (res.success) {
|
||||
// console.log(1, res);
|
||||
let temp = res.result;
|
||||
|
||||
temp.forEach((item) => {
|
||||
if (item.gas === '气井气') {
|
||||
item.yearPlan = 7500;
|
||||
item.yearPerCent = calcPercent(item.yearPlan, item.yearVolume);
|
||||
}
|
||||
});
|
||||
// console.log(2, temp);
|
||||
shishiArr.value = calcZhsc(temp);
|
||||
nextTick();
|
||||
onselectionchange();
|
||||
console.log(3, shishiArr.value);
|
||||
console.log(4, shishiArrSelect.value);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function goHistory(val) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/views/shengchan/ribaoshuju/rbsjLsxq?data=' + JSON.stringify(val) + '&type=trq'
|
||||
});
|
||||
}
|
||||
|
||||
function calcPercent(yearJihua, yearShiji) {
|
||||
// 计算进度百分比,避免除数为 0
|
||||
// 确保进度百分比不超过 100
|
||||
let plan = parseFloat(yearJihua === '' ? 0 : yearJihua);
|
||||
let shiji = parseFloat(yearShiji);
|
||||
let percent = 0;
|
||||
// 修改原始计算代码
|
||||
if (plan > 0) {
|
||||
percent = (shiji / plan) * 100;
|
||||
percent = Math.min(percent, 100); // 限制最大100%
|
||||
}
|
||||
return parseFloat(percent.toFixed(2)); // 转为数值
|
||||
}
|
||||
|
||||
const getJinriShengchansj = () => {
|
||||
const now = new Date();
|
||||
if (now.getHours() < 11) {
|
||||
strDate.value = formatDate(getDateAfterDays(now, -1)).toString(); //11点之前 头一天的数据
|
||||
} else {
|
||||
strDate.value = formatDate(now).toString();
|
||||
}
|
||||
let queryParms = {};
|
||||
dataJinri.value = [];
|
||||
dataJinriSum.value = [];
|
||||
dataJinriSumUnit.value = [];
|
||||
queryParms.rqDate = strDate.value;
|
||||
queryParms.pageSize = 100;
|
||||
// console.log(queryParms);
|
||||
queryJinriShengchansj(queryParms).then((res) => {
|
||||
if (res.success) {
|
||||
// console.log(res);
|
||||
dataJinri.value = res.result.records;
|
||||
dataJinriSumUnit.value = sumByUnit(dataJinri.value); //包含gas unit rq cq totalGas
|
||||
// console.log(dataJinriSumUnit.value);
|
||||
// 使用 nextTick 等待 DOM 更新
|
||||
nextTick();
|
||||
getYearShengchansj(); //再获取今年以来的数据
|
||||
}
|
||||
});
|
||||
};
|
||||
const getYearShengchansj = () => {
|
||||
const now = new Date();
|
||||
let year = formatDate(now).split('-')[0];
|
||||
let queryParms = {};
|
||||
queryParms.yearStart = year;
|
||||
queryParms.yearEnd = year;
|
||||
|
||||
// // console.log(2, queryParms.value);
|
||||
queryYearShengchansj(queryParms).then((res) => {
|
||||
if (res.success) {
|
||||
try {
|
||||
// // console.log(res.result);
|
||||
let yearData = res.result[year];
|
||||
// console.log(dataJinriSumUnit.value.length, dataJinriSumUnit.value, yearData.length,
|
||||
// yearData);
|
||||
dataJinriSumUnit.value.forEach((item) => {
|
||||
yearData.forEach((itemYear) => {
|
||||
// // console.log(item, itemYear);
|
||||
if (item.unit === itemYear.unit) {
|
||||
item.yearVolume = itemYear.yearSum || 0;
|
||||
}
|
||||
});
|
||||
});
|
||||
dataJinriSum.value = sumByGas(dataJinriSumUnit.value);
|
||||
// console.log(dataJinriSum.value);
|
||||
shishiArr.value.forEach((item) => {
|
||||
dataJinriSum.value.forEach((itemjinri) => {
|
||||
if (item.gas === itemjinri.gas) {
|
||||
item.dailyVolume = itemjinri.rq.toFixed(4);
|
||||
item.yearVolume = itemjinri.yearVolume.toFixed(4);
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
// console.log(error);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function sumByGas(records) {
|
||||
// console.log(records);
|
||||
const summaryMap = {};
|
||||
try {
|
||||
records.forEach((record) => {
|
||||
const gas = record.gas;
|
||||
if (!summaryMap[gas]) {
|
||||
// 初始化该 gas 类型的汇总对象
|
||||
summaryMap[gas] = {
|
||||
gas: gas,
|
||||
rq: 0,
|
||||
sq: 0,
|
||||
totalGas: 0,
|
||||
yearVolume: 0
|
||||
};
|
||||
}
|
||||
// 无论是否是第一次遇到该 gas 类型,都进行累加操作
|
||||
summaryMap[gas].rq += record.rq || 0;
|
||||
summaryMap[gas].sq += record.sq || 0;
|
||||
summaryMap[gas].totalGas += record.totalGas || 0;
|
||||
summaryMap[gas].yearVolume += record.yearVolume || 0;
|
||||
});
|
||||
return Object.values(summaryMap);
|
||||
} catch (error) {
|
||||
//TODO handle the exception
|
||||
// console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
function sumByUnit(records) {
|
||||
// console.log(records);
|
||||
const summaryMap = {};
|
||||
try {
|
||||
records.forEach((record) => {
|
||||
const unit = record.unit;
|
||||
if (!unit.includes('区')) {
|
||||
if (!summaryMap[unit]) {
|
||||
// 初始化该 gas 类型的汇总对象
|
||||
summaryMap[unit] = {
|
||||
unit: unit,
|
||||
gas: record.gas,
|
||||
rq: 0,
|
||||
sq: 0,
|
||||
totalGas: 0,
|
||||
yearVolume: 0
|
||||
};
|
||||
}
|
||||
// 无论是否是第一次遇到该 unit 类型,都进行累加操作
|
||||
summaryMap[unit].rq += record.rq || 0;
|
||||
summaryMap[unit].sq += record.sq || 0;
|
||||
summaryMap[unit].totalGas += record.totalGas || 0;
|
||||
summaryMap[unit].yearVolume += record.yearVolume || 0;
|
||||
}
|
||||
});
|
||||
|
||||
return Object.values(summaryMap);
|
||||
} catch (error) {
|
||||
//TODO handle the exception
|
||||
// console.log(error);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10 10rpx;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
.titlepopup {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.more {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.more::after {
|
||||
content: '';
|
||||
width: 8rpx;
|
||||
height: 8rpx;
|
||||
border-top: 2rpx solid #666;
|
||||
border-right: 2rpx solid #666;
|
||||
transform: rotate(45deg);
|
||||
margin-left: 8rpx;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* 鼠标悬停效果 */
|
||||
.more:hover {
|
||||
color: #007aff;
|
||||
}
|
||||
.container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 20rpx;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
padding: 30rpx;
|
||||
max-height: 40vh;
|
||||
}
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 30rpx;
|
||||
padding-bottom: 20rpx;
|
||||
border-bottom: 2rpx solid #eee;
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.table-container {
|
||||
width: 100%;
|
||||
height: 30vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.table {
|
||||
min-width: 100%;
|
||||
border: 2rpx solid #e8e8e8;
|
||||
|
||||
.tr {
|
||||
display: flex;
|
||||
border-bottom: 2rpx solid #e8e8e8;
|
||||
|
||||
&.header {
|
||||
background-color: #fafafa;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&.even {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
}
|
||||
|
||||
.th,
|
||||
.td {
|
||||
flex: 1;
|
||||
min-width: 80rpx;
|
||||
padding: 10rpx;
|
||||
font-size: 22rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
height: 30rpx;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.th1,
|
||||
.td1 {
|
||||
flex: 1;
|
||||
max-width: 40rpx;
|
||||
padding: 10rpx;
|
||||
font-size: 22rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
height: 30rpx;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.th {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.td.negative {
|
||||
color: #ff4444;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.empty {
|
||||
padding: 40rpx;
|
||||
text-align: center;
|
||||
color: #888;
|
||||
font-size: 16rpx;
|
||||
}
|
||||
|
||||
.card-item {
|
||||
flex: 1 1 200rpx; // 基础宽度300rpx,自动伸缩 selectedGas formatNumber
|
||||
min-width: 240rpx;
|
||||
max-width: calc(50% - 10rpx); // 最大不超过容器一半(考虑间距)
|
||||
|
||||
@media (min-width: 768px) {
|
||||
max-width: calc(33.33% - 14rpx); // 大屏显示3列
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
background: #ececec;
|
||||
border-radius: 16rpx;
|
||||
padding: 15rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(179, 179, 179, 0.1);
|
||||
|
||||
.title {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 28rpx;
|
||||
color: #0000ff;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.progress-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
position: relative;
|
||||
height: 20px;
|
||||
background: #f0f0f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.progress-bartime {
|
||||
position: relative;
|
||||
height: 20px;
|
||||
background: #f0f0f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
.progress {
|
||||
height: 100%;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.progressTime {
|
||||
height: 100%;
|
||||
transition: all 0.3s;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: red;
|
||||
/* 保持红色 */
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
/* 提升可读性 */
|
||||
}
|
||||
</style>
|
||||
412
pages/views/shengchan/ribaoshuju/yyRbsj.vue
Normal file
@ -0,0 +1,412 @@
|
||||
<template>
|
||||
<view :class="{ gray: store.isgray == 1 }">
|
||||
<!-- <view style="margin-left: 20rpx;"> <uni-title :title="strDate + ':生产数据'" type="h1" color="red" /> -->
|
||||
<!-- </view> -->
|
||||
|
||||
<view class="content">
|
||||
<!-- 标题行 -->
|
||||
<view class="header-row">
|
||||
<view class="title">原油产量</view>
|
||||
<view class="more"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="container">
|
||||
<view v-for="(item, index) in shishiArr" :key="index" class="card-item" @click="handleCardClick(item.gas)">
|
||||
<view class="card">
|
||||
<!-- <text class="title">{{ item.gas }}</text> -->
|
||||
<view class="content">
|
||||
<text class="label">日油量</text>
|
||||
<text class="value">{{ item.rcwy || '-' }}</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<text class="label">月累计</text>
|
||||
<text class="value">{{ item.yl || '-' }}</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<text class="label">年累计</text>
|
||||
<text class="value">{{ item.nl || '-' }}</text>
|
||||
</view>
|
||||
|
||||
<view class="progress-bar">
|
||||
<!-- 动态设置宽度和颜色 -->
|
||||
<view
|
||||
class="progress"
|
||||
:style="{
|
||||
width: `${Math.abs(item.yearPerCent)}%`,
|
||||
'background-color': item.yearPerCent < 0 ? '#ff4444' : '#007aff'
|
||||
}"
|
||||
></view>
|
||||
<!-- 显示带符号的百分比 -->
|
||||
<text v-if="!(item.yearPlan === '' || item.yearPlan === '0')" class="progress-text">{{ item.yearPerCent }}%</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 数据弹窗 -->
|
||||
<uni-popup ref="popup" type="bottom" background-color="#fff">
|
||||
<view class="popup-content">
|
||||
<view class="popup-header">
|
||||
<text class="title">原油数据详情 单位(吨)</text>
|
||||
<uni-icons type="closeempty" size="24" color="#666" @click="closePopup"></uni-icons>
|
||||
</view>
|
||||
|
||||
<scroll-view scroll-X="true" scroll-Y="true" class="table-container">
|
||||
<view class="table">
|
||||
<!-- 表头 -->
|
||||
<view class="tr header">
|
||||
<view class="th1">序号</view>
|
||||
<view class="th">名称</view>
|
||||
<view class="th">日油量</view>
|
||||
<view class="th">月累计</view>
|
||||
<view class="th">年累计</view>
|
||||
<view class="th1">操作</view>
|
||||
</view>
|
||||
|
||||
<!-- 表格内容 -->
|
||||
<view class="tr" v-for="(item, index) in dataJinri" :key="index" :class="{ even: index % 2 === 0 }">
|
||||
<view class="td1">{{ index }}</view>
|
||||
<view class="td">{{ item.dw }}</view>
|
||||
<view class="td">
|
||||
{{ formatNumber(item.rcwy) }}
|
||||
</view>
|
||||
<view class="td">{{ formatNumber(item.yl) }}</view>
|
||||
<view class="td">
|
||||
{{ formatNumber(item.nl) }}
|
||||
</view>
|
||||
<view class="td1" style="color: red" @click="goHistory(item)">历史</view>
|
||||
</view>
|
||||
|
||||
<!-- 空数据提示 -->
|
||||
<view v-if="!dataJinri.length" class="empty">暂无相关数据</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, computed, nextTick, watchEffect } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { queryJinriYuanyouShengchansj } from '@/api/shengchan.js';
|
||||
import { formatDate, getDateAfterDays } from '@/utils/dateTime.js';
|
||||
import { beforeJump } from '@/utils/index.js';
|
||||
import { useStore } from '@/store';
|
||||
|
||||
const store = useStore();
|
||||
import dataCom from '@/bpm/dataCom.vue';
|
||||
|
||||
const shishiArr = ref([
|
||||
{
|
||||
gas: '原油产量',
|
||||
rcwy: '',
|
||||
yl: '',
|
||||
nl: '',
|
||||
yearPlan: '1500',
|
||||
yearPerCent: ''
|
||||
}
|
||||
]);
|
||||
|
||||
const dataJinri = ref([]);
|
||||
const dataJinriSum = ref([]);
|
||||
const popup = ref(null);
|
||||
// 点击卡片处理
|
||||
const handleCardClick = () => {
|
||||
popup.value.open();
|
||||
};
|
||||
|
||||
// 关闭弹窗
|
||||
const closePopup = () => {
|
||||
popup.value.close();
|
||||
};
|
||||
onMounted(() => {
|
||||
getJinriYuanyouShengchansj();
|
||||
// getYearShengchansj();
|
||||
});
|
||||
|
||||
const strDate = ref('');
|
||||
// 数字格式化
|
||||
const formatNumber = (num) => {
|
||||
if (typeof num !== 'number') return '-';
|
||||
return num.toFixed(4).replace(/\.?0+$/, '');
|
||||
};
|
||||
function goHistory(val) {
|
||||
uni.navigateTo({
|
||||
url: '/pages/views/shengchan/ribaoshuju/rbsjLsxq?data=' + JSON.stringify(val) + '&type=yy'
|
||||
});
|
||||
}
|
||||
const getJinriYuanyouShengchansj = () => {
|
||||
const now = new Date();
|
||||
if (now.getHours() < 11) {
|
||||
strDate.value = formatDate(getDateAfterDays(now, -1)).toString(); //11点之前 头一天的数据
|
||||
} else {
|
||||
strDate.value = formatDate(now).toString();
|
||||
}
|
||||
let queryParms = {};
|
||||
dataJinri.value = [];
|
||||
dataJinriSum.value = [];
|
||||
queryParms.scrq = strDate.value;
|
||||
queryParms.pageSize = 100;
|
||||
// // console.log(queryParms);
|
||||
queryJinriYuanyouShengchansj(queryParms).then((res) => {
|
||||
if (res.success) {
|
||||
// // console.log(res);
|
||||
dataJinri.value = res.result.records;
|
||||
dataJinriSum.value = sumByOil(dataJinri.value); //包含gas unit rq cq totalGas
|
||||
// // console.log(dataJinriSum.value);
|
||||
nextTick();
|
||||
shishiArr.value.forEach((item) => {
|
||||
dataJinriSum.value.forEach((itemjinri) => {
|
||||
item.rcwy = itemjinri.rcwy.toFixed(4);
|
||||
item.nl = itemjinri.nl.toFixed(4);
|
||||
item.yl = itemjinri.yl.toFixed(4);
|
||||
item.yearPerCent = calcPercent(item.yearPlan, item.nl);
|
||||
});
|
||||
});
|
||||
// getYearShengchansj(); //再获取今年以来的数据
|
||||
}
|
||||
});
|
||||
};
|
||||
function calcPercent(yearJihua, yearShiji) {
|
||||
// 计算进度百分比,避免除数为 0
|
||||
// 确保进度百分比不超过 100
|
||||
let plan = parseFloat(yearJihua === '' ? 0 : yearJihua);
|
||||
let shiji = parseFloat(yearShiji);
|
||||
let percent = 0;
|
||||
// 修改原始计算代码
|
||||
if (plan > 0) {
|
||||
percent = (shiji / plan) * 100;
|
||||
percent = Math.min(percent, 100); // 限制最大100%
|
||||
}
|
||||
return parseFloat(percent.toFixed(2)); // 转为数值
|
||||
}
|
||||
function sumByOil(records) {
|
||||
// console.log(records);
|
||||
const summaryMap = {};
|
||||
try {
|
||||
records.forEach((record) => {
|
||||
const gas = record.gas;
|
||||
if (!summaryMap[gas]) {
|
||||
// 初始化该 gas 类型的汇总对象
|
||||
summaryMap[gas] = {
|
||||
rcwy: 0,
|
||||
yl: 0,
|
||||
nl: 0
|
||||
};
|
||||
}
|
||||
// 无论是否是第一次遇到该 gas 类型,都进行累加操作
|
||||
summaryMap[gas].rcwy += record.rcwy || 0;
|
||||
summaryMap[gas].yl += record.yl || 0;
|
||||
summaryMap[gas].nl += record.nl || 0;
|
||||
});
|
||||
return Object.values(summaryMap);
|
||||
} catch (error) {
|
||||
//TODO handle the exception
|
||||
// console.log(error);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.header-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 15rpx 0;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.more {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.more::after {
|
||||
content: '';
|
||||
width: 8rpx;
|
||||
height: 8rpx;
|
||||
border-top: 2rpx solid #666;
|
||||
border-right: 2rpx solid #666;
|
||||
transform: rotate(45deg);
|
||||
margin-left: 8rpx;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* 鼠标悬停效果 */
|
||||
.more:hover {
|
||||
color: #007aff;
|
||||
}
|
||||
.container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 20rpx;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
padding: 30rpx;
|
||||
max-height: 70vh;
|
||||
}
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 30rpx;
|
||||
padding-bottom: 20rpx;
|
||||
border-bottom: 2rpx solid #eee;
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.table-container {
|
||||
width: 100%;
|
||||
height: 30vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.table {
|
||||
min-width: 100%;
|
||||
border: 2rpx solid #e8e8e8;
|
||||
|
||||
.tr {
|
||||
display: flex;
|
||||
border-bottom: 2rpx solid #e8e8e8;
|
||||
|
||||
&.header {
|
||||
background-color: #fafafa;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&.even {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
}
|
||||
|
||||
.th,
|
||||
.td {
|
||||
flex: 1;
|
||||
min-width: 80rpx;
|
||||
padding: 10rpx;
|
||||
font-size: 20rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.th1,
|
||||
.td1 {
|
||||
flex: 1;
|
||||
max-width: 40rpx;
|
||||
padding: 10rpx;
|
||||
font-size: 22rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
height: 30rpx;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.th {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.td.negative {
|
||||
color: #ff4444;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.empty {
|
||||
padding: 40rpx;
|
||||
text-align: center;
|
||||
color: #888;
|
||||
font-size: 16rpx;
|
||||
}
|
||||
|
||||
.card-item {
|
||||
flex: 1 1 200rpx; // 基础宽度300rpx,自动伸缩 selectedGas formatNumber
|
||||
min-width: 200rpx;
|
||||
max-width: calc(50% - 10rpx); // 最大不超过容器一半(考虑间距)
|
||||
|
||||
@media (min-width: 768px) {
|
||||
max-width: calc(33.33% - 14rpx); // 大屏显示3列
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
background: #ececec;
|
||||
border-radius: 16rpx;
|
||||
padding: 15rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(197, 197, 197, 0.1);
|
||||
|
||||
.title {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 28rpx;
|
||||
color: #0000ff;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
.progress-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
position: relative;
|
||||
height: 20px;
|
||||
background: #f0f0f0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress {
|
||||
height: 100%;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: red; /* 保持红色 */
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); /* 提升可读性 */
|
||||
}
|
||||
</style>
|
||||
212
pages/views/zhongheguanli/meeting/detail.vue
Normal file
@ -0,0 +1,212 @@
|
||||
<template>
|
||||
<view :class="['content',{'gray':store.isgray==1}]">
|
||||
<view class="list_box">
|
||||
<view class="list">
|
||||
<view class="title f-row aic jcb">
|
||||
<view class="">
|
||||
年度部门讨论会议
|
||||
</view>
|
||||
<text>1分钟前</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="f-row aic jcb">
|
||||
<view class="">
|
||||
会议状态:
|
||||
</view>
|
||||
<text>待开始/已开始/已结束</text>
|
||||
</view>
|
||||
<view class="f-row aic jcb">
|
||||
<view class="">
|
||||
发起人:
|
||||
</view>
|
||||
<text>周如意</text>
|
||||
</view>
|
||||
<view class="f-row aic jcb">
|
||||
<view class="">
|
||||
会议日期:
|
||||
</view>
|
||||
<text>周如意</text>
|
||||
</view>
|
||||
<view class="f-row aic jcb">
|
||||
<view class="">
|
||||
会议地点:
|
||||
</view>
|
||||
<text>周如意</text>
|
||||
</view>
|
||||
<view class="f-row aic jcb">
|
||||
<view class="">
|
||||
会议内容:
|
||||
</view>
|
||||
<text>周如意</text>
|
||||
</view>
|
||||
<view class="">
|
||||
<view class="">
|
||||
参与人员:
|
||||
</view>
|
||||
<view class="person f-row aic">
|
||||
<view class="item f-col aic" v-for="item,i in 7" :key="i">
|
||||
<image src="" mode=""></image>
|
||||
<view class="name">
|
||||
周如意
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn f-row aic jcb">
|
||||
<view class="refuse">
|
||||
拒绝
|
||||
</view>
|
||||
<view class="agree" @click="openpop">
|
||||
同意
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from 'vue';
|
||||
import {
|
||||
huiyiDetailApi
|
||||
} from '@/api/api.js';
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store'
|
||||
const store = useStore()
|
||||
onLoad(() => {
|
||||
huiyiDetail()
|
||||
})
|
||||
const huiyiDetail = () => {
|
||||
huiyiDetailApi({
|
||||
mainid:1
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.content{
|
||||
padding-bottom: 120rpx;
|
||||
}
|
||||
.btn {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 690rpx;
|
||||
height: 120rpx;
|
||||
background: #FFFFFF;
|
||||
padding: 0 30rpx;
|
||||
border-top: 1px solid #EFEFEF;
|
||||
|
||||
view {
|
||||
|
||||
width: 330rpx;
|
||||
height: 88rpx;
|
||||
font-size: 28rpx;
|
||||
border-radius: 16rpx;
|
||||
text-align: center;
|
||||
line-height: 88rpx;
|
||||
}
|
||||
|
||||
.refuse {
|
||||
box-sizing: border-box;
|
||||
background: #FFFFFF;
|
||||
border: 2rpx solid #01508B;
|
||||
color: #01508B;
|
||||
}
|
||||
|
||||
.agree {
|
||||
background: #01508B;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
.list_box {
|
||||
|
||||
.list {
|
||||
padding: 30rpx;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.title {
|
||||
border-bottom: 1px solid #efefef;
|
||||
padding-bottom: 24rpx;
|
||||
margin-bottom: 8rpx;
|
||||
|
||||
view {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
|
||||
view {
|
||||
padding-top: 16rpx;
|
||||
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
text{
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
.person{
|
||||
flex-wrap: wrap;
|
||||
.item{
|
||||
width: 16.66%;
|
||||
|
||||
}
|
||||
image{
|
||||
width: 78rpx;
|
||||
height: 78rpx;
|
||||
border-radius: 38rpx;
|
||||
background-color: #01508B;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin-top: 30rpx;
|
||||
|
||||
view {
|
||||
width: 300rpx;
|
||||
height: 64rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 28rpx;
|
||||
text-align: center;
|
||||
line-height: 64rpx;
|
||||
}
|
||||
|
||||
.entrust {
|
||||
background: #FFFFFF;
|
||||
border: 2rpx solid #01508B;
|
||||
box-sizing: border-box;
|
||||
color: #01508B;
|
||||
}
|
||||
|
||||
.handle {
|
||||
background: #01508B;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
247
pages/views/zhongheguanli/meeting/index.vue
Normal file
@ -0,0 +1,247 @@
|
||||
<template>
|
||||
<view :class="{'gray':store.isgray==1}">
|
||||
<customNav>
|
||||
<view class="nav_box f-row aic jcb">
|
||||
<view class="back f-row aic" @click="back">
|
||||
<uni-icons type="left" size="20" color="#fff"></uni-icons>
|
||||
</view>
|
||||
<view class="search f-row aic">
|
||||
<input type="text" v-model="searchKey" @confirm="search" @blur="showicon=true&&!searchKey"
|
||||
@focus="showicon=false" />
|
||||
<view class="f-row aic" v-if="showicon">
|
||||
<image src="@/static/search.png" mode=""></image>
|
||||
<text>搜索</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</customNav>
|
||||
<view class="list_box">
|
||||
<view class="list" v-for="item,i in 3" :key="i" @click="jump(`/pages/meeting/detail?id=1`)">
|
||||
<view class="title f-row aic jcb">
|
||||
<view class="">
|
||||
年度部门讨论会议
|
||||
</view>
|
||||
<text>1分钟前</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="f-row aic jcb">
|
||||
<view class="">
|
||||
发起人:
|
||||
</view>
|
||||
<text>周如意</text>
|
||||
</view>
|
||||
<view class="f-row aic jcb">
|
||||
<view class="">
|
||||
会议日期:
|
||||
</view>
|
||||
<text>周如意</text>
|
||||
</view>
|
||||
<view class="f-row aic jcb">
|
||||
<view class="">
|
||||
会议地点:
|
||||
</view>
|
||||
<text>周如意</text>
|
||||
</view>
|
||||
<view class="f-row aic jcb">
|
||||
<view class="">
|
||||
会议内容:
|
||||
</view>
|
||||
<text>周如意</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="btn f-row aic jcb">
|
||||
<view class="entrust">
|
||||
拒绝
|
||||
</view>
|
||||
<view class="handle">
|
||||
同意
|
||||
</view>
|
||||
</view> -->
|
||||
<view class="handled f-row">
|
||||
<view class="refused">
|
||||
已拒绝
|
||||
</view>
|
||||
<!-- <view class="agreed">
|
||||
已同意
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from 'vue';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store'
|
||||
const store = useStore()
|
||||
import {
|
||||
huiyilistApi
|
||||
} from '@/api/api.js';
|
||||
import customNav from '@/bpm/customNav.vue';
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
beforeJump
|
||||
} from '@/utils/index.js';
|
||||
const showicon = ref(true)
|
||||
const searchKey = ref('')
|
||||
onLoad(() => {
|
||||
// huiyilist()
|
||||
})
|
||||
const huiyilist = () => {
|
||||
huiyilistApi().then((res) => {
|
||||
if (res.success) {
|
||||
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
})
|
||||
}
|
||||
const jump = (url) => {
|
||||
beforeJump(url, () => {
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
})
|
||||
}
|
||||
const back = () => {
|
||||
uni.navigateBack()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.nav_box {
|
||||
position: absolute;
|
||||
bottom: 14rpx;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.back {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.search {
|
||||
position: relative;
|
||||
padding-right: 30rpx;
|
||||
flex: 1;
|
||||
|
||||
view {
|
||||
position: absolute;
|
||||
left: 28rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
|
||||
}
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
height: 72rpx;
|
||||
background: #F8F8F8;
|
||||
border-radius: 44rpx;
|
||||
padding: 0 28rpx;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.list_box {
|
||||
padding: 14rpx 30rpx 0 30rpx;
|
||||
margin-top: 24rpx;
|
||||
|
||||
.list {
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0rpx 2rpx 4rpx 0rpx rgba(0, 0, 0, 0.5);
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.title {
|
||||
border-bottom: 1px solid #efefef;
|
||||
padding-bottom: 24rpx;
|
||||
margin-bottom: 8rpx;
|
||||
|
||||
view {
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
|
||||
view {
|
||||
padding-top: 16rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin-top: 30rpx;
|
||||
|
||||
view {
|
||||
width: 300rpx;
|
||||
height: 64rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 28rpx;
|
||||
text-align: center;
|
||||
line-height: 64rpx;
|
||||
}
|
||||
|
||||
.entrust {
|
||||
background: #FFFFFF;
|
||||
border: 2rpx solid #01508B;
|
||||
box-sizing: border-box;
|
||||
color: #01508B;
|
||||
}
|
||||
|
||||
.handle {
|
||||
background: #01508B;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.refused {
|
||||
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.agreed {
|
||||
|
||||
color: #01508B;
|
||||
}
|
||||
|
||||
.handled {
|
||||
justify-content: flex-end;
|
||||
margin-top: 30rpx;
|
||||
|
||||
view {
|
||||
width: 150rpx;
|
||||
height: 64rpx;
|
||||
background: #EFEFEF;
|
||||
border-radius: 8rpx;
|
||||
text-align: center;
|
||||
line-height: 64rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
169
pages/views/zhongheguanli/zhiban/index.vue
Normal file
@ -0,0 +1,169 @@
|
||||
<template>
|
||||
<view :class="[{'gray':store.isgray==1}]">
|
||||
<view style="margin-top: 10px;margin-bottom: 10px;">
|
||||
<picker fields="month" mode="date" @change="bindPickerChange" :value="index">
|
||||
<view class="date">{{index}} 点击选择月份</view>
|
||||
</picker>
|
||||
</view>
|
||||
<uni-row>
|
||||
<uni-col :span="7">
|
||||
<view class="titleStyle">
|
||||
日期
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="titleStyle">
|
||||
带班领导
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="titleStyle">
|
||||
值班领导
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="9">
|
||||
<view class="titleStyle">
|
||||
值班干部
|
||||
</view>
|
||||
</uni-col>
|
||||
</uni-row>
|
||||
<uni-row>
|
||||
<view v-for="(item,index) in zhibanArr">
|
||||
<uni-col :span="7">
|
||||
<view class="dataStyle">
|
||||
{{item.date}}
|
||||
</view>
|
||||
</uni-col>
|
||||
<uni-col :span="4">
|
||||
<view class="dataStyle">
|
||||
{{item.dbld_dictText}}
|
||||
</view>
|
||||
</uni-col><uni-col :span="4">
|
||||
<view class="dataStyle">
|
||||
{{item.zbld_dictText}}
|
||||
</view>
|
||||
</uni-col><uni-col :span="9">
|
||||
<view class="dataStyle">
|
||||
{{item.zbgbrealname}}
|
||||
</view>
|
||||
</uni-col>
|
||||
</view>
|
||||
</uni-row>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref
|
||||
} from 'vue';
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
zhibanQueryApi
|
||||
} from '@/api/api.js';
|
||||
import {
|
||||
useStore
|
||||
} from '@/store';
|
||||
const store = useStore()
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
|
||||
let column = ref([{
|
||||
name: 'date',
|
||||
label: '日期',
|
||||
width: 70,
|
||||
align: 'center'
|
||||
},
|
||||
|
||||
{
|
||||
name: 'dbld_dictText',
|
||||
label: '带班领导',
|
||||
align: 'center',
|
||||
width: 60
|
||||
},
|
||||
{
|
||||
name: 'zbld_dictText',
|
||||
label: '值班领导',
|
||||
align: 'center',
|
||||
width: 60
|
||||
},
|
||||
{
|
||||
name: 'zbgbrealname',
|
||||
label: '值班干部',
|
||||
align: 'center',
|
||||
width: 150
|
||||
}
|
||||
|
||||
])
|
||||
|
||||
const zhibanArr = ref([])
|
||||
onLoad(() => {
|
||||
zhibanQuery()
|
||||
})
|
||||
const index = ref(dayjs().format("YYYY-MM"))
|
||||
const bindPickerChange = (e) => {
|
||||
index.value = e.detail.value
|
||||
zhibanQuery()
|
||||
}
|
||||
const zhibanQuery = () => {
|
||||
let [year, month] = index.value.split('-')
|
||||
zhibanQueryApi({
|
||||
year,
|
||||
month
|
||||
}).then((res) => {
|
||||
zhibanArr.value = res.result.records
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 使用变量来定义颜色,便于统一修改
|
||||
$primary-color: #0056b3;
|
||||
$secondary-color: #f2f9fc;
|
||||
$border-color: #d1e7ff;
|
||||
$text-color: #333;
|
||||
|
||||
.date {
|
||||
width: 100%; // 让宽度更具响应性
|
||||
padding: 20rpx 30rpx;
|
||||
font-size: 28rpx;
|
||||
color: $text-color;
|
||||
text-align: center; // 文字居中
|
||||
background: $secondary-color; // 使用变量代替直接颜色值
|
||||
border-bottom: 1px solid $border-color; // 调整边框颜色
|
||||
}
|
||||
|
||||
.titleStyle {
|
||||
font-size: 14px; // 增加字体大小以提高可读性
|
||||
color: $primary-color; // 更清晰的颜色
|
||||
line-height: 2;
|
||||
height: auto; // 根据内容自动调整高度
|
||||
background: $secondary-color;
|
||||
text-align: center; // 文字居中
|
||||
vertical-align: middle;
|
||||
border-left: 1px solid $border-color;
|
||||
border-bottom: 1px solid $border-color;
|
||||
}
|
||||
|
||||
/* 内容样式 */
|
||||
.dataStyle {
|
||||
font-size: 14px;
|
||||
color: $text-color;
|
||||
line-height: 1.5; // 改进行高以提升阅读体验
|
||||
height: auto; // 动态高度
|
||||
font-weight: normal; // 减少字体重量
|
||||
text-align: center; // 文字居中
|
||||
vertical-align: middle;
|
||||
border-bottom: 1px solid $border-color;
|
||||
border-left: 1px solid $border-color;
|
||||
padding: 10rpx; // 添加内边距
|
||||
|
||||
// 当内容超出容器大小时,显示省略号
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
</style>
|
||||
BIN
static/checkin/chenggong.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
static/checkin/circle1.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
static/checkin/circle2.png
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
static/checkin/circle3.png
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
static/checkin/circle4.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
static/checkin/position1.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
static/checkin/position2.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
static/checkin/position3.png
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
static/checkin/position4.png
Normal file
|
After Width: | Height: | Size: 8.8 KiB |
BIN
static/checkin/shibai.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
static/index/back.png
Normal file
|
After Width: | Height: | Size: 570 B |
BIN
static/index/calendar.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
static/index/eye.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
static/index/line.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
static/index/menu.png
Normal file
|
After Width: | Height: | Size: 791 B |
BIN
static/index/position.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
static/index/rili.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
static/line.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
static/login/checked.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
static/login/eye-off.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
static/login/eye.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |