)P%4_tSB@AiFgE7%FN$Ek2u2|p_NK7()HR6hvoK=M{Y7{!l>P<_F*$8%ODokN|4
z2!8-+KCYEMi@ImSQjn?LMhn>vxc4~jJZJ9)r@*D~S9k(k3%z63(%*dVP`=|n4u1gG
z(v=|@SB>gBSoNd6hP8erWgYjG-Vw6cE!yrfWUP>--CBC3$n&T7JRS{!Q=7oObq{?0sn*G~FD^gvH
>I&@$DP4c_DTfqz3D{aR7>0d!asTGr>m
z7HnSvUn9(FGtYZF#Ja82Ike&U+!-E%YC1YUz3V>)zF}Ph?rT%vaIlY^a6bGIEN7i+
zGGm@)_khG+t?ct)%MN|&Ak4bXUP9Tr*ZpWi!j0iDST3ej>U+#1+!Q>6N1qt#zlY&m
z*cZGfI7j_^yE=Nd=@;uaIG((#tPQsBTTiLX((l>ixi_lo09pM)NB9T*(kA}RLL0iT
zm-fH>`wjBAKu^f-wn_K`lX^=(*x@gUJvT=S2z&XfZS(L>O`6Q@vXe_
zzCK0TQLqdoWh*K-3KB#Ayl;8lnhE8$h;ePA4|4a~I)U8@pM)sW(7z#dL8`6Ei}l<2
z_T6t{Ov|lIs1WLJMd-c}_3=&Vx8Qn{IwtFFbGX){uiDrCZUpB;rMuVdq%RG*x?%ai
z2MNo4AMNg1>)h5KEw?*uM4i0Tx$en7VINo$a`kbv6t>?m4)oO(@ESxP&ER`Q$kkoT
z!zB0zL|JK}Ys|MH8E1sK+R9Q`nSm_`d*BgptzQL_yex7?Ynf;RLjQ*9T6-0^M!pOk
zkh$xY4SbU@&FAIm?#I``=Amxp_G%Rj@?2jg!)4(8;O#If&v&)#Q7s>vMBh0MeEa+b
zI5#ufin7X>0JlK7pR2{6p}hCLrp(7EhtPMW4%idcftK$z)oeUc^01SB7!PZKZ-$vv
zw;Zev)y|cb#=)_nZl-o>6$-K(x9%&Rbr<-(meHD!AMCEZr$Z$_S4#8D;riSJ4T>U^
zRZ7zYFA!AK0wp#-ns4v>mHb_v=2`q}v2N7{7Gw^43j{wdMR+!N&nx$LrMUNiuY+fD
z_Z!#iNiB8a3k@ebo-RFI;Yr88ZBlN
zwd^sP6iAF8ETBF;nyr|fROq(#q%{Au7dzD#<8<3jcgOfxtdck@B#bG{MqGb!dZP3C
zi_<_K;$v;X4s4W+rjXX&J5B@eqiN){_f9A(m-MZ>Z9;E*;?1J(XSYr0=}7uQX@6Z4
zdO8zv#b}{tTu&md=no{0yD1UZ8S>|ho2Izvk3wPWG_{Mx3xz2sDn1r36sDby_&D$o
zGIJ{0Vv+cJacWPZdVk!`cN$YpM`0Gt6{{2FYZlEV)q9NViemNPpv1N$7Hy!SG*7hO
zgxE-NeMxQp>FiC!b;o#nZ_=3<#a_X%A!S^5srzXlaer5T`LSJy56YN0rVCs3w`Lse
zd-{v>f$h4Iczdy4dx&dOJsaahlWuerhf~qyJ&CdSH%x)PF@6wFY=kCB95K{Neq-!?
zZ!jsJ$4=p&FflD~Q!(D*x4%cH6lP+>V#N4~g=vM^bNxT_#KN(KIdlF0^7KMmVNOR<
zzK7uD>2qRblx!#N0QaZT%IPcWRvgrw{c*FC&KDQIe*aR>*7}lcyIG8P7vl)*E_EQi
zP2!=rX6n|WJ;mb2yVR$vG>-TfB~OQ@$Ej*3tlv=_Yh9YYyXb*#>UODaPjOJY#wYRK
zr0dCo*WF%t5s$P}sxX_nJ?(|wg0r6AoMODY(+uOt>g_0Wbn+BiG%6O|7~=FOR7-{nh33Y|pm-cb$rS3E8&5nk
zAl_cIke1}vqsP1FmhaUAJp<#X_qDA$x4pugu~?v|s9yo&%pOD6uvGG6cqW6Y2QkU7
yjUpY4djc3FbvZE6s*zz?ME;vU;hudie4-L
literal 0
HcmV?d00001
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 0000000..4123528
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+ <%= htmlWebpackPlugin.options.title %>
+
+
+
+
+
+
+
diff --git a/src/App.vue b/src/App.vue
new file mode 100644
index 0000000..d96c083
--- /dev/null
+++ b/src/App.vue
@@ -0,0 +1,53 @@
+
+
+
+
+
+
diff --git a/src/assets/daochu.png b/src/assets/daochu.png
new file mode 100644
index 0000000000000000000000000000000000000000..6c30158272a8c0476eda903883fb4d97ed611794
GIT binary patch
literal 359
zcmV-t0hs=YP)Px$AxT6*R7gwhmOW0xKoEt$M+zbuasxt%+;9V&n{Wd{Mas|_QII1fCrEC<9>FOh
zO3V#tuxP@fRpcllKeD{GBP6@EcE5SgZ)PlNepEA$EnwJx@6b+Pz;^wLQNs7xy%}A8
zZr-yE9K40%=hY9kI&C@Wndr(iz{b+td8#fn*3Lm)#QA15l>se0vSg+fGvFeFRthvx
zFmyvh?bJbU%IL!nAldZ+EsRYRjI(#)!(t?H=cUlu=2YZOOgLEFvLrUoL0o9k90Qnu
z-DxRkQo5ywtjyG}HqF;mC@dp1dzo2V&|)fBuQjjG98_qD-Tsu+sipDv6;qkQ23V-^
z^G=w55E|FKr|D4Qx`?XvYO=)UDd_*b= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) {
+ for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);
+ }
+ });
+
+ //Handle Row Span
+ if (rowspan || colspan) {
+ rowspan = rowspan || 1;
+ colspan = colspan || 1;
+ ranges.push({s: {r: R, c: outRow.length}, e: {r: R + rowspan - 1, c: outRow.length + colspan - 1}});
+ }
+ ;
+
+ //Handle Value
+ outRow.push(cellValue !== "" ? cellValue : null);
+
+ //Handle Colspan
+ if (colspan) for (var k = 0; k < colspan - 1; ++k) outRow.push(null);
+ }
+ out.push(outRow);
+ }
+ return [out, ranges];
+};
+
+function datenum(v, date1904) {
+ if (date1904) v += 1462;
+ var epoch = Date.parse(v);
+ return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
+}
+
+function sheet_from_array_of_arrays(data, opts) {
+ var ws = {};
+ var range = {s: {c: 10000000, r: 10000000}, e: {c: 0, r: 0}};
+ for (var R = 0; R != data.length; ++R) {
+ for (var C = 0; C != data[R].length; ++C) {
+ if (range.s.r > R) range.s.r = R;
+ if (range.s.c > C) range.s.c = C;
+ if (range.e.r < R) range.e.r = R;
+ if (range.e.c < C) range.e.c = C;
+ var cell = {v: data[R][C]};
+ if (cell.v == null) continue;
+ var cell_ref = XLSX.utils.encode_cell({c: C, r: R});
+
+ if (typeof cell.v === 'number') cell.t = 'n';
+ else if (typeof cell.v === 'boolean') cell.t = 'b';
+ else if (cell.v instanceof Date) {
+ cell.t = 'n';
+ cell.z = XLSX.SSF._table[14];
+ cell.v = datenum(cell.v);
+ }
+ else cell.t = 's';
+
+ ws[cell_ref] = cell;
+ }
+ }
+ if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
+ return ws;
+}
+
+function Workbook() {
+ if (!(this instanceof Workbook)) return new Workbook();
+ this.SheetNames = [];
+ this.Sheets = {};
+}
+
+function s2ab(s) {
+ var buf = new ArrayBuffer(s.length);
+ var view = new Uint8Array(buf);
+ for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
+ return buf;
+}
+
+export function export_table_to_excel(id) {
+ var theTable = document.getElementById(id);
+ console.log('a')
+ var oo = generateArray(theTable);
+ var ranges = oo[1];
+
+ /* original data */
+ var data = oo[0];
+ var ws_name = "SheetJS";
+ console.log(data);
+
+ var wb = new Workbook(), ws = sheet_from_array_of_arrays(data);
+
+ /* add ranges to worksheet */
+ // ws['!cols'] = ['apple', 'banan'];
+ ws['!merges'] = ranges;
+
+ /* add worksheet to workbook */
+ wb.SheetNames.push(ws_name);
+ wb.Sheets[ws_name] = ws;
+
+ var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'});
+
+ saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), "test.xlsx")
+}
+
+function formatJson(jsonData) {
+ console.log(jsonData)
+}
+export function export_json_to_excel(th, jsonData, defaultTitle) {
+
+ /* original data */
+
+ var data = jsonData;
+ data.unshift(th);
+ var ws_name = "SheetJS";
+
+ var wb = new Workbook(), ws = sheet_from_array_of_arrays(data);
+
+
+ /* add worksheet to workbook */
+ wb.SheetNames.push(ws_name);
+ wb.Sheets[ws_name] = ws;
+
+ var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'});
+ var title = defaultTitle || '列表'
+ saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), title + ".xlsx")
+}
\ No newline at end of file
diff --git a/src/assets/excel/Export2Excel.js b/src/assets/excel/Export2Excel.js
new file mode 100644
index 0000000..38c6c97
--- /dev/null
+++ b/src/assets/excel/Export2Excel.js
@@ -0,0 +1,219 @@
+import { saveAs } from 'file-saver'
+import XLSX from 'xlsx'
+
+function generateArray(table) {
+ var out = [];
+ var rows = table.querySelectorAll('tr');
+ var ranges = [];
+ for (var R = 0; R < rows.length; ++R) {
+ var outRow = [];
+ var row = rows[R];
+ var columns = row.querySelectorAll('td');
+ for (var C = 0; C < columns.length; ++C) {
+ var cell = columns[C];
+ var colspan = cell.getAttribute('colspan');
+ var rowspan = cell.getAttribute('rowspan');
+ var cellValue = cell.innerText;
+ if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue;
+
+ //Skip ranges
+ ranges.forEach(function (range) {
+ if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) {
+ for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);
+ }
+ });
+
+ //Handle Row Span
+ if (rowspan || colspan) {
+ rowspan = rowspan || 1;
+ colspan = colspan || 1;
+ ranges.push({
+ s: {
+ r: R,
+ c: outRow.length
+ },
+ e: {
+ r: R + rowspan - 1,
+ c: outRow.length + colspan - 1
+ }
+ });
+ };
+
+ //Handle Value
+ outRow.push(cellValue !== "" ? cellValue : null);
+
+ //Handle Colspan
+ if (colspan)
+ for (var k = 0; k < colspan - 1; ++k) outRow.push(null);
+ }
+ out.push(outRow);
+ }
+ return [out, ranges];
+};
+
+function datenum(v, date1904) {
+ if (date1904) v += 1462;
+ var epoch = Date.parse(v);
+ return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
+}
+
+function sheet_from_array_of_arrays(data, opts) {
+ var ws = {};
+ var range = {
+ s: {
+ c: 10000000,
+ r: 10000000
+ },
+ e: {
+ c: 0,
+ r: 0
+ }
+ };
+ for (var R = 0; R != data.length; ++R) {
+ for (var C = 0; C != data[R].length; ++C) {
+ if (range.s.r > R) range.s.r = R;
+ if (range.s.c > C) range.s.c = C;
+ if (range.e.r < R) range.e.r = R;
+ if (range.e.c < C) range.e.c = C;
+ var cell = {
+ v: data[R][C]
+ };
+ if (cell.v == null) continue;
+ var cell_ref = XLSX.utils.encode_cell({
+ c: C,
+ r: R
+ });
+
+ if (typeof cell.v === 'number') cell.t = 'n';
+ else if (typeof cell.v === 'boolean') cell.t = 'b';
+ else if (cell.v instanceof Date) {
+ cell.t = 'n';
+ cell.z = XLSX.SSF._table[14];
+ cell.v = datenum(cell.v);
+ } else cell.t = 's';
+
+ ws[cell_ref] = cell;
+ }
+ }
+ if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
+ return ws;
+}
+
+function Workbook() {
+ if (!(this instanceof Workbook)) return new Workbook();
+ this.SheetNames = [];
+ this.Sheets = {};
+}
+
+function s2ab(s) {
+ var buf = new ArrayBuffer(s.length);
+ var view = new Uint8Array(buf);
+ for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
+ return buf;
+}
+
+export function export_table_to_excel(id) {
+ var theTable = document.getElementById(id);
+ var oo = generateArray(theTable);
+ var ranges = oo[1];
+
+ /* original data */
+ var data = oo[0];
+ var ws_name = "SheetJS";
+
+ var wb = new Workbook(),
+ ws = sheet_from_array_of_arrays(data);
+
+ /* add ranges to worksheet */
+ // ws['!cols'] = ['apple', 'banan'];
+ ws['!merges'] = ranges;
+
+ /* add worksheet to workbook */
+ wb.SheetNames.push(ws_name);
+ wb.Sheets[ws_name] = ws;
+
+ var wbout = XLSX.write(wb, {
+ bookType: 'xlsx',
+ bookSST: false,
+ type: 'binary'
+ });
+
+ saveAs(new Blob([s2ab(wbout)], {
+ type: "application/octet-stream"
+ }), "test.xlsx")
+}
+
+export function export_json_to_excel({
+ multiHeader = [],
+ header,
+ data,
+ filename,
+ merges = [],
+ autoWidth = true,
+ bookType = 'xlsx'
+} = {}) {
+ /* original data */
+ filename = filename || 'excel-list'
+ data = [...data]
+ data.unshift(header);
+
+ for (let i = multiHeader.length - 1; i > -1; i--) {
+ data.unshift(multiHeader[i])
+ }
+
+ var ws_name = "SheetJS";
+ var wb = new Workbook(),
+ ws = sheet_from_array_of_arrays(data);
+
+ if (merges.length > 0) {
+ if (!ws['!merges']) ws['!merges'] = [];
+ merges.forEach(item => {
+ ws['!merges'].push(XLSX.utils.decode_range(item))
+ })
+ }
+
+ if (autoWidth) {
+ /*设置worksheet每列的最大宽度*/
+ const colWidth = data.map(row => row.map(val => {
+ /*先判断是否为null/undefined*/
+ if (val == null) {
+ return {
+ 'wch': 10
+ };
+ }
+ /*再判断是否为中文*/
+ else if (val.toString().charCodeAt(0) > 255) {
+ return {
+ 'wch': val.toString().length * 2
+ };
+ } else {
+ return {
+ 'wch': val.toString().length
+ };
+ }
+ }))
+ /*以第一行为初始值*/
+ let result = colWidth[0];
+ for (let i = 1; i < colWidth.length; i++) {
+ for (let j = 0; j < colWidth[i].length; j++) {
+ if (result[j]['wch'] < colWidth[i][j]['wch']) {
+ result[j]['wch'] = colWidth[i][j]['wch'];
+ }
+ }
+ }
+ ws['!cols'] = result;
+ }
+
+ /* add worksheet to workbook */
+ wb.SheetNames.push(ws_name);
+ wb.Sheets[ws_name] = ws;
+
+ var wbout = XLSX.write(wb, {
+ bookType: bookType,
+ bookSST: false,
+ type: 'binary'
+ });
+ saveAs(new Blob([s2ab(wbout)], {
+ type: "application/octet-stream"
+ }), `${filename}.${bookType}`);
+}
\ No newline at end of file
diff --git a/src/assets/icon/iconfont.ttf b/src/assets/icon/iconfont.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..f2d0a598659f223635c5678ad6fc673fd3da04ef
GIT binary patch
literal 9020
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
literal 0
HcmV?d00001
diff --git a/src/assets/style/global.scss b/src/assets/style/global.scss
new file mode 100644
index 0000000..2b65889
--- /dev/null
+++ b/src/assets/style/global.scss
@@ -0,0 +1,260 @@
+html,
+body {
+ margin: 0;
+ padding: 0;
+ color: #333;
+ box-sizing: border-box;
+}
+
+a {
+ text-decoration: none;
+}
+
+/*去掉项目标签*/
+ul {
+ list-style-type: none;
+}
+
+.el-main {
+ padding: 0px !important;
+}
+
+.main-container {
+ width: -moz-available;
+ width: -webkit-fill-available;
+ width: stretch;
+ height: -moz-available;
+ height: -webkit-fill-available;
+ height: stretch;
+ height: 100% !important;
+}
+
+.min-height-fill4parent {
+ height: -moz-available;
+ height: -webkit-fill-available;
+ height: stretch;
+}
+
+/*成本管理样式*/
+.bg_white {
+ background-color: #FFF
+}
+
+.m-t-20 {
+ margin-top: 20px
+}
+
+.m-t-10 {
+ margin-top: 10px
+}
+
+.table_90 {
+ width: -moz-calc(100% - 24px);
+ width: -webkit-calc(100% - 24px);
+ width: calc(100% - 24px);
+ margin-left: 12px;
+ margin-right: 12px;
+}
+
+.p-t-10 {
+ padding-top: 10px;
+}
+
+.p-b-10 {
+ padding-bottom: 10px;
+}
+
+.border-r-10 {
+ border-radius: 10px;
+}
+
+.text-black {
+ color: #606266;
+}
+
+.text-red {
+ color: #e73235;
+}
+
+.text-green {
+ color: #38b48b;
+}
+
+.m-b-90 {
+ margin-bottom: 90px;
+}
+
+.m-t-10 {
+ margin-top: 10px;
+}
+
+.m-b-20 {
+ margin-bottom: 20px;
+}
+
+.p-t-20 {
+ padding-top: 20px;
+}
+
+.p-b-20 {
+ padding-bottom: 20px;
+}
+
+/*字体居中*/
+.text-l {
+ text-align: left;
+}
+
+.text-c {
+ text-align: center;
+}
+
+.text-r {
+ text-align: right;
+}
+
+.f-12 {
+ font-size: 12px;
+}
+
+.header-title {
+ height: 0;
+}
+
+.svg-icon-custom {
+ width: 16px;
+ height: 16px;
+ fill: currentColor;
+ overflow: hidden;
+ margin-right: 10px
+}
+
+label {
+ font-weight: bold;
+}
+
+/*图片放大样式*/
+/*定位*/
+.position-r {
+ position: relative
+}
+
+.position-a {
+ position: absolute;
+}
+
+.position-f {
+ position: fixed;
+}
+
+/*知识产权样式*/
+.m-20 {
+ margin: 20px;
+}
+
+.p-20 {
+ padding: 20px;
+}
+
+.m-l-10 {
+ margin-left: 10px;
+}
+
+.m-r-10 {
+ margin-right: 10px;
+}
+
+.p-t-20 {
+ padding-top: 20px;
+}
+
+.p-b-20 {
+ padding-bottom: 20px;
+}
+
+.p-l-40 {
+ padding-left: 40px;
+}
+
+.p-r-40 {
+ padding-right: 40px;
+}
+
+.m-l-40 {
+ margin-left: 40px;
+}
+
+.m-r-20 {
+ margin-right: 20px;
+}
+
+.m-r-40 {
+ margin-right: 40px;
+}
+
+.text_blue {
+ color: #2c74fa;
+}
+
+.fr {
+ float: right;
+}
+
+.fl {
+ float: left;
+}
+
+.Cursor {
+ cursor: pointer;
+}
+
+.footer {
+ position: fixed;
+ bottom: 0;
+ z-index: 5;
+ text-align: right;
+ right: 0;
+ box-shadow: -1px 0px 15px 0px #c9ccd4;
+}
+
+.search_button {
+ float: right;
+ margin-right: 60px;
+}
+
+.tips {
+ // margin-left: 120px;
+ font-size: 12px;
+ line-height: 24px;
+ color: #999999;
+ margin: 0 !important;
+}
+
+.msgbox {
+ width: 25%;
+ max-height: 70%;
+}
+
+.el-table__body-wrapper::-webkit-scrollbar {
+ width: 8px;
+ height: 8px;
+}
+
+.el-table__body-wrapper::-webkit-scrollbar-thumb {
+ border-radius: 6px;
+}
+
+::-webkit-scrollbar {
+ width: 8px;
+ height: 8px;
+}
+
+::-webkit-scrollbar-thumb {
+ background-color: #a1a3a9;
+ border-radius: 6px;
+}
+
+.el-table--fluid-height .el-table__fixed,
+.el-table--fluid-height .el-table__fixed-right {
+ bottom: 8px !important;
+}
\ No newline at end of file
diff --git a/src/assets/style/icon.scss b/src/assets/style/icon.scss
new file mode 100644
index 0000000..80b8fd3
--- /dev/null
+++ b/src/assets/style/icon.scss
@@ -0,0 +1,13 @@
+@font-face {
+ font-family: 'icon-font';
+ src: url('../icon/iconfont.woff2') format('woff2'),
+ url('../icon/iconfont.woff') format('woff'),
+ url('../icon/iconfont.ttf') format('truetype');
+}
+.icon-font {
+ font-family: "icon-font" !important;
+ font-style: normal;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
diff --git a/src/assets/tianjia.png b/src/assets/tianjia.png
new file mode 100644
index 0000000000000000000000000000000000000000..498c5569dd9da7b0e2edd5008faf80e4fe6bd975
GIT binary patch
literal 471
zcmV;|0Vw{7P)Px$kx4{BR7gv`mib^>67b^|tm4UAsp
zt9-#1U&`qso$ilB`T6rXf|-}h%)@A)svZHj1aM*>ZT+%uEh0Z-j8B28x&ZJ1fdAV1
z0PrLt{12`{pn3EH;A)KJ?#v3n-H^v2&|vQX&KhCe@eP2B2>J&&0jvs*fD8$XV~VvB
zk!ycZ4`>C#P}bHKz`Y$<0ys_1Gqn3cDuLWMPcHZrkzK{A>X`FvnSJ5yftI`P5piq<
z^2+0`fIRRP0NWs2hXC0oue{g;AFaVlAamwbWFsQG9I7gF=v#+s6y=nH!25eZT5uD%
z*GqcM{Yue2cSd>-X9o_2l&axFx-CNLL&%Uu>J)}__M)M6^R-1oBe%9i-1r8hf@IRh
zoO)@?Cd#n18FWhV?s?bi!>+$f;;50CC})a9!B~_tu{MDJ0}WxJhlQsUgVx#j#vC_2
zF?_5{t|$uG*jfWv9{h+Z6J)vNT#KHGob1y)6SK-_-A~`8truqJe*uulz8#ECA!Psn
N002ovPDHLkV1mPT($D|^
literal 0
HcmV?d00001
diff --git a/src/components/index.js b/src/components/index.js
new file mode 100644
index 0000000..e98d632
--- /dev/null
+++ b/src/components/index.js
@@ -0,0 +1,4 @@
+import Layout from './layout/index'
+export {
+ Layout
+}
diff --git a/src/components/layout/index.vue b/src/components/layout/index.vue
new file mode 100644
index 0000000..5a5b1d4
--- /dev/null
+++ b/src/components/layout/index.vue
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/layout/libs/index.js b/src/components/layout/libs/index.js
new file mode 100644
index 0000000..96e21ca
--- /dev/null
+++ b/src/components/layout/libs/index.js
@@ -0,0 +1,8 @@
+import LayoutAside from './layout-aside/index.vue'
+import LayoutHeader from './layout-header/index.vue'
+import LayoutFooter from './layout-footer/index.vue'
+export {
+ LayoutAside,
+ LayoutHeader,
+ LayoutFooter
+}
diff --git a/src/components/layout/libs/layout-aside/index.vue b/src/components/layout/libs/layout-aside/index.vue
new file mode 100644
index 0000000..853af27
--- /dev/null
+++ b/src/components/layout/libs/layout-aside/index.vue
@@ -0,0 +1,82 @@
+
+
+
+
+ {{ settingsTitle }}
+
+
Cost
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/layout/libs/layout-aside/item.vue b/src/components/layout/libs/layout-aside/item.vue
new file mode 100644
index 0000000..cbb3043
--- /dev/null
+++ b/src/components/layout/libs/layout-aside/item.vue
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+ {{ item.meta.title }}
+
+
+
+
+
+
+ {{ item.meta.title }}
+
+
+
+
+
+
+
diff --git a/src/components/layout/libs/layout-footer/index.vue b/src/components/layout/libs/layout-footer/index.vue
new file mode 100644
index 0000000..4ba268c
--- /dev/null
+++ b/src/components/layout/libs/layout-footer/index.vue
@@ -0,0 +1,6 @@
+
+ footer
+
+
diff --git a/src/components/layout/libs/layout-header/index.vue b/src/components/layout/libs/layout-header/index.vue
new file mode 100644
index 0000000..830b105
--- /dev/null
+++ b/src/components/layout/libs/layout-header/index.vue
@@ -0,0 +1,319 @@
+
+
+
+
+
diff --git a/src/icons/index.js b/src/icons/index.js
new file mode 100644
index 0000000..2c6b309
--- /dev/null
+++ b/src/icons/index.js
@@ -0,0 +1,9 @@
+import Vue from 'vue'
+import SvgIcon from '@/components/SvgIcon'// svg component
+
+// register globally
+Vue.component('svg-icon', SvgIcon)
+
+const req = require.context('./svg', false, /\.svg$/)
+const requireAll = requireContext => requireContext.keys().map(requireContext)
+requireAll(req)
diff --git a/src/main.js b/src/main.js
new file mode 100644
index 0000000..d395fba
--- /dev/null
+++ b/src/main.js
@@ -0,0 +1,64 @@
+import {
+ createApp
+} from 'vue'
+import ElementPlus from 'element-plus'
+import App from './App.vue'
+import router from './router'
+import store from './store'
+import Request from '@/utils/request'
+import '@/router/permission.js'
+import 'element-plus/dist/index.css'
+import {
+ ElMessage
+} from 'element-plus'
+import locale from 'element-plus/lib/locale/lang/zh-cn' //需要新加的代码
+
+import {
+ defineRule,
+ configure
+} from 'vee-validate'
+import all from '@vee-validate/rules'
+import allValid from '@/utils/validate'
+import '@/assets/style/global.scss'
+import '@/assets/style/icon.scss'
+import '@/utils/iconfont.js'
+
+import 'xe-utils'
+import VXETable from 'vxe-table'
+import 'vxe-table/lib/style.css'
+
+configure({
+ validateOnBlur: true, // controls if `blur` events should trigger validation with `handleChange` handler
+ validateOnChange: true, // controls if `change` events should trigger validation with `handleChange` handler
+ validateOnInput: false, // controls if `input` events should trigger validation with `handleChange` handler
+ validateOnModelUpdate: true // controls if `update:modelValue` events should trigger validation with `handleChange` handler
+})
+Object.keys(all).forEach(rule => {
+ defineRule(rule, all[rule])
+})
+Object.keys(allValid).forEach(rule => {
+ defineRule(rule, allValid[rule])
+})
+
+const app = createApp(App)
+app.use(store)
+app.use(router)
+app.use(ElMessage)
+app.use(ElementPlus, {
+ locale
+}) //需要改变的地方,加入locale
+app.use(VXETable)
+
+app.config.globalProperties.$http = new Request()
+// app.config.globalProperties.$message = ElMessage
+app.mount('#app')
+
+// 注册一个全局自定义指令 `v-allow` 配合路由meta.permission信息控制节点显示权限
+app.directive('allow', {
+ mounted(el, binding) {
+ const permission = binding.instance.$route.meta.permission
+ if (!permission.includes(binding.value)) {
+ el.parentNode.removeChild(el)
+ }
+ }
+})
\ No newline at end of file
diff --git a/src/router/index.js b/src/router/index.js
new file mode 100644
index 0000000..66ac485
--- /dev/null
+++ b/src/router/index.js
@@ -0,0 +1,55 @@
+import {
+ createRouter,
+ createWebHistory
+} from 'vue-router'
+import {
+ Layout
+} from '@/components/'
+
+export const staticRoutes = [
+ {
+ path: '/',
+ name: 'Main',
+ component: Layout,
+ meta: {
+ title: '老成本管理',
+ icon: ''
+ },
+ hidden: true,
+ children: [{
+ path: '/oindex',
+ name: 'NewCostList',
+ meta: {
+ title: '老成本管理',
+ icon: 'el-icon-s-home'
+ },
+ hidden: true,
+ component: () => import('@/views/index/oindex')
+ }]
+ },
+ {
+ path: '/login',
+ name: 'Login',
+ hidden: true,
+ component: () => import('@/views/login/index'),
+ meta: {
+ title: '登录页'
+ }
+ },
+ {
+ path: '/404',
+ name: '404',
+ hidden: true,
+ component: () => import('@/views/public/404'),
+ meta: {
+ title: '页面未找到'
+ }
+ }
+]
+
+const router = createRouter({
+ history: createWebHistory(process.env.BASE_URL),
+ routes: staticRoutes
+})
+
+export default router
diff --git a/src/router/permission.js b/src/router/permission.js
new file mode 100644
index 0000000..5260134
--- /dev/null
+++ b/src/router/permission.js
@@ -0,0 +1,55 @@
+import router from '@/router'
+import store from '@/store'
+import { title as settingsTitle } from '@/settings'
+import { checkSignedInStatus, setNotLoggedIn } from '@/utils/auth'
+
+let loadedDynamicRoutes = false // 是否已加载动态路由
+const whiteList = ['/login']
+router.beforeEach(async (to, from, next) => {
+ // 网页title跟随路由title
+ document.title = settingsTitle + '-' + to.meta.title
+
+ if (checkSignedInStatus()) {
+ // 身份验证通过
+ if (to.path !== '/login') { // 不在登录页面,正常进入相应页面
+ if (loadedDynamicRoutes) {
+ store.dispatch('topNavTag/addNavTag', to) // 顶部页面标签处理
+ next()
+ } else {
+
+ try {
+ // 获取用户信息
+ await store.dispatch('user/getUserInfo')
+ // 获取用户权限列表
+ const authList = store.getters['user/getUserAuthList']
+ // 获取用户有权限操作权限的路由
+ const accessRoutes = await store.dispatch('routes/generateRoutes', authList)
+ // 动态添加路由
+ accessRoutes.forEach(route => {
+ router.addRoute(route)
+ })
+
+ // 设为已加载动态路由
+ loadedDynamicRoutes = true
+
+ // 确保动态添加的路由已经被完全加载上去并替换浏览器路由使浏览器没有浏览历史可回退
+ next({ ...to, replace: true })
+ } catch (error) {
+ // 设为非登录状态
+ setNotLoggedIn()
+ next('/login')
+ }
+ }
+ } else { // 在登录页面
+ next({ path: '/' })
+ }
+ } else { // 身份验证不过
+ // 设为非登录状态
+ setNotLoggedIn()
+ if (whiteList.indexOf(to.path) !== -1) { // 处于不用登录页面
+ next()
+ } else {
+ next('/login')
+ }
+ }
+})
diff --git a/src/settings.js b/src/settings.js
new file mode 100644
index 0000000..280a718
--- /dev/null
+++ b/src/settings.js
@@ -0,0 +1,3 @@
+module.exports = {
+ title: 'OPD211'
+}
diff --git a/src/store/index.js b/src/store/index.js
new file mode 100644
index 0000000..efca841
--- /dev/null
+++ b/src/store/index.js
@@ -0,0 +1,19 @@
+import {
+ createStore
+} from 'vuex'
+import leftAside from './modules/leftAside'
+import topNavTag from './modules/topNavTag'
+import routes from './modules/routes'
+import user from './modules/user'
+
+export default createStore({
+ state: {},
+ mutations: {},
+ actions: {},
+ modules: {
+ leftAside,
+ topNavTag,
+ routes,
+ user
+ }
+})
diff --git a/src/store/modules/leftAside.js b/src/store/modules/leftAside.js
new file mode 100644
index 0000000..e008e78
--- /dev/null
+++ b/src/store/modules/leftAside.js
@@ -0,0 +1,28 @@
+const state = {
+ leftMenuWidth: '200px',
+ isCollapse: false
+}
+
+const mutations = {
+ CHANGE_COLLAPSE: (state) => {
+ state.isCollapse = !state.isCollapse
+ if (state.isCollapse) {
+ state.leftMenuWidth = 'auto'
+ } else {
+ state.leftMenuWidth = '200px'
+ }
+ }
+}
+
+const actions = {
+ changeCollapse (context) {
+ context.commit('CHANGE_COLLAPSE')
+ }
+}
+
+export default {
+ namespaced: true,
+ state,
+ mutations,
+ actions
+}
diff --git a/src/store/modules/routes.js b/src/store/modules/routes.js
new file mode 100644
index 0000000..5227a6d
--- /dev/null
+++ b/src/store/modules/routes.js
@@ -0,0 +1,84 @@
+import { staticRoutes } from '@/router'
+import Request from '@/utils/request'
+import Layout from '@/components/layout/index'
+
+// 从服务器获取菜单
+async function fetchAsyncRoutes4Server() {
+ return (new Request()).mock(true).get('menu/index').then(r => {
+ if (r.errno !== 0) {
+ return []
+ }
+ let ar =[{"id":616,"pid":0,"menu_title":"OPD211","menu_name":"NewCost","menu_path":"\/index","menu_component":"\/layout","redirect":"","sort":1,"type":1,"is_menu":1,"component":"\/layout","name":"NewCost","path":"\/index","title":"OPD211","meta":{"title":"OPD211"},"hidden":false,"alwaysshow":true,"children":[{"id":617,"pid":616,"menu_title":"老成本管理","menu_name":"NewCostList","menu_path":"\/index\/index","menu_component":"\/index\/index","redirect":"","sort":2,"type":1,"is_menu":1,"component":"\/index\/index","name":"NewCostList","path":"\/index\/index","title":"老成本管理","meta":{"title":"老成本管理"},"hidden":false,"alwaysshow":false},{"id":619,"pid":616,"menu_title":"日志管理","menu_name":"NewCostLog","menu_path":"\/index\/log","menu_component":"\/index\/log","redirect":"","sort":4,"type":1,"is_menu":1,"component":"\/index\/log","name":"NewCostLog","path":"\/index\/log","title":"日志管理","meta":{"title":"日志管理"},"hidden":true,"alwaysshow":false}]}]
+ // ar.children.push(r.data.children[2])
+ console.log(ar)
+ return ar
+ })
+ // return ar
+}
+
+// 组装路由结构
+function buildTreeAsyncRoutes (routes, authList) {
+ const menus = []
+ routes.forEach(item => {
+ const it = { id: item.id, path: item.path, name: item.name, meta: item.meta, alwaysShow: item.alwaysShow, hidden: item.hidden }
+ if (item.redirect != null) {
+ it.redirect = item.redirect
+ }
+ if (item.component && authList.indexOf(item.id) >= 0) {
+ if (item.component === '/layout') {
+ it.component = Layout
+ } else {
+ it.component = () => import('@/views' + item.component)
+ }
+ if (item.children && item.children.length) {
+ item.children.forEach(v => {
+ if (!it.meta.permission) {
+ it.meta.permission = []
+ }
+ if (item.path.startsWith('/')) {
+ item.path = item.path.substring(1)
+ }
+ if (authList.indexOf(v.id) >= 0) {
+ it.meta.permission.push(item.name + '.' + v.name)
+ }
+ })
+ it.children = buildTreeAsyncRoutes(item.children, authList)
+ }
+ menus.push(it)
+
+ }
+ })
+ return menus
+
+}
+
+const state = {
+ routes: []
+}
+
+const mutations = {
+ SET_ROUTES: (state, routes) => {
+ state.routes = routes
+ }
+}
+
+const actions = {
+ async generateRoutes (context, authList) {
+ // 服务器获取菜单
+ const routes = await fetchAsyncRoutes4Server()
+ // 权限过滤
+ // const accessRoutes = routes.filter(v => authList.indexOf(v.id) >= 0)
+ // 组装路由
+ const treeRoutes = buildTreeAsyncRoutes(routes, authList)
+ const mergeTreeRoutes = staticRoutes.concat(treeRoutes)
+ context.commit('SET_ROUTES', mergeTreeRoutes)
+ return mergeTreeRoutes
+ }
+}
+
+export default {
+ namespaced: true,
+ state,
+ mutations,
+ actions
+}
diff --git a/src/store/modules/topNavTag.js b/src/store/modules/topNavTag.js
new file mode 100644
index 0000000..05aca74
--- /dev/null
+++ b/src/store/modules/topNavTag.js
@@ -0,0 +1,68 @@
+import router from '@/router'
+const state = {
+ tags: [
+ // 默认打开路由标签
+ { fullPath: '/index/index', name: 'NewCostList', meta: { title: '成本管理' } }
+ ] // 标签
+}
+
+const mutations = {
+ // 新增标签
+ ADD_NAV_TAG: (state, tag) => {
+ state.tags.push(tag)
+ },
+
+ // 替换标签
+ REPLACE_NAV_TAG: (state, tag) => {
+ const index = state.tags.findIndex(it => it.fullPath === tag.fullPath)
+ // const index = state.tags.findIndex(it => it.path === tag.path)
+ state.tags.splice(index, 1, tag)
+ },
+
+ // 删除标签
+ RM_NAV_TAG: (state, index) => {
+ state.tags = state.tags.filter((it, i) => {
+ return i !== index || it.name === 'NewCostList'
+ })
+ }
+}
+
+const actions = {
+ // 新增标签
+ addNavTag: (context, tag) => {
+ // 跳转至新打开页面
+ if (tag.name == '404') {
+ return false
+ }
+ // router.push({ path: tag.fullPath })
+ // if (!context.state.tags.some(v => v.name === tag.name)) {
+ if (!context.state.tags.some(v => v.fullPath === tag.fullPath)) {
+ // 标签栏没有,新增页面标签
+ context.commit('ADD_NAV_TAG', tag)
+ } else {
+ // 标签栏有,替换标签
+ context.commit('REPLACE_NAV_TAG', tag)
+ }
+ },
+
+ // 删除标签
+ removeNavTag: (context, index) => {
+ let nextIndex = index - 1
+ var overallVar = context
+ if (context.state.tags.length - 1 > index) {
+ nextIndex = index + 1
+ }
+ // 最后一个页面标签不允许删除
+ if (nextIndex === -1) return false
+ // router.push({ path: context.state.tags[nextIndex].path })
+ router.push(context.state.tags[nextIndex]);
+ context.commit('RM_NAV_TAG', index)
+ }
+}
+
+export default {
+ namespaced: true,
+ state,
+ mutations,
+ actions
+}
diff --git a/src/store/modules/user.js b/src/store/modules/user.js
new file mode 100644
index 0000000..6f31ac8
--- /dev/null
+++ b/src/store/modules/user.js
@@ -0,0 +1,68 @@
+import { toRaw } from 'vue'
+import Request from '@/utils/request'
+
+const state = {
+ userInfo: {}
+}
+
+const getters = {
+ // 获取用户菜单权限
+ getUserAuthList: state => {
+ if (state.userInfo.length <= 0) {
+ return []
+ }
+ if (typeof state.userInfo.auth_list === 'undefined') {
+ return []
+ }
+ return toRaw(state.userInfo.auth_list)
+ }
+}
+
+const mutations = {
+ SET_USER_INFO: (state, user) => {
+ state.userInfo = user
+ }
+}
+
+const actions = {
+ // 设置用户信息
+ setUserInfo (context, user) {
+ context.commit('SET_USER_INFO', user)
+ },
+
+ // 获取用户信息
+ getUserInfo (context) {
+ return new Promise((resolve, reject) => {
+ if (context.state.userInfo.length <= 0 || typeof context.state.userInfo.auth_list === 'undefined') {
+ // 服务器获取用户信息
+ return (new Request()).get('login/getOssInfo')
+ .then(r => {
+ const { errno, data, errmsg } = r
+ if (errno !== 0) {
+ if (errno == 500){
+ alert(errmsg)
+ setTimeout(() => window.location.href="/login")
+ }else{
+ reject(errmsg)
+ }
+
+ }
+ context.commit('SET_USER_INFO', data)
+ resolve(data)
+ })
+ .catch(e => {
+ reject(e)
+ })
+ }
+ resolve(toRaw(context.state.userInfo))
+ })
+ }
+}
+
+export default {
+ namespaced: true,
+ state,
+ getters,
+ mutations,
+ actions
+}
diff --git a/src/utils/auth.js b/src/utils/auth.js
new file mode 100644
index 0000000..156596f
--- /dev/null
+++ b/src/utils/auth.js
@@ -0,0 +1,16 @@
+import Cookies from 'js-cookie'
+
+const signedInKey = 's_pass'
+// 设置已登录状态cookie
+export function setSignedIn () {
+ return Cookies.set(signedInKey, 1)
+}
+// 判断是否已登录
+export function checkSignedInStatus () {
+ return (Cookies.get(signedInKey) * 1) === 1
+}
+// 删除登录状态cookie
+export function setNotLoggedIn () {
+ sessionStorage.clear()
+ return Cookies.remove(signedInKey)
+}
diff --git a/src/utils/common.js b/src/utils/common.js
new file mode 100644
index 0000000..d29fa20
--- /dev/null
+++ b/src/utils/common.js
@@ -0,0 +1,69 @@
+// 深拷贝对象
+export function copyObj(obj) {
+ if (!isObject(obj)) {
+ throw new Error('obj 不是一个对象!')
+ }
+
+ const isArray = Array.isArray(obj)
+ const cloneObj = isArray ? [] : {}
+ for (const key in obj) {
+ cloneObj[key] = isObject(obj[key]) ? copyObj(obj[key]) : obj[key]
+ }
+
+ return cloneObj
+}
+
+// 赋值对象
+export function assignObj(obj1, obj2) {
+ for (const key in obj1, obj2) {
+ if (isObject(obj2[key])) {
+ assignObj(obj1[key], obj2[key])
+ } else {
+ obj1[key] = obj2[key]
+ }
+ }
+}
+
+export function isObject(o) {
+ return (typeof o === 'object' || typeof o === 'function') && o !== null
+}
+
+//转义
+export function HTMLDecode(str){
+ var s = ''
+ if (str.length == 0) return ''
+ s = str.replace(/</g, '<')
+ s = s.replace(/&/g, '&')
+ s = s.replace(/>/g, '>')
+ s = s.replace(/'/g, "\'")
+ s = s.replace(/"/g, '"')
+ return s
+}
+
+export function HTMLEncode(str){
+ var s = ''
+ if (str.length == 0) return ''
+ s = str.replace(/&/g, '&')
+ s = s.replace(//g, '>')
+ s = s.replace(/\'/g, ''')
+ s = s.replace(/\"/g, '"')
+ return s
+}
+//正则
+export function dealInputVal(value) {
+ value = value.replace(/^0*(0\.|[1-9])/, "$1");
+ value = value.replace(/[^\d.]/g, ""); //清除"数字"和"."以外的字符
+ value = value.replace(/^\./g, ""); //验证第一个字符是数字而不是字符
+ value = value.replace(/\.{1,}/g, "."); //只保留第一个.清除多余的
+ value = value
+ .replace(".", "$#$")
+ .replace(/\./g, "")
+ .replace("$#$", ".");
+ value = value.replace(/^()*(\d*)\.(\d\d).*$/, "$1$2.$3"); //只能输入两个小数
+ value =
+ value.indexOf(".") > 0
+ ? value.split(".")[0].substring(0, 10) + "." + value.split(".")[1]
+ : value.substring(0, 10);
+ return value;
+ }
\ No newline at end of file
diff --git a/src/utils/exportExcel.js b/src/utils/exportExcel.js
new file mode 100644
index 0000000..7387098
--- /dev/null
+++ b/src/utils/exportExcel.js
@@ -0,0 +1,32 @@
+import axios from 'axios'
+
+const exportExcel = (url, params) => {
+ console.log('我是公共的方法' + url)
+ const apiVersion = process.env.VUE_APP_API_VERSION.replace(/\./g, '_')
+ axios.post(process.env.VUE_APP_API_BASEURL + apiVersion + url, params, {
+ responseType: 'blob',
+ headers: {
+ // 'X-Token': getToken(),
+ 'Content-Type': 'application/json;charset=utf-8'
+ }
+ }).then(res => {
+ if (!res) {
+ this.$message.error('下载模板文件失败')
+ return false
+ }
+ const stream = res.data // 后端用stream返回Excel文件
+ const blob = new Blob([stream])
+ // 前端获取业务码,成功执行正常业务
+ const downloadElement = document.createElement('a')
+ const href = window.URL.createObjectURL(blob) // 创建下载的链接
+ downloadElement.href = href
+ const timeStamp = new Date().toString()
+ const nameStr = decodeURI(escape(JSON.parse(res.headers['content-disposition'].split(';')[1].split('=')[1])))
+ downloadElement.download = nameStr // 下载后文件名
+ document.body.appendChild(downloadElement)
+ downloadElement.click() // 点击下载
+ document.body.removeChild(downloadElement) // 下载完成移除元素
+ window.URL.revokeObjectURL(href) // 释放掉blob对象
+ })
+}
+export { exportExcel }
\ No newline at end of file
diff --git a/src/utils/iconfont.js b/src/utils/iconfont.js
new file mode 100644
index 0000000..a4cf0e8
--- /dev/null
+++ b/src/utils/iconfont.js
@@ -0,0 +1 @@
+!function(a){var l,h,t,i,c,C='',o=(o=document.getElementsByTagName("script"))[o.length-1].getAttribute("data-injectcss"),p=function(a,l){l.parentNode.insertBefore(a,l)};if(o&&!a.__iconfont__svg__cssinject__){a.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(a){console&&console.log(a)}}function d(){c||(c=!0,t())}function e(){try{i.documentElement.doScroll("left")}catch(a){return void setTimeout(e,50)}d()}l=function(){var a,l;(l=document.createElement("div")).innerHTML=C,C=null,(a=l.getElementsByTagName("svg")[0])&&(a.setAttribute("aria-hidden","true"),a.style.position="absolute",a.style.width=0,a.style.height=0,a.style.overflow="hidden",l=a,(a=document.body).firstChild?p(l,a.firstChild):a.appendChild(l))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(l,0):(h=function(){document.removeEventListener("DOMContentLoaded",h,!1),l()},document.addEventListener("DOMContentLoaded",h,!1)):document.attachEvent&&(t=l,i=a.document,c=!1,e(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,d())})}(window);
\ No newline at end of file
diff --git a/src/utils/index.js b/src/utils/index.js
new file mode 100644
index 0000000..4830c04
--- /dev/null
+++ b/src/utils/index.js
@@ -0,0 +1,117 @@
+/**
+ * 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
+}
diff --git a/src/utils/request.js b/src/utils/request.js
new file mode 100644
index 0000000..32aaf0f
--- /dev/null
+++ b/src/utils/request.js
@@ -0,0 +1,141 @@
+import axios from 'axios'
+import router from '@/router'
+import {
+ ElLoading,
+ ElMessage
+} from 'element-plus'
+import {
+ setNotLoggedIn
+} from '@/utils/auth'
+
+export default class Request {
+ http
+ isMock = false
+ isJWT = false
+ loadingInstance
+ loading = true
+ constructor() {
+ const apiVersion = process.env.VUE_APP_API_VERSION.replace(/\./g, '_')
+ this.http = axios.create({
+ baseURL: process.env.VUE_APP_API_BASEURL + apiVersion + '/',
+ timeout: 600000,
+ withCredentials: true
+ })
+
+ this.interceptors()
+ }
+
+ mock(mock) {
+ this.isMock = mock
+ return this
+ }
+
+ JWT() {
+ this.isJWT = true
+ // this.http.defaults.headers.common['isJWT'] = true;
+ }
+
+ showLoading(show) {
+ this.loading = show
+ return this
+ }
+
+ post(path, params) {
+ let config = {}
+ if (this.isMock) config = { baseURL: process.env.VUE_APP_API_MOCK }
+ return new Promise((resolve, reject) => {
+ this.http.post(path, params, config).then((r) => {
+ resolve(r)
+ }).catch((e) => {
+ reject(e.message)
+ })
+ })
+ }
+
+ get(path, params) {
+ const data = {
+ params: params
+ }
+ if (this.isMock) data.baseURL = process.env.VUE_APP_API_MOCK
+ return new Promise((resolve, reject) => {
+ this.http.get(path, data).then((r) => {
+ resolve(r)
+ }).catch((e) => {
+ reject(e.message)
+ })
+ })
+ }
+
+ put(path, params) {
+ let config = {}
+ if (this.isMock) config = { baseURL: process.env.VUE_APP_API_MOCK }
+ return new Promise((resolve, reject) => {
+ this.http.put(path, params, config).then((r) => {
+ resolve(r)
+ }).catch((e) => {
+ reject(e.message)
+ })
+ })
+ }
+
+ delete(path) {
+ let config = {}
+ if (this.isMock) config = { baseURL: process.env.VUE_APP_API_MOCK }
+ return new Promise((resolve, reject) => {
+ this.http.delete(path, config).then((r) => {
+ resolve(r)
+ }).catch((e) => {
+ reject(e.message)
+ })
+ })
+ }
+
+ interceptors() {
+ this.http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8'
+ // 添加请求拦截器
+ this.http.interceptors.request.use((config) => {
+ // 显示loading
+ if (this.loading) {
+ this.loadingInstance = ElLoading.service({
+ fullscreen: true
+ })
+ }
+
+ if (this.isJWT) {
+ config.headers.Authorization = 'token'
+ }
+ return config
+ }, (error) => {
+ // 请求错误
+ return Promise.reject(error)
+ })
+
+ // 添加响应拦截器
+ this.http.interceptors.response.use((response) => {
+ // 关闭loading
+ if (this.loading) this.loadingInstance.close()
+ if (response.status === 200) {
+ if(response.data.status !== 200 && response.data.status !== 99999){
+ if(response.data.message){
+ ElMessage.error(response.data.message)
+ }
+ }
+ if (response.data.errno === 2003) {
+ setNotLoggedIn() // 设置未登录
+ router.replace('/login')
+ return
+ }
+ return response.data
+ } else {
+ console.error(response)
+ }
+ }, (error) => {
+ // 关闭loading
+ setTimeout(() => {
+ if (this.loading) this.loadingInstance.close()
+ }, 3000)
+ // 响应错误
+ return Promise.reject(error)
+ })
+ }
+}
diff --git a/src/utils/storage.js b/src/utils/storage.js
new file mode 100644
index 0000000..f0cbdf5
--- /dev/null
+++ b/src/utils/storage.js
@@ -0,0 +1,33 @@
+// session操作
+const sessionData = function (method, url, name, obj) {
+ /*
+ * 参数说明:
+ * method:get获取,set存入或覆盖,clean清除
+ * name:session的名称
+ * obj:存入的内容,可以是任意类型
+ * */
+ switch (method) {
+ case 'get':
+ if (sessionStorage.getItem(url + name + '_obj')) {
+ return JSON.parse(sessionStorage.getItem(url + name + '_obj'));
+ } else if (sessionStorage.getItem(url + name + '_str')) {
+ return sessionStorage.getItem(url + name + '_str');
+ } else {
+ return null
+ }
+ case 'set':
+ sessionData('clean', url + name);
+ if (typeof obj == 'object') {
+ sessionStorage.setItem(url+ name + '_obj', JSON.stringify(obj));
+ } else {
+ sessionStorage.setItem(url + name + '_str', obj);
+ }
+ return true;
+ case 'clean':
+ sessionStorage.removeItem(url + name + '_obj');
+ sessionStorage.removeItem(url + name + '_str');
+ return true;
+ }
+};
+
+export {sessionData}
diff --git a/src/utils/upload.js b/src/utils/upload.js
new file mode 100644
index 0000000..859679f
--- /dev/null
+++ b/src/utils/upload.js
@@ -0,0 +1,58 @@
+// An highlighted block
+import COS from 'cos-js-sdk-v5'
+import { getSecret } from '@/api/upload'
+
+export default function upload(file, config, callback) {
+ if (typeof config.isPublic === 'undefined') {
+ config.isPublic = true
+ }
+ getSecret({
+ type: config.type,
+ path: config.path,
+ isPublic: config.isPublic ? config.isPublic : false
+ }).then(response => {
+ const data = response.data
+ const cos = new COS({
+ getAuthorization: function(options, callback) {
+ callback({
+ TmpSecretId: data.tmpSecretId,
+ TmpSecretKey: data.tmpSecretKey,
+ XCosSecurityToken: data.sessionToken,
+ ExpiredTime: data.expiredTime
+ })
+ }
+ })
+
+ return {
+ cos: cos,
+ dir: data.url,
+ bucket: data.bucket,
+ region: data.region
+ }
+ }).then(data => {
+ const cos = data.cos
+ const dir = data.dir
+ const bucket = data.bucket
+ const region = data.region
+
+ const url = cos.getObjectUrl({
+ Bucket: bucket,
+ Region: region,
+ Key: `${dir}/${file.name}`,
+ Sign: false
+ }, function(data) {
+ cos.putObject({
+ Bucket: bucket,
+ Region: region,
+ Key: `${dir}/${file.name}`,
+ Body: file
+ }, function(data) {
+ if (config.isPublic) {
+ callback(url.replace(/^http(s)?:\/\/(.*?)\//, 'https://www.baidu.com/'))
+ } else {
+ callback(url)
+ }
+ })
+ })
+ })
+}
diff --git a/src/utils/util.js b/src/utils/util.js
new file mode 100644
index 0000000..235c077
--- /dev/null
+++ b/src/utils/util.js
@@ -0,0 +1,79 @@
+const formatDate = function (time, format) {
+ var t = new Date(time)
+ var tf = function(i) {
+ return (i < 10 ? "0" : "") + i
+ }
+ return format.replace(/Y|m|d|H|i|s/g, function(a) {
+ switch (a) {
+ case "Y":
+ return tf(t.getFullYear())
+ case "m":
+ return tf(t.getMonth() + 1)
+ case "d":
+ return tf(t.getDate())
+ case "H":
+ return tf(t.getMinutes())
+ case "i":
+ return tf(t.getHours())
+ case "s":
+ return tf(t.getSeconds())
+ }
+ })
+}
+// 时间戳转日期
+const timestampToTime = function (timestamp, type) {
+ var date = new Date(timestamp * 1000) // 时间戳为10位需*1000,时间戳为13位的话不需乘1000
+ var Y = date.getFullYear()
+ var M =
+ date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
+ var D = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
+ var dateStr = ''
+ switch (type) {
+ case 1:
+ dateStr = Y + '年' + M + '月' + D + '日'
+ break
+ case 2:
+ dateStr = Y + '-' + M + '-' + D
+ break
+ default:
+ dateStr = Y + '年' + M + '月' + D + '日'
+ }
+ return dateStr
+}
+
+// 标准化时间 即将 2015年12月31日 转为 2015-12-31
+const dateFormat = function (dateStr) {
+ if (dateStr) {
+ dateStr = dateStr.replace('年', '-')
+ dateStr = dateStr.replace('月', '-')
+ dateStr = dateStr.replace('日', '')
+ return dateStr
+ } else {
+ return ''
+ }
+}
+
+
+// 存储本地浏览器 mainKey是唯一标识 aryy是存储书 ,type - save 是存 getdata是取
+const saveactionDate = function (mainKey, arry, type) {
+ const _this = this
+ if (arry) {
+ arry.forEach(item => {
+ if (type === 'save') {
+ // 保存操作
+ window.localStorage.setItem(mainKey + '-' + item, JSON.stringify(_this[item]))
+ } else {
+ // 回显
+ _this[item] = JSON.parse(window.localStorage.getItem(mainKey + '-' + item) ? window.localStorage
+ .getItem(mainKey + '-' + item) : [])
+ }
+ })
+ }
+}
+
+export {
+ formatDate,
+ timestampToTime,
+ dateFormat,
+ saveactionDate
+};
diff --git a/src/utils/validate.js b/src/utils/validate.js
new file mode 100644
index 0000000..fff67aa
--- /dev/null
+++ b/src/utils/validate.js
@@ -0,0 +1,158 @@
+/**
+ * 验证是否为空
+ * @param string|array value
+ * @returns
+ */
+function isEmpty(value) {
+ if (value === null || value === undefined || value === "") {
+ return true;
+ }
+ if (Array.isArray(value) && value.length === 0) {
+ return true;
+ }
+ return false;
+}
+
+/**
+ * 是否为手机号
+ * @param {*} value
+ * @param {*} param1
+ * @returns
+ */
+export const mobileValidator = (value, [locale]) => {
+ if (isEmpty(value)) {
+ return true;
+ }
+ if ((!locale || locale == "CN") && /^1[3456789][0-9]{9}$/.test(value)) {
+ return true;
+ } else if (locale == "EN" && /^\+[\d]{1,5}\s[\d]{1,14}$/.test(value)) {
+ return true;
+ }
+ return "请输入正确的手机号";
+};
+
+/**
+ * 是否为电话号码
+ * @param value
+ * @param {*} param1
+ * @returns
+ */
+export const telValidator = (value, [locale]) => {
+ if (isEmpty(value)) {
+ return true;
+ }
+ if ((!locale || locale == "CN") && !/^(?:0|8)[1-9]{3,}-[0-9]{8}$/.test(value)) {
+ return true;
+ }
+ return "电话号码格式不正确";
+};
+
+/**
+ * 身份证号码是否正确
+ * @param string value
+ * @returns
+ */
+export const identifyValidator = (value) => {
+ if (isEmpty(value)) {
+ return true;
+ }
+ if (!/(?:^\d{15}$)|(?:^\d{18}$)|(?:^\d{17}(?:\d|X|x)$)/.test(value)) {
+ return "身份证号码格式不正确";
+ }
+ return true;
+};
+
+/**
+ * 验证小数位长度
+ * @param number value 值
+ * @param number param1.length 为小数位长度
+ * @returns
+ */
+export const decimalValidator = (value, [length]) => {
+ if (isEmpty(value)) {
+ return true;
+ }
+ let regExp = new RegExp("^[0-9]+(?:.[0-9])?$");
+ if (length) {
+ regExp = new RegExp("^[0-9]+(?:.[0-9]{1," + length + "})?$");
+ }
+ if (regExp.test(value)) {
+ return true;
+ }
+ return "小数位长度不正确";
+};
+
+/**
+ * 验证是否为大写字母
+ * @param string value
+ * @returns
+ */
+export const letterUpperValidator = (value) => {
+ if (isEmpty(value) || /^[A-Z]+$/.test(value)) {
+ return true;
+ }
+ return "请填写大写字母";
+};
+
+/**
+ * 验证是否为小写字母
+ * @param string value
+ * @returns
+ */
+export const letterLowerValidator = (value) => {
+ if (isEmpty(value) || /^[a-z]+$/.test(value)) {
+ return true;
+ }
+ return "请填写小写字母";
+};
+
+/**
+ * 验证是否为中文
+ * @param string value
+ * @returns
+ */
+export const characterCNValidator = (value) => {
+ if (isEmpty(value) || /^[\u4e00-\u9fa5]+$/.test(value)) {
+ return true;
+ }
+ return "请输入中文";
+};
+
+/**
+ * 验证是否为邮编格式
+ * @param string value
+ * @returns
+ */
+export const zipcodeValidator = (value) => {
+ if (isEmpty(value) || /^[1-9]\d{5}(?!\d)$/.test(value)) {
+ return true;
+ }
+ return "请输入正确邮编";
+};
+
+/**
+ * 验证是否为传真格式
+ * @param string value
+ * @returns
+ */
+export const faxValidator = (value) => {
+ if (isEmpty(value) || /^(\d{3,4}-)?\d{7,8}$/.test(value)) {
+ return true;
+ }
+ return "请输入正确的传真格式";
+};
+
+
+const allValid = {
+ mobile: mobileValidator,
+ tel: telValidator,
+ identify: identifyValidator,
+ decimal: decimalValidator,
+ letter_upper: letterUpperValidator,
+ letter_lower: letterLowerValidator,
+ character_cn: characterCNValidator,
+ zipcode: zipcodeValidator,
+ fax: faxValidator
+};
+
+export default allValid;
diff --git a/src/views/PIP/copyright.vue b/src/views/PIP/copyright.vue
new file mode 100644
index 0000000..58a0676
--- /dev/null
+++ b/src/views/PIP/copyright.vue
@@ -0,0 +1,335 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+
+
+
+
+
+ 新增版权
+ 下载装备材料模板
+
+
+
+
+
+
+ {{scope.row.name}}
+
+
+
+
+
+
+
+ 下载
+
+
+
+
+ 下载
+
+
+
+
+ 下载
+
+
+
+
+
+
+ 下载
+
+
+
+
+ 下载
+
+
+
+
+ 下载
+
+
+
+
+ 下载
+
+
+
+
+ 下载
+
+
+
+
+
+
+
+
+
+ 查看详情
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/PIP/copyright_add.vue b/src/views/PIP/copyright_add.vue
new file mode 100644
index 0000000..fa9e6e5
--- /dev/null
+++ b/src/views/PIP/copyright_add.vue
@@ -0,0 +1,701 @@
+
+
+
+
+
+
+
基础信息
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
附件上传
+
+
+
+
+ 上传
+
+
+ 支持PDF、Word、Excel格式,限10M内
+
+
+
+
+
+
+
+
+ 上传
+
+
+ 支持PDF、Word、Excel格式,限10M内
+
+
+
+
+
+
+
+
+ 上传
+
+
+ 支持PDF、Word、Excel格式,限10M内
+
+
+
+
+
+
+
+
+
+
+ 上传
+
+
+ 支持PDF、Word、Excel格式,限10M内
+
+
+
+
+
+
+
+
+ 上传
+
+
+ 支持PDF、Word、Excel格式,限10M内
+
+
+
+
+
+
+
+
+ 上传
+
+
+ 支持PDF、Word、Excel格式,限10M内
+
+
+
+
+
+
+
+
+ 上传
+
+
+ 支持PDF、Word、Excel格式,限10M内
+
+
+
+
+
+
+
+
+ 上传
+
+
+ 支持PDF、Word、Excel格式,限10M内
+
+
+
+
+
+
+
+
+
+ 申请结果
+
+ {{ item.name }}
+
+
+
+
费用信息
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/PIP/copyright_edit.vue b/src/views/PIP/copyright_edit.vue
new file mode 100644
index 0000000..18443da
--- /dev/null
+++ b/src/views/PIP/copyright_edit.vue
@@ -0,0 +1,745 @@
+
+
+
+
+
+
+
基础信息
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
附件上传
+
+
+
+
+ 上传
+
+
+ 支持PDF、Word、Excel格式,限10M内
+
+
+
+
+
+
+
+
+ 上传
+
+
+ 支持PDF、Word、Excel格式,限10M内
+
+
+
+
+
+
+
+
+ 上传
+
+
+ 支持PDF、Word、Excel格式,限10M内
+
+
+
+
+
+
+
+
+
+
+ 上传
+
+
+ 支持PDF、Word、Excel格式,限10M内
+
+
+
+
+
+
+
+
+ 上传
+
+
+ 支持PDF、Word、Excel格式,限10M内
+
+
+
+
+
+
+
+
+ 上传
+
+
+ 支持PDF、Word、Excel格式,限10M内
+
+
+
+
+
+
+
+
+ 上传
+
+
+ 支持PDF、Word、Excel格式,限10M内
+
+
+
+
+
+
+
+
+ 上传
+
+
+ 支持PDF、Word、Excel格式,限10M内
+
+
+
+
+
+
+
+
+
+ 申请结果
+
+ {{ item.name }}
+
+
+
+
费用信息
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/PIP/patent.vue b/src/views/PIP/patent.vue
new file mode 100644
index 0000000..4dc2c4f
--- /dev/null
+++ b/src/views/PIP/patent.vue
@@ -0,0 +1,421 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+
+
+
+
+
+ 新增专利
+ 下载专利交底模板
+
+
+
+
+
+
+ {{scope.row.name}}
+
+
+
+
+
+
+
+
+
+
+
+ 下载
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查看详情
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/PIP/patent_add.vue b/src/views/PIP/patent_add.vue
new file mode 100644
index 0000000..5ef64dd
--- /dev/null
+++ b/src/views/PIP/patent_add.vue
@@ -0,0 +1,866 @@
+
+
+
+
+
+
+
基础信息
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 支持png、jpg格式, 上限1M
+
+
+
+
+
+
+
+
+ 上传
+
+
+ 支持PDF、Word、Excel格式,限10M内
+
+
+
+
+
+
+
+
+
+
+ 查询结果
+
+ {{ item.name }}
+
+
+
+
+
+ 申请结果
+
+ {{ item.name }}
+
+
+
+
时间进度
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 费用信息
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/PIP/patent_edit.vue b/src/views/PIP/patent_edit.vue
new file mode 100644
index 0000000..4d37a36
--- /dev/null
+++ b/src/views/PIP/patent_edit.vue
@@ -0,0 +1,906 @@
+
+
+
+
+
+
+
基础信息
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 支持png、jpg格式, 上限1M
+
+
+
+
+
+
+
+
+ 上传
+
+
+ 支持PDF、Word、Excel格式,限10M内
+
+
+
+
+
+
+
+
+
+
+ 查询结果
+
+ {{ item.name }}
+
+
+
+
+
+ 申请结果
+
+ {{ item.name }}
+
+
+
+
时间进度
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 费用信息
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/PIP/quality_requisition.vue b/src/views/PIP/quality_requisition.vue
new file mode 100644
index 0000000..a256234
--- /dev/null
+++ b/src/views/PIP/quality_requisition.vue
@@ -0,0 +1,379 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+
+
+
+
+
+ 确认
+ 反确认
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 上传
+
+
+ 下载
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/PIP/trademark.vue b/src/views/PIP/trademark.vue
new file mode 100644
index 0000000..068a5da
--- /dev/null
+++ b/src/views/PIP/trademark.vue
@@ -0,0 +1,408 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+
+
+
+
+
+ 新增商标
+ 下载产品类目表
+
+
+
+
+
+
+ {{scope.row.name}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查看详情
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/PIP/trademark_add.vue b/src/views/PIP/trademark_add.vue
new file mode 100644
index 0000000..6148130
--- /dev/null
+++ b/src/views/PIP/trademark_add.vue
@@ -0,0 +1,747 @@
+
+
+
+
+
+
+
基础信息
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 支持png、jpg格式, 上限1M
+
+
+
+
+
+
+
+
+
+
+ 查询结果
+
+ {{ item.name }}
+
+
+
+
+
+ 申请结果
+
+ {{ item.name }}
+
+
+
+
时间进度
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 费用信息
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/PIP/trademark_edit.vue b/src/views/PIP/trademark_edit.vue
new file mode 100644
index 0000000..17f223e
--- /dev/null
+++ b/src/views/PIP/trademark_edit.vue
@@ -0,0 +1,771 @@
+
+
+
+
+
+
+
基础信息
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 支持png、jpg格式, 上限1M
+
+
+
+
+
+
+
+
+
+
+ 查询结果
+
+ {{ item.name }}
+
+
+
+
+
+ 申请结果
+
+ {{ item.name }}
+
+
+
+
时间进度
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 费用信息
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/agv/agv.scss b/src/views/agv/agv.scss
new file mode 100644
index 0000000..459c1dd
--- /dev/null
+++ b/src/views/agv/agv.scss
@@ -0,0 +1,67 @@
+/**/
+.m-16{margin: 16px;}
+.p-16{padding: 16px;}
+.m-t-16{ margin-top: 16px;}
+.m-b-16{ margin-bottom: 16px;}
+.m-l-16{ margin-left: 16px;}
+.m-r-16{ margin-right: 16px;}
+.m-r-8{ margin-right: 8px;}
+
+/**/
+.isGreen{
+ color: #00AA5B
+}
+.isYellow{
+ color: #FFAB00
+}
+.isBlue{
+ color: #4178D5
+}
+.isCyan{
+ color: #3CBFFF
+}
+.isRed{
+ color: #FF4747
+}
+.Cursor{
+ cursor: pointer;
+}
+.el-button+.el-button{
+ margin-left: 0!important;
+}
+.el-form-item{
+ margin-bottom: 10px!important;
+}
+:deep(.el-dialog__title){
+ font-weight: bold;
+ color: #303133;
+}
+:deep(.el-dialog__body){
+ padding-top: 16px!important;
+ padding-bottom: 16px!important;
+}
+.pagination {
+ text-align: right;
+}
+
+/**顶部图标**/
+.Files{
+ background: url('../../assets/daochu.png');
+ width: 14px;
+ height: 14px;
+ display: block;
+ background-size: cover;
+ float: left;
+ margin-right: 5px;
+}
+::v-deep(.top-box .el-button--small) {
+ font-size: 14px;
+}
+::v-deep(.top-box .el-button:hover,.top-box .el-button:focus){
+ background: #ecf5ff;
+ color: #409eff;
+}
+::v-deep(.top-box .el-button--primary:focus, .top-box .el-button--primary:hover){
+ background: #ecf5ff;
+ color: #409eff;
+}
\ No newline at end of file
diff --git a/src/views/agv/agvList.vue b/src/views/agv/agvList.vue
new file mode 100644
index 0000000..7980b3f
--- /dev/null
+++ b/src/views/agv/agvList.vue
@@ -0,0 +1,373 @@
+
+
+
+
+
+
+
+ 新增
+ 导出
+
+
+
+
+
+
+
+
+
+ 全部
+
+
+
+
+
+
+
+ 全部
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 重置
+ 搜索
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 空闲
+ 任务中
+ 充电中
+
+
+
+
+
+
+
+
+
+
+
+
+ 编辑
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/agv/hopperCar.vue b/src/views/agv/hopperCar.vue
new file mode 100644
index 0000000..7a1d0c2
--- /dev/null
+++ b/src/views/agv/hopperCar.vue
@@ -0,0 +1,383 @@
+
+
+
+
+
+
+
+ 新增
+ 导出
+
+
+
+
+
+
+
+
+
+ 全部
+
+
+
+
+
+
+
+ 全部
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 重置
+ 搜索
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 空闲
+ 任务中
+ 已装载
+
+
+
+
+
+
+
+
+
+
+
+ 编辑
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/agv/position.vue b/src/views/agv/position.vue
new file mode 100644
index 0000000..9b04690
--- /dev/null
+++ b/src/views/agv/position.vue
@@ -0,0 +1,541 @@
+
+
+
+
+
+
+
+ 新增
+
+ 导出
+
+
+
+
+
+
+
+
+
+ 全部
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 重置
+ 搜索
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查看明细
+
+
+
+
+
+
+
+
+
+
+
+ 空闲
+ 占用
+
+
+
+
+ 是
+ 否
+
+
+
+
+ 是
+ 否
+
+
+
+ {{ computedFn(scope.row.cart_title) }}
+
+
+
+ 空闲
+ 任务中
+ 已装载
+
+
+
+
+
+
+
+
+
+
+
+ 编辑
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 空料车停放点
+ 加入库存统计
+
+
+
+
+
+
+
+
+
+ 位置:{{ address }}
+ 料车:{{ cart }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/agv/stockDetail.vue b/src/views/agv/stockDetail.vue
new file mode 100644
index 0000000..edb1d3e
--- /dev/null
+++ b/src/views/agv/stockDetail.vue
@@ -0,0 +1,206 @@
+
+
+
+
+
+
+ 导出
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 重置
+ 搜索
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/agv/taskList.vue b/src/views/agv/taskList.vue
new file mode 100644
index 0000000..8e6b5cd
--- /dev/null
+++ b/src/views/agv/taskList.vue
@@ -0,0 +1,312 @@
+
+
+
+
+
+
+ 导出
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/gys/quality_requisition.vue b/src/views/gys/quality_requisition.vue
new file mode 100644
index 0000000..2fcce95
--- /dev/null
+++ b/src/views/gys/quality_requisition.vue
@@ -0,0 +1,483 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+
+
+
+
+
+ 确认
+ 反确认
+
+
+ 批量上传
+
+
+ 批量删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 上传
+
+
+ 下载
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/index/index.vue b/src/views/index/index.vue
new file mode 100644
index 0000000..abc969f
--- /dev/null
+++ b/src/views/index/index.vue
@@ -0,0 +1,850 @@
+
+
+
+
+
+
+ 保存修改
+
+
+
+
+ 导入
+
+
+ 导出
+ 日志
+ 同步ERP数据
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/index/log.vue b/src/views/index/log.vue
new file mode 100644
index 0000000..fe6ecda
--- /dev/null
+++ b/src/views/index/log.vue
@@ -0,0 +1,278 @@
+
+
+
+
+
+ 搜索
+ 重置
+
+
+ 导出
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ row.cost_change }}
+ {{ row.cost_change }}
+
+
+
+
+ {{ row.range }} %
+ {{ row.range }} %
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/index/oindex.vue b/src/views/index/oindex.vue
new file mode 100644
index 0000000..920d571
--- /dev/null
+++ b/src/views/index/oindex.vue
@@ -0,0 +1,768 @@
+
+
+
+
+
+
+ 保存修改
+
+
+
+ 导出
+ 日志
+ 同步ERP数据
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/login/index.vue b/src/views/login/index.vue
new file mode 100644
index 0000000..c47f29c
--- /dev/null
+++ b/src/views/login/index.vue
@@ -0,0 +1,50 @@
+
+
+
+
diff --git a/src/views/mold/add_mold.vue b/src/views/mold/add_mold.vue
new file mode 100644
index 0000000..0581560
--- /dev/null
+++ b/src/views/mold/add_mold.vue
@@ -0,0 +1,859 @@
+
+
+
+
+
+
diff --git a/src/views/mold/edit_mold.vue b/src/views/mold/edit_mold.vue
new file mode 100644
index 0000000..1f331b6
--- /dev/null
+++ b/src/views/mold/edit_mold.vue
@@ -0,0 +1,701 @@
+
+
+
+
+
+
diff --git a/src/views/mold/index.vue b/src/views/mold/index.vue
new file mode 100644
index 0000000..be7b539
--- /dev/null
+++ b/src/views/mold/index.vue
@@ -0,0 +1,414 @@
+
+
+
+
+
+
+
+
+
+
+ {{ row.matrix_sn }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ row.status_name }}
+ {{ row.status_name }}
+ {{ row.status_name }}
+ {{ row.status_name }}
+
+
+
+
+
+ 下载
+ 下载
+
+
+
+
+
+
+ {{ scope.row.remark }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/public/404.vue b/src/views/public/404.vue
new file mode 100644
index 0000000..a0175bf
--- /dev/null
+++ b/src/views/public/404.vue
@@ -0,0 +1,12 @@
+
+ 404
+
+
+
diff --git a/vue.config.js b/vue.config.js
new file mode 100644
index 0000000..2419ca3
--- /dev/null
+++ b/vue.config.js
@@ -0,0 +1,83 @@
+const settings = require('./src/settings')
+const path = require('path')
+const fs = require('fs') // 新增:用于HTTPS证书
+
+function resolve(dir) {
+ return path.join(__dirname, dir)
+}
+
+// 自动生成自签名证书(开发环境使用)
+function getHttpsConfig() {
+ try {
+ return {
+ https: {
+ key: fs.readFileSync('./cert/key.pem'),
+ cert: fs.readFileSync('./cert/cert.pem')
+ }
+ }
+ } catch (e) {
+ console.warn('未找到HTTPS证书,将使用HTTP协议')
+ return { https: false }
+ }
+}
+
+const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
+const Timestamp = new Date().getTime()
+const CompressionWebpackPlugin = require('compression-webpack-plugin')
+const productionGzipExtensions = ['js', 'css']
+const Components = require('unplugin-vue-components/webpack')
+const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
+
+module.exports = {
+ assetsDir: 'static',
+ runtimeCompiler: true,
+ css: {
+ requireModuleExtension: true,
+ sourceMap: process.env.NODE_ENV == 'development'
+ },
+
+ configureWebpack: {
+ name: settings.title,
+ resolve: {
+ extensions: ['.js', '.vue', '.json'],
+ alias: {
+ '@': resolve('src')
+ }
+ },
+ plugins: [
+ new UglifyJsPlugin({
+ uglifyOptions: {
+ compress: {
+ drop_console: process.env.NODE_ENV === 'production' // 只在生产环境移除console
+ }
+ }
+ }),
+ new CompressionWebpackPlugin({
+ filename: '[path].gz[query]',
+ algorithm: 'gzip',
+ test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'),
+ threshold: 10240,
+ minRatio: 0.8,
+ deleteOriginalAssets: false
+ }),
+ Components({
+ resolvers: [ElementPlusResolver()]
+ })
+ ],
+ output: {
+ filename: `js/[name].${Timestamp}.js`,
+ chunkFilename: `js/[name].${Timestamp}.js`
+ }
+ },
+
+ devServer: {
+ host: 'swt.costapi.f2b211.com',
+ port: 8080,
+ ...getHttpsConfig(), // 动态获取HTTPS配置
+ hot: true,
+ open: true,
+ headers: {
+ 'Access-Control-Allow-Origin': '*' // 解决跨域问题
+ }
+ }
+}
\ No newline at end of file