自由职业个人服务数字宣传手册一、实际应用场景描述场景自由职业者小林是一名UI/UX设计师同时提供品牌策划、插画设计、动效设计等多维服务。他每天都会收到大量咨询但传统方式存在诸多问题- 客户问你能做什么时他只能发一堆杂乱的作品集链接- 报价体系不透明每次都要重新沟通- 没有统一的专业形象展示显得不够正规- 优秀案例散落在各个平台客户难以全面了解实力目标用户设计师、摄影师、文案策划、程序员、咨询师等自由职业者核心价值打造一张数字名片集成服务介绍、作品展示、报价体系、联系方式于一体客户扫码即可全面了解提升转化率。二、引入痛点1. 形象碎片化作品在Behance简历在LinkedIn报价在微信客户需要跳转多个平台2. 信息不透明服务内容、交付标准、价格体系模糊导致反复沟通3. 缺乏信任感个人品牌展示不专业难以建立客户信任4. 更新不及时作品更新需要重新发送链接客户看到的是过时内容5. 转化率低传统PDF作品集枯燥乏味无法展现动态能力和服务流程三、核心逻辑讲解┌─────────────────────────────────────────────────────────────┐│ 数字宣传手册架构 │├─────────────────────────────────────────────────────────────┤│ 展示层(PWA) → 响应式界面/动画效果/离线访问 ││ ↓ ││ 业务层 → 服务管理/作品展示/预约系统/报价计算 ││ ↓ ││ 数据层(SQLite) → 服务数据/作品数据/客户数据/订单数据 ││ ↓ ││ 服务层 → 邮件通知/二维码生成/文件管理/缓存 │└─────────────────────────────────────────────────────────────┘核心流程1. 自由职业者注册并完善服务档案2. 添加服务项目、作品案例、报价体系3. 系统自动生成个性化数字手册4. 通过二维码/链接分享给潜在客户5. 客户浏览、咨询、预约数据实时同步四、代码模块化实现项目结构freelance_portfolio/├── app.py # 主应用入口├── config.py # 配置文件├── database.py # 数据库管理├── services/ # 业务服务层│ ├── __init__.py│ ├── portfolio_service.py # 作品集服务│ ├── booking_service.py # 预约服务│ ├── pricing_service.py # 报价服务│ └── notification_service.py # 通知服务├── templates/ # 展示模板│ ├── __init__.py│ ├── base_template.py # 基础模板│ ├── portfolio_template.py # 作品集模板│ └── service_template.py # 服务介绍模板├── static/ # 静态资源│ ├── css/│ ├── js/│ └── images/├── utils/ # 工具函数│ ├── __init__.py│ ├── qr_generator.py # 二维码生成│ └── helpers.py├── requirements.txt # 依赖包└── README.md # 项目说明1. 主应用入口 (app.py)自由职业个人服务数字宣传手册功能为自由职业者提供专业的数字名片服务技术栈Streamlit SQLite PWA Service Workerimport streamlit as stfrom datetime import datetime, timedeltaimport osimport jsonimport hashlibfrom database import DatabaseManagerfrom services.portfolio_service import PortfolioServicefrom services.booking_service import BookingServicefrom services.pricing_service import PricingServicefrom services.notification_service import NotificationServicefrom templates.base_template import BaseTemplatefrom templates.portfolio_template import PortfolioTemplatefrom templates.service_template import ServiceTemplatefrom utils.qr_generator import QRGeneratorfrom utils.helpers import format_currency, calculate_age, time_agofrom config import Config# PWA配置st.set_page_config(page_title自由职业数字手册,page_icon,layoutwide,initial_sidebar_statecollapsed,menu_items{Get Help: None,Report a bug: None,About: 自由职业个人服务数字宣传手册 v1.0})# 注入PWA支持def inject_pwa_support():注入PWA所需的HTML和JSpwa_html link relmanifest href/manifest.jsonmeta nameviewport contentwidthdevice-width, initial-scale1.0, maximum-scale1.0, user-scalablenometa nametheme-color content#6366f1meta nameapple-mobile-web-app-capable contentyesmeta nameapple-mobile-web-app-status-bar-style contentblack-translucentmeta nameapple-mobile-web-app-title content自由职业手册link relapple-touch-icon href/static/icons/icon-192.pngstyle/* PWA样式优化 */media (display-mode: standalone) {body {padding-top: env(safe-area-inset-top);padding-bottom: env(safe-area-inset-bottom);}}/* 触摸优化 */button, a {min-height: 44px;min-width: 44px;}/* 平滑滚动 */html {scroll-behavior: smooth;}/* 骨架屏动画 */keyframes shimmer {0% { background-position: -468px 0; }100% { background-position: 468px 0; }}.skeleton {animation: shimmer 1.5s infinite linear;background: linear-gradient(to right, #f6f7f8 8%, #edeef1 18%, #f6f7f8 33%);background-size: 800px 104px;}/stylest.markdown(pwa_html, unsafe_allow_htmlTrue)class FreelancePortfolioApp:主应用类def __init__(self):self.config Config()self.db DatabaseManager(self.config.DATABASE_PATH)self.portfolio_service PortfolioService(self.db)self.booking_service BookingService(self.db)self.pricing_service PricingService(self.db)self.notification_service NotificationService()self.base_template BaseTemplate()self.portfolio_template PortfolioTemplate()self.service_template ServiceTemplate()self.qr_generator QRGenerator()def run(self):运行主应用# 注入PWA支持inject_pwa_support()# 检查是否为访客模式if user_mode not in st.session_state:st.session_state.user_mode guest# 路由处理self._handle_routing()def _handle_routing(self):处理页面路由# 获取当前路径query_params st.query_paramscurrent_path query_params.get(page, home)if st.session_state.user_mode owner:# 所有者模式 - 管理后台self._render_owner_dashboard()else:# 访客模式 - 展示页面if current_path portfolio:self._render_portfolio_view()elif current_path services:self._render_services_view()elif current_path booking:self._render_booking_view()elif current_path contact:self._render_contact_view()else:self._render_home_view()def _render_owner_dashboard(self):渲染所有者仪表板st.title( 自由职业数字手册 - 管理后台)# 侧边栏导航with st.sidebar:st.header( 管理菜单)page st.radio(选择功能,[概览, 服务管理, 作品管理, 报价设置, 预约管理, 数据分析])st.markdown(---)st.info( 提示点击右上角二维码图标生成分享链接)if st.button(切换为访客模式, use_container_widthTrue):st.session_state.user_mode guestst.rerun()# 根据选择渲染不同页面if page 概览:self._render_overview()elif page 服务管理:self._render_service_management()elif page 作品管理:self._render_portfolio_management()elif page 报价设置:self._render_pricing_management()elif page 预约管理:self._render_booking_management()elif page 数据分析:self._render_analytics()def _render_overview(self):渲染概览页面st.header( 数据概览)# 获取统计数据stats self._get_dashboard_stats()# 统计卡片col1, col2, col3, col4 st.columns(4)with col1:st.metric(label 服务项目,valuestats[service_count],deltaf{stats[new_services_month]} 本月新增)with col2:st.metric(label 作品案例,valuestats[portfolio_count],deltaf{stats[new_portfolio_month]} 本月新增)with col3:st.metric(label 预约咨询,valuestats[booking_count],deltaf{stats[new_bookings_week]} 本周新增)with col4:st.metric(label️ 总浏览量,valuestats[total_views],deltaf{stats[views_this_week]} 本周浏览)st.markdown(---)# 快捷操作st.subheader(⚡ 快捷操作)col1, col2, col3 st.columns(3)with col1:if st.button(➕ 添加新服务, use_container_widthTrue):st.session_state.editing_service Nonest.switch_page(pages/service_edit.py)with col2:if st.button( 上传作品, use_container_widthTrue):st.switch_page(pages/portfolio_upload.py)with col3:if st.button( 生成分享链接, use_container_widthTrue):self._generate_share_link()# 最近活动st.markdown(---)st.subheader( 最近活动)recent_activities self._get_recent_activities()for activity in recent_activities:with st.container(borderTrue):col1, col2 st.columns([1, 4])with col1:st.write(activity[icon])with col2:st.write(f**{activity[title]}**)st.caption(f{activity[time_ago]} · {activity[description]})def _get_dashboard_stats(self):获取仪表板统计数据return {service_count: self.db.count_services(),new_services_month: self.db.count_new_services_this_month(),portfolio_count: self.db.count_portfolio_items(),new_portfolio_month: self.db.count_new_portfolio_this_month(),booking_count: self.db.count_bookings(),new_bookings_week: self.db.count_new_bookings_this_week(),total_views: self.db.get_total_views(),views_this_week: self.db.get_views_this_week()}def _get_recent_activities(self):获取最近活动列表activities self.db.get_recent_activities(limit5)icons {service_created: ,portfolio_added: ,booking_received: ,view_milestone: ️,contact_received: }for activity in activities:activity[icon] icons.get(activity[type], )activity[time_ago] time_ago(activity[created_at])return activitiesdef _render_service_management(self):渲染服务管理页面st.header(️ 服务管理)# 添加服务按钮if st.button(➕ 添加新服务, typeprimary):st.session_state.editing_service Nonest.switch_page(pages/service_edit.py)st.markdown(---)# 服务列表services self.db.get_all_services()if not services:st.info(暂无服务项目点击上方按钮添加第一个服务)returnfor service in services:with st.expander(f {service[name]} - ¥{service[base_price]}/起, expandedFalse):col1, col2 st.columns([2, 1])with col1:st.write(f**描述**{service[description]})st.write(f**交付周期**{service[delivery_time]})st.write(f**包含内容**{service[includes]})if service[features]:features json.loads(service[features])st.write(**特色服务**)for feature in features:st.write(f • {feature})with col2:st.write(f**状态**{ 上架 if service[is_active] else 下架})st.write(f**浏览量**{service[view_count]})btn_col1, btn_col2 st.columns(2)with btn_col1:if st.button(✏️ 编辑, keyfedit_{service[id]}, use_container_widthTrue):st.session_state.editing_service service[id]st.switch_page(pages/service_edit.py)with btn_col2:if st.button(️ 删除, keyfdelete_{service[id]}, use_container_widthTrue):self._delete_service(service[id])def _render_portfolio_management(self):渲染作品管理页面st.header( 作品集管理)# 上传作品按钮if st.button( 上传新作品, typeprimary):st.switch_page(pages/portfolio_upload.py)st.markdown(---)# 筛选条件col1, col2 st.columns(2)with col1:category_filter st.selectbox(按分类筛选,[全部] self.db.get_portfolio_categories())with col2:status_filter st.selectbox(按状态筛选,[全部, 已发布, 草稿])# 作品列表portfolios self.db.get_portfolio_items(categorycategory_filter if category_filter ! 全部 else None)if not portfolios:st.info(暂无作品点击上方按钮上传第一个作品)return# 瀑布流展示cols st.columns(2)for idx, item in enumerate(portfolios):with cols[idx % 2]:with st.container(borderTrue):# 作品预览if item[thumbnail]:st.image(item[thumbnail], use_column_widthTrue)# 作品信息st.write(f**{item[title]}**)st.caption(f {item[category]} · ️ {item[view_count]}次浏览)# 标签if item[tags]:tags json.loads(item[tags])tag_str .join([f{tag} for tag in tags[:3]])st.markdown(tag_str)# 操作按钮btn_col1, btn_col2, btn_col3 st.columns(3)with btn_col1:if st.button(️ 预览, keyfpreview_{item[id]}, use_container_widthTrue):st.session_state.preview_portfolio item[id]with btn_col2:if st.button(✏️ 编辑, keyfedit_{item[id]}, use_container_widthTrue):st.session_state.editing_portfolio item[id]st.switch_page(pages/portfolio_edit.py)with btn_col3:if st.button(️ 删除, keyfdelete_{item[id]}, use_container_widthTrue):self._delete_portfolio(item[id])def _render_pricing_management(self):渲染报价管理页面st.header( 报价体系设置)# 定价策略st.subheader( 定价策略)pricing_strategy self.db.get_pricing_strategy()with st.form(pricing_strategy_form):col1, col2 st.columns(2)with col1:strategy_type st.selectbox(定价模式,[固定报价, 按需报价, 套餐组合],index[fixed, custom, package].index(pricing_strategy[type]))base_hourly_rate st.number_input(基础时薪元/小时,min_value0,valuepricing_strategy.get(base_hourly_rate, 200))with col2:rush_multiplier st.slider(加急倍率,min_value1.0,max_value3.0,step0.1,valuepricing_strategy.get(rush_multiplier, 1.5))discount_threshold st.number_input(批量折扣门槛项目数,min_value1,valuepricing_strategy.get(discount_threshold, 3))if st.form_submit_button( 保存定价策略):self.db.update_pricing_strategy({type: strategy_type,base_hourly_rate: base_hourly_rate,rush_multiplier: rush_multiplier,discount_threshold: discount_threshold})st.success(定价策略已更新)st.markdown(---)# 价格计算器st.subheader( 价格计算器)st.write(模拟不同服务组合的价格计算)# 选择服务available_services self.db.get_all_services()selected_services st.multiselect(选择服务项目,[f{s[name]} (¥{s[base_price]}) for s in available_services])# 计算选项col1, col2 st.columns(2)with col1:quantity st.number_input(项目数量, min_value1, value1)with col2:is_rush st.checkbox(加急需求)if selected_services and st.button(计算总价, typeprimary):total self.pricing_service.calculate_total(selected_services,quantity,is_rush)st.success(f预估总价{format_currency(total)})# 详细 breakdownwith st.expander( 价格明细):st.write(**基础费用**)for service_str in selected_services:price float(service_str.split(¥)[1].rstrip()))st.write(f • {service_str.split( ()[0]}: {format_currency(price * quantity)})if is_rush:st.write(f**加急费用** ({(pricing_strategy.get(rush_multiplier, 1.5) - 1) * 100:.0f}%))st.write(f**总计**: {format_currency(total)})def _render_booking_management(self):渲染预约管理页面st.header( 预约咨询管理)# 预约列表bookings self.db.get_all_bookings(order_bycreated_at DESC)if not bookings:st.info(暂无预约咨询)return# 状态筛选status_filter st.selectbox(按状态筛选,[全部, 待处理, 已确认, 已完成, 已取消])filtered_bookings [b for b in bookingsif status_filter 全部 or b[status] status_filter]for booking in filtered_bookings:status_colors {pending: ,confirmed: ,completed: ,cancelled: }with st.container(borderTrue):col1, col2, col3 st.columns([2, 2, 1])with col1:st.write(f**{booking[client_name]}**)st.write(f {booking[client_email]})st.write(f {booking[client_phone] or 未提供})with col2:st.write(f {booking[service_type]})st.write(f {booking[preferred_date]} {booking[preferred_time]})st.write(f {booking[message][:50]}...)with col3:status booking[status]st.write(f{status_colors.get(status, ⚪)} **{status}**)st.write(time_ago(booking[created_at]))# 操作按钮if booking[status] pending:btn_col1, btn_col2 st.columns(2)with btn_col1:if st.button(✅ 确认, keyfconfirm_{booking[id]}, use_container_widthTrue):self._update_booking_status(booking[id], confirmed)with bt利用AI解决实际问题如果你觉得这个工具好用欢迎关注长安牧笛