| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651 |
- <template>
- <div>
- <div v-if="operateType === 'edit'" class="tool-btn" style="width: 800px; margin: 0 auto; text-align: right;">
- <el-button type="primary" v-print="'#applyDoc'">打印</el-button>
- </div>
- <div id="applyDoc" class="apply-form" v-loading="loading">
- <h3 class="page-title" style="height: 60px; line-height: 60px; margin: 0;">{{ teantData.tenantName }}</h3>
- <h3 class="page-title" style="margin: 5px 0 16px;">{{ getDocTile }}</h3>
- <div class="project-basic-info">
- <div class="info-row">{{ `研发项目名称:${ formData.xmmc || '' }` }}</div>
- <div class="info-row">{{ `项目负责人:${ getXmfzrName || '' }` }}</div>
- <div class="info-row">{{ `项目申请单位:${ xmsqdwName }` }}</div>
- <div class="info-row">{{ `项目执行期:${ getXmDateRange || '' }` }}</div>
- </div>
- <!-- 打印强制分页 -->
- <div style="page-break-after: always;"></div>
- <h3 class="page-title" style="margin: 24px 0 16px;">研发立项申请表</h3>
- <table>
- <tbody>
- <tr>
- <td class="doc-label">
- <span style="color: red; padding-right: 3px; font-size: 16px;">*</span>研发项目名称
- </td>
- <td class="doc-input">
- <el-input v-model="formData.xmmc" placeholder="请输入项目名称" :disabled="isEdit" />
- </td>
- <td class="doc-label">
- <span style="color: red; padding-right: 3px; font-size: 16px;">*</span>项目编号
- </td>
- <td class="doc-input">
- <el-input v-model="formData.xmbh" placeholder="请输入项目编号" :disabled="isEdit" />
- </td>
- </tr>
- <tr>
- <td class="doc-label">
- <span style="color: red; padding-right: 3px; font-size: 16px;">*</span>研发开始时间
- </td>
- <td class="doc-input">
- <el-date-picker
- v-model="formData.xmkssj"
- format="yyyy年MM月dd日"
- value-format="yyyy-MM-dd"
- placeholder="请选择日期"
- style="width: 100%"
- :disabled="isEdit"
- ></el-date-picker>
- </td>
- <td class="doc-label">
- <span style="color: red; padding-right: 3px; font-size: 16px;">*</span>研发结束时间
- </td>
- <td class="doc-input">
- <el-date-picker
- v-model="formData.xmjssj"
- format="yyyy年MM月dd日"
- value-format="yyyy-MM-dd"
- placeholder="请选择日期"
- style="width: 100%"
- :disabled="isEdit"
- ></el-date-picker>
- </td>
- </tr>
- <tr>
- <td class="doc-label">
- <span style="color: red; padding-right: 3px; font-size: 16px;">*</span>项目申请单位
- </td>
- <td colspan="3">
- <second-unit-cascader
- v-model="formData.xmsqdwid"
- :yearAndMonth="yearAndMonth"
- style="width: 100%;"
- :disabled="isEdit"
- @change="handleSecondUnitChange"
- >
- </second-unit-cascader>
- </td>
- </tr>
-
- <tr>
- <td class="doc-label">
- <span style="color: red; padding-right: 3px; font-size: 16px;">*</span>项目负责人
- </td>
- <td class="doc-input">
- <person-select v-model="formData.xmfzr" :yearAndMonth="xmStartDateYearAndMonth" valueKey="id" :disabled="isEdit" style="width: 100%" />
- </td>
- <td class="doc-label">
- <span style="color: red; padding-right: 3px; font-size: 16px;">*</span>研究类型
- </td>
- <td class="doc-input">
- <avue-select
- v-model="formData.yjlx"
- placeholder="请选择"
- :dic="studyTypeList"
- style="width: 100%"
- ></avue-select>
- </td>
- </tr>
- <tr>
- <td class="doc-label">
- <span style="color: red; padding-right: 3px; font-size: 16px;">*</span>项目来源
- </td>
- <td class="doc-input">
- <avue-select
- v-model="formData.xmly"
- placeholder="请选择"
- :dic="projectSourceList"
- style="width: 100%"
- ></avue-select>
- </td>
- <td class="doc-label">
- <span style="color: red; padding-right: 3px; font-size: 16px;">*</span>项目开展形式
- </td>
- <td class="doc-input">
- <avue-select
- v-model="formData.xmkzxs"
- placeholder="请选择"
- :dic="implementFormatList"
- style="width: 100%"
- ></avue-select>
- </td>
- </tr>
- <tr>
- <td class="doc-label">
- <span style="color: red; padding-right: 3px; font-size: 16px;">*</span>预期成果形式
- </td>
- <td class="doc-input">
- <avue-select
- multiple
- v-model="formData.yqcgxs"
- placeholder="请选择"
- :dic="expectedOutComeFormList"
- style="width: 100%"
- ></avue-select>
- </td>
- <td class="doc-label">
- <span style="color: red; padding-right: 3px; font-size: 16px;">*</span>项目技术经济目标
- </td>
- <td class="doc-input">
- <avue-select
- multiple
- v-model="formData.xmjsjjmb"
- placeholder="请选择"
- :dic="economicObjectivesList"
- style="width: 100%"
- ></avue-select>
- </td>
- </tr>
- <tr>
- <td class="doc-label">
- <span style="color: red; padding-right: 3px; font-size: 16px;">*</span>项目预算总额(万元)
- </td>
- <td class="doc-input">
- <!-- <el-input-number v-model="formData.xmysze" type="number" :min="0" controls-position="right" :disabled="isEdit" /> -->
- {{ getXmysze }}
- </td>
- <td class="doc-label">
- <span style="color: red; padding-right: 3px; font-size: 16px;">*</span>其中
- </td>
- <td class="doc-input">
- <div class="year-list">
- <div class="year-list-item" v-for="year of yearList" :key="year" :style="{ height: yearList.length == 1 ? '51px' : '32px', lineHeight: yearList.length == 1 ? '51px' : '32px' }">
- <div class="year" >{{ year }}</div>
- <div class="year-input">
- <input v-model="formData[year]" type="number" @input="handleYearInput" style="padding: 0 6px;" :disabled="isEdit" />
- </div>
- </div>
- </div>
- </td>
- </tr>
- </tbody>
- </table>
- <avue-form v-model="formData" :option="option" style="margin-top: 30px; padding: 0;">
- <template slot="lxpwLabel">
- <label>立项批文</label>
- <el-link type="primary" style="position: absolute; left: 220px; z-index: 1;">下载模板</el-link>
- </template>
- <template slot="lxbgLabel">
- <label>立项报告</label>
- <el-link type="primary" style="position: absolute; left: 220px; z-index: 1;">下载模板</el-link>
- </template>
- <template slot="qtzlLabel">
- <label>其他资料</label>
- <el-link type="primary" style="position: absolute; left: 220px; z-index: 1;">下载模板</el-link>
- </template>
- </avue-form>
- <p class="tip">注:可一次上传多个相关文件(文档、表格、图片等)。 支持格式:DOC, PDF, Excel, PNG, JPG, PPT 等。 请确保文件内容清晰有效。</p>
- <div class="btn-wrap printHide" style="text-align: center;">
- <el-button type="primary" style="width: 160px;" @click="handleSaveBtn">保存</el-button>
- </div>
- </div>
- </div>
- </template>
- <script>
- import secondUnitCascader from "@/components/second-unit-cascader";
- import personSelect from "@/components/person-select";
- import { getDictionary } from "@/api/system/dictbiz";
- import { getList as getTechnicanRosterList } from "@/api/basicResource/technicianRoster";
- import { add, update, getDetail } from "@/api/projectManage/projectList";
- import moment from "moment";
- import { deepClone } from "@/util/util";
- import Decimal from "decimal.js";
- import { mapGetters } from "vuex";
- import { getDetail as getTenantDetail } from '@/api/system/tenant';
- export default {
- components: {
- personSelect,
- secondUnitCascader
- },
- props: {
- // add or edit
- operateType: String,
- projectId: [String, Number]
- },
- data() {
- return {
- loading: false,
- formData: {},
- yearList: [],
- // 预算是否超出
- budgetIsExceed: false,
- // 项目负责人列表
- fzrList: [],
- // 研究类型数据字典
- studyTypeList: [],
- // 项目来源列表
- projectSourceList: [],
- // 开展形式
- implementFormatList: [],
- // 预期成果形式
- expectedOutComeFormList: [],
- // 经济目标
- economicObjectivesList: [],
- xmsqdwName: '',
- // 租户信息
- teantData: {}
- };
- },
- watch: {
- 'formData.xmkssj'(newVal) {
- this.yearList = this.getDateRangeYear(newVal, this.formData.xmjssj);
- let cMonth = newVal ? moment(newVal).format('yyyyMM') : '';
- if (cMonth != this.xmStartDateYearAndMonth) {
- this.xmStartDateYearAndMonth = cMonth;
- }
- },
- 'formData.xmjssj'(newVal) {
- this.yearList = this.getDateRangeYear(this.formData.xmkssj, newVal);
- },
- 'formData.xmysze'(newVal) {
- this.calcBudgetIsExceed(newVal);
- }
- },
- computed: {
- ...mapGetters(["userInfo"]),
- isEdit() {
- return this.operateType == 'edit';
- },
- // 获取项目预算总额
- getXmysze() {
- let total = new Decimal(0);
- this.yearList.forEach(year => {
- total = total.add (new Decimal(this.formData[year] || 0));
- });
- return total.toFixed(2);
- },
- option() {
- return {
- submitBtn: false,
- emptyBtn: false,
- submitText: '保存',
- menuBtn: false,
- column: [
- {
- label: "立项批文",
- prop: "lxpw",
- type: "upload",
- multiple: true,
- span: 24,
- disabled: this.isEdit,
- dataType: "object",
- propsHttp: {
- url: "link",
- name: "originalName",
- res: "data",
- },
- action: '/api/kd-resource/oss/endpoint/put-file',
- uploadPreview: (file, column, done) => {
- window.open(file.url, "_blank");
- return;
- },
- // rules: [{
- // required: true,
- // message: "请上传立项批文"
- // }]
- },
- {
- label: "立项报告",
- prop: "lxbg",
- type: "upload",
- multiple: true,
- span: 24,
- dataType: "object",
- propsHttp: {
- url: "link",
- name: "originalName",
- res: "data",
- },
- action: '/api/kd-resource/oss/endpoint/put-file',
- disabled: this.isEdit,
- uploadPreview: (file, column, done) => {
- window.open(file.url, "_blank");
- return;
- },
- // rules: [{
- // required: true,
- // message: "请上传立项报告"
- // }]
- },
- {
- label: "其他资料",
- prop: "qtzl",
- type: "upload",
- multiple: true,
- span: 24,
- action: '/api/kd-resource/oss/endpoint/put-file',
- disabled: this.isEdit,
- uploadPreview: (file, column, done) => {
- window.open(file.url, "_blank");
- return;
- },
- dataType: "object",
- propsHttp: {
- url: "link",
- name: "originalName",
- res: "data",
- },
- },
- ],
- }
- },
- getDocTile() {
- let tit = '研发项目资料';
- if (this.formData.xmmc) {
- return `${this.formData.xmmc}${tit}`;
- }
- return tit;
- },
- getXmfzrName() {
- // if (this.formData.xmfzr) {
- // let fzrObj = this.fzrList.find(item => item.value == this.formData.xmfzr);
- // return fzrObj ? fzrObj.label : "";
- // }
- return this.formData.xmfzrxm;
- },
- getXmDateRange() {
- if (this.formData.xmkssj && this.formData.xmjssj) {
- let xmkssj = moment(this.formData.xmkssj).format('yyyy年MM月DD日');
- let xmjssj = moment(this.formData.xmjssj).format('yyyy年MM月DD日')
- return `${xmkssj}至${xmjssj}`;
- }
- return `年 月 日至 年 月 日`;
- },
- yearAndMonth() {
- return !!this.formData.xmkssj ? moment(this.formData.xmkssj).format('yyyy') : '';
- }
- },
- mounted() {
- this.getTenantDetailFunc(this.userInfo.tenant_id);
- this.getDictList("study_type", "studyTypeList");
- this.getDictList("project_source", "projectSourceList");
- this.getDictList("implementation_format", "implementFormatList");
- this.getDictList("expected_outcome_form", "expectedOutComeFormList");
- this.getDictList("economic_objectives", "economicObjectivesList");
- if (this.projectId) {
- this.getProjectDetail(this.projectId);
- }
- },
- methods: {
- // 获取租户详情信息
- getTenantDetailFunc(tenantId) {
- getTenantDetail(tenantId).then(({ data }) => {
- if (data.code == 200) {
- this.teantData = data.data;
- }
- });
- },
- handleSecondUnitChange(val, nameArr) {
- this.xmsqdwName = nameArr.join('/');
- },
- getProjectDetail(xmId) {
- this.loading = true;
- getDetail({ id: xmId }).then(({ data }) => {
- this.loading = false;
- if (data.code == 200) {
- let beanData = { ...data.data };
- beanData.xmfzr = beanData.xmfzr.toString();
- beanData.yqcgxs = beanData.yqcgxs.split(",");
- beanData.xmjsjjmb = beanData.xmjsjjmb.split(",");
- beanData.lxpw = beanData.lxpw ? JSON.parse(beanData.lxpw) : [];
- beanData.lxbg = beanData.lxbg ? JSON.parse(beanData.lxbg) : [];
- beanData.qtzl = beanData.qtzl ? JSON.parse(beanData.qtzl) : [];
- beanData.xmyszemx = beanData.xmyszemx ? JSON.parse(beanData.xmyszemx) : [];
- beanData.xmyszemx.forEach(item => {
- beanData[item.year] = item.amount;
- });
- this.formData = { ...beanData };
- }
- }).catch(err => {
- this.loading = false;
- });
- },
- getDateRangeYear(sDate, eDate) {
- let yearArr = [];
- if (sDate && eDate) {
- let sDateYear = moment(sDate).format('yyyy');
- let dDateYear = moment(eDate).format('yyyy');
- for (let i=sDateYear; i<=dDateYear; i++) {
- yearArr.push(i);
- }
- }
-
- return yearArr;
- },
- getDictList(code, toListKey) {
- getDictionary({ code }).then((res) => {
- this[toListKey] = res.data.data.map((item) => {
- return { label: item.dictValue, value: item.dictKey };
- });
- });
- },
- handleYearInput(e) {
- this.calcBudgetIsExceed(this.formData.xmysze);
- },
- /**
- * 计算是否超出预算
- * @param total 预算总额
- */
- calcBudgetIsExceed(total) {
- let yearTotal = 0;
- let projectBudget = Number(total || 0);
- this.yearList.forEach(year => {
- let num = Number(this.formData[year] || 0);
- yearTotal += num;
- });
- if (yearTotal > projectBudget) {
- this.budgetIsExceed = true;
- } else {
- this.budgetIsExceed = false;
- }
- },
- /**
- * 获取人员花名册
- */
- // getTechnicanRosterListFunc(yearAndMonth) {
- // if (!yearAndMonth) {
- // this.fzrList = [];
- // return;
- // }
- // getTechnicanRosterList(1, 99999, { yearAndMonth }).then(res => {
- // if (res.data.success) {
- // this.fzrList = res.data.data.records.map(item => {
- // return { label: item.name, value: item.id };
- // });
- // }
- // });
- // },
- validForm() {
- let errorText = '';
- if (!this.formData.xmmc) {
- errorText = '请输入项目名称';
- } else if (/技改|技术改造|推广|打样|翻新|产业化|生产线|改造|年产|示范/g.test(this.formData.xmmc)) {
- errorText = '研发项目名称,不符合统计部门的命名要求';
- } else if (!this.formData.xmbh) {
- errorText = '请输入项目编号';
- } else if (!this.formData.xmsqdwid || !this.formData.xmsqdwid.length) {
- errorText = '请选择项目申请单位';
- } else if (!this.formData.xmkssj) {
- errorText = '请选择项目开始时间';
- } else if (!this.formData.xmjssj) {
- errorText = '请选择项目结束时间';
- } else if (!this.formData.yjlx) {
- errorText = '请选择研究类型'
- } else if (!this.formData.xmfzr) {
- errorText = '请选择项目负责人';
- } else if (!this.formData.xmly) {
- errorText = '请选择项目来源';
- } else if (!this.formData.xmkzxs) {
- errorText = '请选择项目开展形式';
- } else if (!this.formData.yqcgxs) {
- errorText = '请选择预期成果形式';
- } else if (!this.formData.xmjsjjmb) {
- errorText = '请选择项目技术经济目标';
- }
-
- else {
- this.yearList.forEach(year => {
- if (this.formData[year] === null || this.formData[year] === undefined || this.formData[year] === '') {
- errorText = `${year}年的预算不能为空`;
- }
- });
- }
- return errorText;
- },
- handleSaveBtn() {
- if (!this.operateType || this.operateType === 'add') {
- let errorText = this.validForm();
- if (errorText) {
- this.$message.error(errorText+'!');
- return;
- }
- let params = deepClone(this.formData);
- params.yqcgxs = params.yqcgxs ? params.yqcgxs.join(',') : '';
- params.xmjsjjmb = params.xmjsjjmb ? params.xmjsjjmb.join(',') : '';
- params.xmsqdwid = params.xmsqdwid ? params.xmsqdwid[params.xmsqdwid.length - 1] : '';
- params.lxbg = JSON.stringify(params.lxbg);
- params.lxpw = JSON.stringify(params.lxpw);
- params.qtzl = JSON.stringify(params.qtzl);
- let yearAmountList = [];
- this.yearList.forEach(year => {
- yearAmountList.push({ year: Number(year), amount: params[year] || 0 });
- delete params[year];
- });
- params.xmyszemx = JSON.stringify(yearAmountList);
- params.xmysze = this.getXmysze;
- this.addOrUpdate(params);
- } else if (this.operateType === 'edit') {
- let params = {
- xmId: this.formData.id,
- yjlx: this.formData.yjlx,
- xmly: this.formData.xmly,
- xmkzxs: this.formData.xmkzxs,
- yqcgxs: this.formData.yqcgxs.join(','),
- xmjsjjmb: this.formData.xmjsjjmb.join(',')
- };
- this.addOrUpdate(params);
- }
-
- },
- addOrUpdate(params) {
- let func = this.operateType === 'edit' ? update : add;
- this.loading = true;
- func(params).then(({ data }) => {
- this.loading = false;
- if (data.code == 200) {
- this.$emit('success', data.data);
- this.$message.success(this.operateType === 'edit' ? '修改成功!' : '保存成功!');
- }
- }).catch(err => {
- this.loading = false;
- });
- }
- },
- };
- </script>
- <style lang="scss" scoped>
- .page-title {
- text-align: center;
- font-size: 24px;
- }
- .project-basic-info .info-row {
- line-height: 26px;
- color: #666;
- }
- .apply-form {
- width: 800px;
- margin: 30px auto;
- }
- table {
- width: 100%;
- border: 1px solid #333;
- }
- .doc-label {
- width: 100px;
- text-align: center;
- padding: 6px;
- color: #777;
- font-size: 14px;
- }
- .doc-input {
- text-align: center;
- color: #333;
- }
- .el-input__inner {
- border: none;
- }
- tr td {
- border: 1px solid #333;
- }
- .year-list {
- &-item {
- display: flex;
- height: 32px;
- line-height: 32px;
- border-bottom: 1px solid #333;
- &:last-child {
- border-bottom: 0;
- }
- .year {
- width: 65px;
- border-right: 1px solid #333;
- }
- .year-input {
- input {
- width: 100%;
- height: 30px;
- border: 0;
- }
- }
- }
-
- }
- .red {
- color: red;
- }
- .tip {
- position: relative;
- top: 0;
- color: red;
- padding-left: 90px;
- margin-top: 0;
- font-size: 12px;
- }
- </style>
|