diff --git a/.env.production b/.env.production index 788deaf..6b0e14d 100644 --- a/.env.production +++ b/.env.production @@ -2,7 +2,7 @@ ENV = 'production' # base api -VUE_APP_DOMIAN=http://192.168.60.99:9003/ +VUE_APP_DOMIAN='' VUE_APP_BASE_API = '' VUE_APP_OUT_URL = http://192.168.60.18:2021 VUE_APP_UPLOAD=http://192.168.60.99:9003/api/admin/upload-file diff --git a/.env.staging b/.env.staging index a5121e9..f2eb87d 100644 --- a/.env.staging +++ b/.env.staging @@ -4,7 +4,7 @@ NODE_ENV = production ENV = 'staging' # base api -VUE_APP_DOMIAN=http://hdcontract.ali251.langye.net/ +VUE_APP_DOMIAN='' VUE_APP_BASE_API = '' VUE_APP_UPLOAD=http://hdcontract.ali251.langye.net/api/admin/upload-file diff --git a/package.json b/package.json index ea892a4..91537c8 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "docx-parser": "^0.2.1", "docx2html": "^1.3.2", "docxtemplater": "^3.61.1", + "echarts": "^5.0.0", "element-ui": "2.13.2", "file-saver": "^2.0.5", "html2canvas": "^1.4.1", diff --git a/src/api/budget/plantype.js b/src/api/budget/plantype.js new file mode 100644 index 0000000..933692b --- /dev/null +++ b/src/api/budget/plantype.js @@ -0,0 +1,60 @@ +import request from "@/utils/request"; +function customParamsSerializer(params) { + let result = ''; + for (let key in params) { + if (params.hasOwnProperty(key)) { + if (Array.isArray(params[key])) { + params[key].forEach((item,index) => { + if(item.key){ + result += `${key}[${index}][key]=${item.key}&${key}[${index}][op]=${item.op}&${key}[${index}][value]=${item.value}&`; + + }else{ + result +=`${key}[${index}]=${item}&` + } + }); + } else { + result += `${key}=${params[key]}&`; + } + } + } + return result.slice(0, -1); +} + +export function index(params,isLoading = false) { + return request({ + method: "get", + url: "/api/admin/plan-type/index", + params, + paramsSerializer: customParamsSerializer, + isLoading + }) +} + +export function show(params, isLoading = true) { + return request({ + method: "get", + url: "/api/admin/plan-type/show", + params, + isLoading + }) +} + +export function save(data) { + return request({ + method: "post", + url: "/api/admin/plan-type/save", + data + }) +} + +export function destroy(params) { + return request({ + method: "get", + url: "/api/admin/plan-type/destroy", + params + }) +} + + + + diff --git a/src/components/Progress/index.vue b/src/components/Progress/index.vue new file mode 100644 index 0000000..854c834 --- /dev/null +++ b/src/components/Progress/index.vue @@ -0,0 +1,179 @@ + + + + + diff --git a/src/components/XyDialog/index.vue b/src/components/XyDialog/index.vue index f185beb..8f2438c 100644 --- a/src/components/XyDialog/index.vue +++ b/src/components/XyDialog/index.vue @@ -111,7 +111,8 @@ export default { Object.keys(form).map((key)=>{ formItems.push( + prop={key} + class={key}> {eval(`{$scopedSlots.${key} ? $scopedSlots.${key}() : ''}`)} ) @@ -194,7 +195,7 @@ export default { align-items: center; margin-right: 80px; &-label{ - + min-width: 120px; padding: 0 20px; } &-content{ diff --git a/src/icons/svg/caidan.svg b/src/icons/svg/caidan.svg new file mode 100644 index 0000000..69bbaf4 --- /dev/null +++ b/src/icons/svg/caidan.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/calendar-check.svg b/src/icons/svg/calendar-check.svg new file mode 100644 index 0000000..a5c78db --- /dev/null +++ b/src/icons/svg/calendar-check.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/notice.svg b/src/icons/svg/notice.svg new file mode 100644 index 0000000..010a8a3 --- /dev/null +++ b/src/icons/svg/notice.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/yuan.svg b/src/icons/svg/yuan.svg new file mode 100644 index 0000000..100c968 --- /dev/null +++ b/src/icons/svg/yuan.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/zhangdan.svg b/src/icons/svg/zhangdan.svg new file mode 100644 index 0000000..1cebff5 --- /dev/null +++ b/src/icons/svg/zhangdan.svg @@ -0,0 +1 @@ + diff --git a/src/icons/svg/zhifu.svg b/src/icons/svg/zhifu.svg new file mode 100644 index 0000000..98f39e1 --- /dev/null +++ b/src/icons/svg/zhifu.svg @@ -0,0 +1 @@ + diff --git a/src/mixins/resize.js b/src/mixins/resize.js new file mode 100644 index 0000000..234953b --- /dev/null +++ b/src/mixins/resize.js @@ -0,0 +1,55 @@ +import { debounce } from '@/utils' + +export default { + data() { + return { + $_sidebarElm: null, + $_resizeHandler: null + } + }, + mounted() { + this.$_resizeHandler = debounce(() => { + if (this.chart) { + this.chart.resize() + } + }, 100) + this.$_initResizeEvent() + this.$_initSidebarResizeEvent() + }, + beforeDestroy() { + this.$_destroyResizeEvent() + this.$_destroySidebarResizeEvent() + }, + // to fixed bug when cached by keep-alive + // https://github.com/PanJiaChen/vue-element-admin/issues/2116 + activated() { + this.$_initResizeEvent() + this.$_initSidebarResizeEvent() + }, + deactivated() { + this.$_destroyResizeEvent() + this.$_destroySidebarResizeEvent() + }, + methods: { + // use $_ for mixins properties + // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential + $_initResizeEvent() { + window.addEventListener('resize', this.$_resizeHandler) + }, + $_destroyResizeEvent() { + window.removeEventListener('resize', this.$_resizeHandler) + }, + $_sidebarResizeHandler(e) { + if (e.propertyName === 'width') { + this.$_resizeHandler() + } + }, + $_initSidebarResizeEvent() { + this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0] + this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler) + }, + $_destroySidebarResizeEvent() { + this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler) + } + } +} diff --git a/src/utils/index.js b/src/utils/index.js index 4129bd2..4a19b38 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -1,179 +1,226 @@ -/** - * Created by PanJiaChen on 16/11/18. - */ - -/** - * Parse the time to string - * @param {(Object|string|number)} time - * @param {string} cFormat - * @returns {string | null} - */ -export function parseTime(time, cFormat) { - if (arguments.length === 0 || !time) { - return null - } - const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}' - let date - if (typeof time === 'object') { - date = time - } else { - if ((typeof time === 'string')) { - if ((/^[0-9]+$/.test(time))) { - // support "1548221490638" - time = parseInt(time) - } else { - // support safari - // https://stackoverflow.com/questions/4310953/invalid-date-in-safari - time = time.replace(new RegExp(/-/gm), '/') - } - } - - if ((typeof time === 'number') && (time.toString().length === 10)) { - time = time * 1000 - } - date = new Date(time) - } - const formatObj = { - y: date.getFullYear(), - m: date.getMonth() + 1, - d: date.getDate(), - h: date.getHours(), - i: date.getMinutes(), - s: date.getSeconds(), - a: date.getDay() - } - const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => { - const value = formatObj[key] - // Note: getDay() returns 0 on Sunday - if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] } - return value.toString().padStart(2, '0') - }) - return time_str -} - -/** - * @param {number} time - * @param {string} option - * @returns {string} - */ -export function formatTime(time, option) { - if (('' + time).length === 10) { - time = parseInt(time) * 1000 - } else { - time = +time - } - const d = new Date(time) - const now = Date.now() - - const diff = (now - d) / 1000 - - if (diff < 30) { - return '刚刚' - } else if (diff < 3600) { - // less 1 hour - return Math.ceil(diff / 60) + '分钟前' - } else if (diff < 3600 * 24) { - return Math.ceil(diff / 3600) + '小时前' - } else if (diff < 3600 * 24 * 2) { - return '1天前' - } - if (option) { - return parseTime(time, option) - } else { - return ( - d.getMonth() + - 1 + - '月' + - d.getDate() + - '日' + - d.getHours() + - '时' + - d.getMinutes() + - '分' - ) - } -} - -/** - * @param {string} url - * @returns {Object} - */ -export function param2Obj(url) { - const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ') - if (!search) { - return {} - } - const obj = {} - const searchArr = search.split('&') - searchArr.forEach(v => { - const index = v.indexOf('=') - if (index !== -1) { - const name = v.substring(0, index) - const val = v.substring(index + 1, v.length) - obj[name] = val - } - }) - return obj -} - -//防抖 -export function debounce(fn,delay=500){ - let timer = null - return function _debounce() { - if (timer) clearTimeout(timer) - timer = setTimeout(() => { - fn() - }, delay) - } -} - -//金额分隔 -export function moneyFormatter(money,precision=2){ - return Number(money).toFixed(precision).replace(/(\d)(?=(\d{3})+\.)/g, '$1,') -} -//金额分隔复原 -export function moneyRecovery(money){ - return parseFloat(money.replace(/[^\d\.-]/g, "")); -} - -export function deepCopy(data) { - //string,number,bool,null,undefined,symbol - //object,array,date - if (data && typeof data === "object") { - //针对函数的拷贝 - if (typeof data === "function") { - let tempFunc = data.bind(null); - tempFunc.prototype = deepCopy(data.prototype); - return tempFunc; - } - - switch (Object.prototype.toString.call(data)) { - case "[object String]": - return data.toString(); - case "[object Number]": - return Number(data.toString()); - case "[object Boolean]": - return Boolean(data.toString()); - case "[object Date]": - return new Date(data.getTime()); - case "[object Array]": - let arr = []; - for (let i = 0; i < data.length; i++) { - arr[i] = deepCopy(data[i]); - } - return arr; - - //js自带对象或用户自定义类实例 - case "[object Object]": - let obj = {}; - for (let key in data) { - //会遍历原型链上的属性方法,可以用hasOwnProperty来控制 (obj.hasOwnProperty(prop) - obj[key] = deepCopy(data[key]); - } - return obj; - } - } else { - //string,number,bool,null,undefined,symbol - return data; - } +/** + * Created by PanJiaChen on 16/11/18. + */ + +/** + * Parse the time to string + * @param {(Object|string|number)} time + * @param {string} cFormat + * @returns {string | null} + */ +export function parseTime(time, cFormat) { + if (arguments.length === 0 || !time) { + return null + } + const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}' + let date + if (typeof time === 'object') { + date = time + } else { + if ((typeof time === 'string')) { + if ((/^[0-9]+$/.test(time))) { + // support "1548221490638" + time = parseInt(time) + } else { + // support safari + // https://stackoverflow.com/questions/4310953/invalid-date-in-safari + time = time.replace(new RegExp(/-/gm), '/') + } + } + + if ((typeof time === 'number') && (time.toString().length === 10)) { + time = time * 1000 + } + date = new Date(time) + } + const formatObj = { + y: date.getFullYear(), + m: date.getMonth() + 1, + d: date.getDate(), + h: date.getHours(), + i: date.getMinutes(), + s: date.getSeconds(), + a: date.getDay() + } + const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => { + const value = formatObj[key] + // Note: getDay() returns 0 on Sunday + if (key === 'a') { + return ['日', '一', '二', '三', '四', '五', '六'][value] + } + return value.toString().padStart(2, '0') + }) + return time_str +} + +/** + * @param {number} time + * @param {string} option + * @returns {string} + */ +export function formatTime(time, option) { + if (('' + time).length === 10) { + time = parseInt(time) * 1000 + } else { + time = +time + } + const d = new Date(time) + const now = Date.now() + + const diff = (now - d) / 1000 + + if (diff < 30) { + return '刚刚' + } else if (diff < 3600) { + // less 1 hour + return Math.ceil(diff / 60) + '分钟前' + } else if (diff < 3600 * 24) { + return Math.ceil(diff / 3600) + '小时前' + } else if (diff < 3600 * 24 * 2) { + return '1天前' + } + if (option) { + return parseTime(time, option) + } else { + return ( + d.getMonth() + + 1 + + '月' + + d.getDate() + + '日' + + d.getHours() + + '时' + + d.getMinutes() + + '分' + ) + } +} + +/** + * @param {string} url + * @returns {Object} + */ +export function param2Obj(url) { + const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ') + if (!search) { + return {} + } + const obj = {} + const searchArr = search.split('&') + searchArr.forEach(v => { + const index = v.indexOf('=') + if (index !== -1) { + const name = v.substring(0, index) + const val = v.substring(index + 1, v.length) + obj[name] = val + } + }) + return obj +} + +//防抖 +export function debounce(fn, delay = 500) { + let timer = null + return function _debounce() { + if (timer) clearTimeout(timer) + timer = setTimeout(() => { + fn() + }, delay) + } +} + +//金额分隔 +export function moneyFormatter(money, precision = 2) { + if(Number(money)===0){ + return 0 + } + return Number(money).toFixed(precision).replace(/(\d)(?=(\d{3})+\.)/g, '$1,') +} +//金额分隔复原 +export function moneyRecovery(money) { + return parseFloat(money.replace(/[^\d\.-]/g, "")); +} + +export function deepCopy(data) { + //string,number,bool,null,undefined,symbol + //object,array,date + if (data && typeof data === "object") { + //针对函数的拷贝 + if (typeof data === "function") { + let tempFunc = data.bind(null); + tempFunc.prototype = deepCopy(data.prototype); + return tempFunc; + } + + switch (Object.prototype.toString.call(data)) { + case "[object String]": + return data.toString(); + case "[object Number]": + return Number(data.toString()); + case "[object Boolean]": + return Boolean(data.toString()); + case "[object Date]": + return new Date(data.getTime()); + case "[object Array]": + let arr = []; + for (let i = 0; i < data.length; i++) { + arr[i] = deepCopy(data[i]); + } + return arr; + + //js自带对象或用户自定义类实例 + case "[object Object]": + let obj = {}; + for (let key in data) { + //会遍历原型链上的属性方法,可以用hasOwnProperty来控制 (obj.hasOwnProperty(prop) + obj[key] = deepCopy(data[key]); + } + return obj; + } + } else { + //string,number,bool,null,undefined,symbol + return data; + } + +} +export function requestToForm(requestObj, form) { + // 获取a对象中属性的顺序和值 + let aKeys = Object.keys(form); + let aValues = aKeys.map(key => form[key]); + + // 遍历b对象,将属性等于a中属性值的对象深拷贝给a中的相应属性 + for (let i = 0; i < aKeys.length; i++) { + let key = aKeys[i]; + let value = aValues[i]; + if (requestObj[key] === value) { + // 深拷贝对象 + Object.assign(form, { + [key]: deepCopy(requestObj[key]) + }); + } + } + + // 遍历b对象,将b中独有的属性按照a的顺序插入到a中 + for (let key in requestObj) { + if (!form[key]) { + // 深拷贝属性值 + Object.assign(form, { + [key]: deepCopy(requestObj[key]) + }); + } + } + return form +} +export function buildTree(data, pid = 0) { + const tree = []; + for (const item of data) { + if (item.pid === pid) { + const children = buildTree(data, item.id); + if (children.length > 0) { + item.children = children; + } + tree.push(item); + } + } + return tree; } diff --git a/src/views/budget/budgetList.vue b/src/views/budget/budgetList.vue index 89c80c3..3bd6daa 100644 --- a/src/views/budget/budgetList.vue +++ b/src/views/budget/budgetList.vue @@ -16,22 +16,28 @@ placement="bottom" style="width: 130px" type="year" - @on-change="(e) => (select.year = e)" + @on-change="(e) => (select.year = e,changeYear(e),getBudgets())" > 预算类型 - + + + + + + 科室 @@ -280,49 +286,55 @@ -